转载请注明原创出处,谢谢!
- GitHub: @Ricco
Android中的定时任务一般有两种实现方式,一种是使用Java API里提供的Timer类,一种是使用Android的Alarm机制。这两种方式在多数情况下都能实现类似的效果,但Timer有一个明显的短板,它并不太适用于那些需要长期的后台运行的定时任务。为了能让电池更加耐用,每种手机都有自己的休眠策略,Android手机就会在长时间不操作的情况下自动让CPU进入到睡觉状态,这就有可能导致Timer中的定时任务无法正常运行。而Alarm可以保证大多数情况下需要执行电池任务的时候CPU都能正常工作。
唤醒CPU和唤醒屏幕完全不是一个概念
从Android4.4系统开始,Alarm任务的触发时间将会变的不准确,有可能会延迟一段时间后任务才能得到执行。这不是bug,而是系统在耗电性方面进行的优化。系统对自动检测目前有多少Alarm任务存在,任何将触发时间相近的几个任务放在一起执行,这就可以大幅度地减少CPU被唤醒的次数,从而有效延长电池的使用时间。
如果你需要Alarm任务的执行时间必须准确无误,Android仍然提供了解决方案。使用AlarmManager的setExact()方法代替set()方法,要求API19,基本上可以保证任务能够准时执行了。
Alarm机制
借助AlarmManager类来实现的,和NotificationManager类似,都是通过调用Context的getSystemService()方法来获取实例的。
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
定时任务,设定一个任务在1分钟后执行,比如闹钟1分钟响铃。
long triggerAtMillis= SystemClock.elapsedRealtime() + 60 * 1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, pendingIntent);
void set(int type, long triggerAtMillis, PendingIntent operation)
type
工作类型
- ELAPSED_REALTIME_WAKEUP,从系统开始算起,唤醒CPU
- ELAPSED_REALTIME,从系统开始算起,不唤醒CPU
- RTC_WAKEUP,从1970.01.01日0点算起,唤醒CPU
- RTC,从1970.01.01日0点算起,不唤醒CPU
triggerAtMillis
触发的时间,毫秒
- SystemClock.elapsedRealtime()获取开机至今所经历时间的毫秒数
- System.currentTimeMillis()获取1970.01.01日0点至今所经历时间的毫秒数
PendingIntent
- getService()
- getBroadcast()
后台自动更新
public class AutoUpdateService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
update();
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
long triggerAtMillis = SystemClock.elapsedRealtime() + 6 * 60 * 60 * 1000;
Intent i = new Intent(this, AutoUpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, i, 0);
manager.cancel(pendingIntent);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, pendingIntent);
return super.onStartCommand(intent, flags, startId);
}
private void update() {
//逻辑操作
}
}