Android定时任务采用AlarmManager来实现,兼容8.0系统

最近项目中需要实现定时任务,安卓实现定时任务的方式有不少

短期的定时任务可以采用前三种,要实现长期精确的定时任务就看第四种AlarmManager实现

1.通过Handler + Thread 的方式

        这种方式是通过循环加线程sleep来实现

 new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){ 
                    try {
                        Thread.sleep(1000); //休眠一秒
                        mHanler.sendEmptyMessage(TIMER);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

 2.通过Handler+message

        这里通过发送延时消息不停循环调用

 private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case TIMER:
                    //在这里去执行定时操作逻辑
                    
                    if (flag) {
                        Message message = mHandler.obtainMessage(TIMER);
                        mHandler.sendMessageDelayed(message, 1000);
                    }
                    break;
                default:
                    break;
            }
        }
    };

 3.通过TimerTask

 Timer timer = new Timer();

    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            mHandler.sendEmptyMessage(TIMER);
        }
    };

timer.schedule(task, 1000, 1000);   

4.采用AlarmManger实现长期精确的定时任务

使用场景:公司项目就要求每一天凌晨执行一下检查更新App的任务,类似的情况还有很多

AlarmManger 设置定时任务的方法有这么几个

set(int type,long startTime,PendingIntent pi);//一次性
setExact(int type, long triggerAtMillis, PendingIntent operation)//一次性的精确版
setRepeating(int type,long startTime,long intervalTime,PendingIntentpi);//精确重复
setInexactRepeating(int type,long startTime,longintervalTime,PendingIntent pi);//非精确,降低功耗

常见使用方式:利用AlarmManger+Service+BarocastReceiver来实现可唤醒cpu,甚至实现精确定时,适用于配合service在后台执行一些长期的定时行为

startTime:闹钟的第一次执行时间,以毫秒为单位,一般使用当前时间。
intervalTime:执行时间间隔。
PendingIntent :PendingIntent用于描述Intent及其最终的行为.,这里用于获取定时任务的执行动作。

这些Api使用起来还是非常简单的,但是问题在于版本的兼容。

需要特别注意的是:

当执行任务唤醒的时候PendingIntent,在8.0版本之后获取方式不同

启动服务不在是startService() 而是startForegroundService()

	if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
			pendingIntent = PendingIntent.getForegroundService(context, requestCode,
					intent, PendingIntent.FLAG_UPDATE_CURRENT);
		}else{
			pendingIntent = PendingIntent.getService(context, requestCode,
					intent, PendingIntent.FLAG_UPDATE_CURRENT);
		}

这是由于在8.0及之后,系统对后台服务运行做了限制,如果一个后台服务没有设置前台通知startForeground,那么系统将在5s内杀死服务,并且报出ANR。这么做是为了防止应用在后台偷偷的干着不可告人的事,后台服务一多不仅卡顿还增加了功耗,消耗了流量。如果要在后台做事,google官方推荐使用jobSchedule,这个jobService实际上也是继承自Service,只对Service进行了包装,当然包装之后jobScheduler的任务都交由JobSchedulerService系统服务去调度。

jobScheduler的优点

1.把任务整合起来,等到充电状态或者 Wifi 连接情况下进行执行,充电时候就不会在乎耗电量, Wifi 连接情况下比蜂窝网络省电

2.在系统待机的时候,把任务整合到一起,一定时间批量处理,可以避免多次的唤醒 CPU,使 CPU 得不到休息,造成耗电

综合上面的定时方案的优缺点,及项目实际情况最终考虑采用AlarmManger来实现定时任务。

有不对的地方还望指出,欢迎拍砖

 

展开阅读全文

没有更多推荐了,返回首页