AlarmManager详解

    xiaoxiao2021-03-26  15

    AlarmManager通常的用途就是用来开发手机闹钟,但实际上它的作用不止于此。它的本质是一个全局的定时器,AlarmManager可在指定时间或指定周期启动其他组件(包括Activity,Service,BroadcastReceiver)。

    1.为什么会有AlarmManager类? 随着Android版本越来越高,Android团队对Android之前版本的漏洞也在不断修复,比如:(通知)Notification、权限、后台流氓进程的kill等。Android中的定时任务一般有两种实现方式,一种是使用JAVA里提供的Timer类,一种是使用Android的Alarm机制。Timer有一个明显的缺点,不适合那些需要长期在后台运行的定时任务。为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android手机就会在长时间不操作的情况下自动让CPU进入到睡眠状态,这就导致Timer不能正常运行。而Alarm则具有唤醒CPU的功能,能保证大多数执行任务的时候CPU都能正常工作(有时候还需要配合一些“进程保活、后台拉起”等操作)。 2.AlarmManager类所有Public的方法: 以上是基于Android 6.0 API的Public方法。 3. 介绍几个AlarmManager类中常用到的方法。 (1)public void set(int type, long triggerAtMillis, PendingIntent operation) 该方法用于设置一次性闹钟或者可以设置一个定时任务。 第一个参数int type指定定时服务的类型,该参数接受如下值: ELAPSED_REALTIME 表示让定时任务的触发时间从系统开机开始算起,但不会唤醒CPU。如果系统处于休眠状态,这个定时任务不会触发。  ELAPSED_REALTIME_WAKEUP 表示让定时任务的触发时间从系统开机开始算起,但会唤醒CPU。如果系统处于休眠状态,系统会唤醒CPU,这个定时任务会触发。 RTC 指定当系统调用System.currentTimeMillis()方法返回的值(也就是说定时任务的触发时间从1970年1月1日0点开始算起,但不会唤醒CPU)执行定时任务,但是不会唤醒CPU,也就是说,如果系统处于休眠状态,这个定时任务不会触发。 RTC_WAKEUP 指定当系统调用System.currentTimeMillis()方法返回的值(也就是说定时任务的触发时间从1970年1月1日0点开始算起,但会唤醒CPU)执行定时任务,但是会唤醒CPU,也就是说,如果系统处于休眠状态,这个定时任务会触发。 第二个参数表示定时任务的触发时间,以毫秒为单位。 第三个参数PendingIntent operation表示定时器响应动作: PendingIntent operation:是定时器的执行动作,比如发送一个广播、给出提示等等。PendingIntent是Intent的封装类。如果是通过启动服务来实现定时器提示的话,PendingIntent对象的获取就应该采用Pending.getService(Context c,int i,Intentintent,int j)方法;如果是通过广播来实现定时器提示的话,PendingIntent对象的获取就应该采用PendingIntent.getBroadcast(Context c,inti,Intent intent,int j)方法;如果是采用Activity的方式来实现定时器提示的话,PendingIntent对象的获取就应该采用PendingIntent.getActivity(Context c,inti,Intent intent,int j)方法。如果这三种方法错用了的话,虽然不会报错,但是看不到定时器提示效果。 (2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi) 设置一个周期性执行的定时任务。第一个参数表示定时器类型,第二个参数表示定时器首次执行时间,第三个参数表示定时器两次执行的间隔时间,第四个参数表示定时器响应动作。 (3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi) 该方法也用于设置重复定时器,与第二个方法相似,不过其两个定时器执行的间隔时间不是固定的而已。它相对而言更省电一些,因为系统可能会将几个差不多的定时器合并为一个来执行,减少设备的唤醒次数。 第三个参数intervalTime为定时器间隔,内置的几个变量如下: INTERVAL_DAY: 设置闹钟,间隔一天 INTERVAL_HALF_DAY: 设置闹钟,间隔半天 INTERVAL_FIFTEEN_MINUTES:设置闹钟,间隔15分钟 INTERVAL_HALF_HOUR: 设置闹钟,间隔半个小时 INTERVAL_HOUR: 设置闹钟,间隔一个小时 注意:从Android 4.4 系统开始,Alarm任务的触发时间将会变得不准确,有可能会延迟一段时间后任务才能得到执行。这并不是Bug,而是系统在耗电性能方面进行的优化。系统会自动检测目前有多少Alarm任务存在,然后将触发时间接近的几个任务放在一起执行,这就可以大幅度地减少CPU被唤醒的次数,从而有效延迟电池的使用时间。 (4) 当然如果你要求Alarm任务的执行时间必须准确无误,Android仍然提供了解决方案。使用AlarmManager的public void setExact(int type, long triggerAtMillis, PendingIntent operation)方法代替set(int type, long triggerAtMillis, PendingIntent operation),基本上可以保证任务能够准时执行。参数的含义和set一样。 虽然Android的每个系统版本都在手机电量方面努力进行优化,不过一直没有解决后台服务泛滥、手机电量消耗过快的问题。于是在Android 6.0 系统中,谷歌加入了一种全新的Doze模式,从而可以极大幅度地延长手机电池的使用寿命。 什么是Doze模式? 当用户的设备是Android 6.0或以上系统的时候,如果该设备未插接电源,处于静止状态,且屏幕关闭了一段时间之后,就会进入到Doze模式。在Doze模式下,系统会对CPU、网络、Alarm等活动进行限制,从而延长了电池的使用寿命。具体的Doze模式还请读者自己去研究。 如果你真的有非常特殊的需求,需要Alarm(计时器)任务即使在Doze模式下也必须正常执行,Android还是提供了解决方法。调用AlarmManager的setAndAllowWhileIdle()或setExactAndAllowWhileIdle()方法使定时器即使在Doze模式下也能正常执行。 (5) public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) 在Doze模式下执行定时任务,可能不会准时执行你的定时任务,会把几个触发时间相同的任务放在一起执行。 (6) public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation)在Doze模式下执行任务,准时执行任务。 以上两个函数的区别和set()、setExact()区别是一样的。
    转载请注明原文地址: https://ju.6miu.com/read-500417.html

    最新回复(0)