业精于勤荒于嬉,写文章练习表达能力,写代码练习基本工。
Android 后台精准定时任务
引子
在Android平台上,要实现一个后台任务定时执行,并不是什么难事,方案有很多:
- 使用handler的sendMessageDelayed或sendMessageAtTime方法。
- 使用Timer + TimerTask。
- 使用AlarmManger。
- 使用WorkManager(周期性任务间隔大于15分钟以上)
不过,方式1,2都依赖于实现的线程生命周期,应用进程一旦停止,定时任务无法执行,而且如果CPU处在休眠状态,这两种方式是无法唤醒的,更不用说android在6.0之后为了延长电池寿命增加对后台任务的一系列限制措施,点击参考官网《针对低电耗模式和应用待机模式进行优化》,定时任务无法保证精准执行。
总之,如果你的后台任务,需要在进程退出后也能定时执行,并且具备唤醒CPU的能力,使用AlarmManger是不二选择。
方案
AlarmManger+Service+BroadcastReceiver
问题1:设置一次性精准定时任务的API兼容性
构造一个Intent,告诉闹铃何时启动。
Calendar calendar_now = Calendar.getInstance();
Calendar calendar_target = Calendar.getInstance();
calendar_target.set(Calendar.HOUR_OF_DAY,hour);
calendar_target.set(Calendar.MINUTE,minute);
calendar_target.set(Calendar.SECOND,0);
calendar_target.set(Calendar.MILLISECOND,0);
//如果设置的时间已经过去了,推迟到第二天的这个时刻。
if(calendar_target.before(calendar_now)){
calendar_target.add(Calendar.DATE,1);
}
// 注册AlarmManager的定时服务
Intent intent=new Intent(context, BackUpAlarmService.class);
//获取闹钟服务
AlarmManager am = (AlarmManager)context.getSystemService(ALARM_SERVICE);
//8.0,必须启动前台服务,注意需要申请 android.permission.FOREGROUND_SERVICE权限
PendingIntent pendingIntent;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
pendingIntent = PendingIntent.getForegroundService(context, REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
}else{
pendingIntent = PendingIntent.getService(context, REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT)