Android Doze模式下Alarm定时任务实现流程详解
作者:Tsuky1
定时任务
Timer不太适合那些需要长期在后台运行的定时任务,因为每个手机都有自己的休眠策略,Android手机长时间不操作就会导致Timer定时任务无法执行,而Alarm具有唤醒CPU的功能,能保证大多数情况下,执行定时任务的时候CPU能正常工作。
AlarmManager manager= (AlarmManager) getSystemService(Context.ACTIVITY_SERVICE); PendingIntent pendingIntent; /** * SystemClock.elapsedRealtime():获取到系统开机至今所经历的毫秒数 * System.currentTimeMillis():1970-1-1 0:00至今所经历的毫秒数 * * ELAPSED_REALTIME:定时任务触发从系统开机算起 但不唤醒CPU * ELAPSED_REALTIME_WAKEUP:定时任务触发从系统开机算起 唤醒CPU * RTC:从1970-1-1 0:00算起 不唤醒CPU * RTC_WAKEUP:从1970-1-1 0:00算起 唤醒CPU */ /**pendIntent:一般会调用getSrervice或getBroadCast 来获取一个能够执行服务或广播的pendingIntent, 这样才能保证在任务被触发的时候, 服务里的onStartCommand()和onRecive()方法被执行 */ long time= SystemClock.elapsedRealtime()+10*1000;//10秒钟后执行任务 manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,time,pendingIntent);
那么要实现一个长时间在后台定时运行的服务该怎么做?
创建一个MyService类
package com.example.test; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.SystemClock; import androidx.annotation.Nullable; public class MyService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { //TODO } }).start(); AlarmManager manager= (AlarmManager) getSystemService(ALARM_SERVICE); int time=60*60*1000;//一小时 long triggerAtTime= SystemClock.elapsedRealtime()+time; Intent intent1=new Intent(this,MyService.class); PendingIntent pendingIntent=PendingIntent.getService(this,0,intent1,0); manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent); return super.onStartCommand(intent, flags, startId); } }
可以看到先创建了一个子线程在这里执行具体的操作任务,然后就是alarm机制,定义任务触发一小时后,再使用PendingIntent指定定时处理任务的MyService,最后调用set方法设定完成。
这样就将一个长时间在后台定时运行的服务设定成功了,一旦启动了MyService,就会在onStartCommand()方法里设定一个定时任务,这样一小时后将会再次启动MyService,每隔一小时就会执行一次。
然后去使用,在manifest文件中注册服务
<service android:name=".MyService"/>
在使用的地方调用下面代码就可以。
Intent intent=new Intent(context,MyService.class); context.startService(intent);
但是在Android4.4后,定时任务变得不准确,会延时一段时间才能执行,那是因为系统在耗电方面进行的优化,系统会检测有多少Alarm任务存在,将触发时间相近的几个任务放在一起执行,这样可以大幅度的减少CPU被唤醒的次数,演唱电池的使用时长。也可以使用setExact()来代替set()方法,可以保证任务能够准时执行。
Doze模式
如果设备未充电,并处于静止状态,且屏幕关闭了一段时间后,就能进入到Doze模式。
在Doze模式下,系统会对CPU、网络、Alarm等活动进行限制,从而延长电池的使用寿命。当然,系统并不会一直处于Doze模式,而是会间歇性地退出Doze模式一小段时间,在这段时间中,应用就可以去完成它的同步操作、Alarm任务等。
Doze模式下受限制的功能:
- 网络访问被禁止。
- 系统忽略唤醒CPU或者屏幕操作。
- 系统不再执行WIFI扫描。
- 系统不再执行同步服务。
- Alarm任务将会在下次退出Doze模式的时候执行。
在Doze模式下, Alarm任务会变得相当不准,当然这种情况下对Alarm的要求也并不高,如果有特殊的要求,调用AlarmManager的setAndAllowWhileIdle()或者setExactAndAllowWhileIdle()方法就能让定时任务正常执行,和set()与setExact()的区别是一样的。
到此这篇关于Android Doze模式下Alarm定时任务实现流程详解的文章就介绍到这了,更多相关Android Alarm定时任务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!