美文网首页Android基础
Android各版本AlarmManager使用

Android各版本AlarmManager使用

作者: Candy有雪吃 | 来源:发表于2019-02-27 11:38 被阅读2次

一、长时间定时任务,比较Timer、Hnadler、AlarmManager

Timer,有一个明显的问题,它并不太适合用于需要长期在后台运行的定时任务。我们都知道,为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android手机就会在长时间不操作的情况下自动让CPU进入睡眠状态,这就有可能导致Timer中的定时任务无法正常运行。

Hnadler,Handler的postDelay方法也可以实现定时操作,它同样也是不靠谱的,因为默认Hnadler依赖于线程(main线程或者子线程),所以只要进程被杀死,所有相关的线程都被晒死,所以handler中的定时操作就无效了。Timer也一样,因为Timer实际上是另起一个子线程,进程被杀,子线程当然也被杀了。

AlarmManager,它通过pendingIntent具有唤醒未启动进程的功能,即可以保证每次需要执行定时任务的时候CPU都能正常工作。但是当设备关机和重启后,闹钟将被清除。

二、使用AlarmManager

通过上面的分析,我们可以明显感受到AlarmManager在长时间定时任务中的优点,下面来说说它的用法(由于AlarmManager在不同的Android版本都有修改,所以如果想使用AlarmManager需要处理不同版本问题

1. 初始化PendingIntent

Intent intent = new Intent(ALARM_ACTION_CODE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
                REQUEST_CODE, intent,
                PendingIntent.FLAG_CANCEL_CURRENT);
  • PendingInent,Intent 更加倾向于去立即执行某个动作,而 PendingIntent 更加倾向于在某个合适的时机去执行某个动作。所以,也可以把 PendingIntent 简单地理解为延迟执行的 Intent。
    getActivity()方法、getBroadcast()方法、getService()方法

  • ALARM_ACTION_CODE,Intent传递给广播接收者的action,自己设定。

  • PendingIntent.FLAG_CANCEL_CURRENT,pendingIntent的第四个参数如果直接传0,表示你不打算通过任何一个flag来控制pendingIntent的创建。下面说说pendingIntent提供的四种flag:

    1. FLAG_CANCEL_CURRENT,如果要创建的PendingIntent已经存在了,那么在创建新的PendingIntent之前,原先已经存在的PendingIntent中的intent将不能使用。
    2. FLAG_NO_CREATE,如果要创建的PendingIntent尚未存在,则不创建新的PendingIntent,直接返回null。
    3. FLAG_ONE_SHOT,相同的PendingIntent只能使用一次,且遇到相同的PendingIntent时不会去更新PendingIntent中封装的Intent的extra部分的内容。
    4. FLAG_UPDATE_CURRENT,如果要创建的PendingIntent已经存在了,那么在保留原先PendingIntent的同时,将原先PendingIntent封装的Intent中的extra部分替换为现在新创建的PendingIntent的intent中extra的内容。

    那么如何比较新老pendingIntent是否相同呢?
    PendingIntent重写了equals方法,判定两个PendingIntent是否相同的依据是它封装的Intent是否“相同”和requestCode是否一致。

    注意,“相同”上打了引号,这是因为在比较PendingIntent中封装的intent时是否相同时,使用的是Intent的filterEquals方法,该方法认为只要两个intent具有相同的action、data、categories、components、type和flags(这个flags是intent的flags)就认为它们两个是“相同”的,filterEquals是不会比较两个intent的extra部分和内存地址的。

    另外需要注意的是,Intent并没有重写equals方法,所以如果使用Intent的equals方法比较两个intent对象的话,比较的是两个对象的内存地址。

2. 初始化AlarmManager

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

3. 设置重复执行的定时任务

这个就要区分Android版本了

4.4之前,SDK API < 19

alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime(), TIME_INTERVAL, pendingIntent);

alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
                System.currentTimeMillis(), TIME_INTERVAL, pendingIntent);
  • 第一个参数表示闹钟类型:一般为 AlarmManager.ELAPSED_REALTIME_WAKEUP或者 AlarmManager.RTC_WAKEUP。它们之间的区别就是前者是从手机开机后的时间,包含了手机睡眠时间;而后者使用的就是手机系统设置中的时间。所以如果设置为AlarmManager.RTC_WAKEUP ,那么可以通过修改手机系统的时间来提前触发定时事件。另外,对于相似的 AlarmManager.ELAPSED_REALTIMEAlarmManager.RTC 来说,它们不会唤醒 CPU 。所以使用的频率较少;
  • 第二个参数表示任务首次执行时间:与第一个参数密切相关。第一个参数若为 AlarmManager.ELAPSED_REALTIME_WAKEUP ,那么当前时间就为 SystemClock.elapsedRealtime() ;若为 AlarmManager.RTC_WAKEUP ,那么当前时间就为 System.currentTimeMillis()
  • 第三个参数表示两次执行的间隔时间:这个参数没什么好讲的,一般为常量;
  • 第四个参数表示对应的响应动作:一般都是去发送广播,然后在广播接收 onReceive(Context context, Intent intent) 中做相关操作。

4.4之后,6.0之前, SDK API >= 19, SDK API < 23

alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,                
                SystemClock.elapsedRealtime(), pendingIntent);

查阅 Android 官网中关于 Android 4.4 API 会看到如下几句话:

图片.png

6.0之后的版本,SDK API >= 23

alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,                
                SystemClock.elapsedRealtime(), pendingIntent);

再次打开 Android 官网中关于 Android 6.0 变更 ,发现在 Android 6.0 中引入了低电耗模式和应用待机模式。然后接着往下看 对低电耗模式和应用待机模式进行针对性优化 ,发现会有下面一段话:

图片.png

相关文章

网友评论

    本文标题:Android各版本AlarmManager使用

    本文链接:https://www.haomeiwen.com/subject/vnkxuqtx.html