轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處嘹悼,謝謝叛甫!
- GitHub: @Ricco
Android中的定時(shí)任務(wù)一般有兩種實(shí)現(xiàn)方式层宫,一種是使用Java API里提供的Timer類,一種是使用Android的Alarm機(jī)制其监。這兩種方式在多數(shù)情況下都能實(shí)現(xiàn)類似的效果萌腿,但Timer有一個(gè)明顯的短板,它并不太適用于那些需要長(zhǎng)期的后臺(tái)運(yùn)行的定時(shí)任務(wù)抖苦。為了能讓電池更加耐用毁菱,每種手機(jī)都有自己的休眠策略,Android手機(jī)就會(huì)在長(zhǎng)時(shí)間不操作的情況下自動(dòng)讓CPU進(jìn)入到睡覺狀態(tài)锌历,這就有可能導(dǎo)致Timer中的定時(shí)任務(wù)無(wú)法正常運(yùn)行贮庞。而Alarm可以保證大多數(shù)情況下需要執(zhí)行電池任務(wù)的時(shí)候CPU都能正常工作。
喚醒CPU和喚醒屏幕完全不是一個(gè)概念
從Android4.4系統(tǒng)開始究西,Alarm任務(wù)的觸發(fā)時(shí)間將會(huì)變的不準(zhǔn)確窗慎,有可能會(huì)延遲一段時(shí)間后任務(wù)才能得到執(zhí)行。這不是bug卤材,而是系統(tǒng)在耗電性方面進(jìn)行的優(yōu)化遮斥。系統(tǒng)對(duì)自動(dòng)檢測(cè)目前有多少Alarm任務(wù)存在,任何將觸發(fā)時(shí)間相近的幾個(gè)任務(wù)放在一起執(zhí)行扇丛,這就可以大幅度地減少CPU被喚醒的次數(shù)术吗,從而有效延長(zhǎng)電池的使用時(shí)間。
如果你需要Alarm任務(wù)的執(zhí)行時(shí)間必須準(zhǔn)確無(wú)誤帆精,Android仍然提供了解決方案较屿。使用AlarmManager的setExact()方法代替set()方法,要求API19,基本上可以保證任務(wù)能夠準(zhǔn)時(shí)執(zhí)行了卓练。
Alarm機(jī)制
借助AlarmManager類來(lái)實(shí)現(xiàn)的吝镣,和NotificationManager類似,都是通過(guò)調(diào)用Context的getSystemService()方法來(lái)獲取實(shí)例的昆庇。
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
定時(shí)任務(wù)末贾,設(shè)定一個(gè)任務(wù)在1分鐘后執(zhí)行,比如鬧鐘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拱撵,從系統(tǒng)開始算起,喚醒CPU
- ELAPSED_REALTIME表蝙,從系統(tǒng)開始算起拴测,不喚醒CPU
- RTC_WAKEUP,從1970.01.01日0點(diǎn)算起府蛇,喚醒CPU
- RTC集索,從1970.01.01日0點(diǎn)算起,不喚醒CPU
triggerAtMillis
觸發(fā)的時(shí)間,毫秒
- SystemClock.elapsedRealtime()獲取開機(jī)至今所經(jīng)歷時(shí)間的毫秒數(shù)
- System.currentTimeMillis()獲取1970.01.01日0點(diǎn)至今所經(jīng)歷時(shí)間的毫秒數(shù)
PendingIntent
- getService()
- getBroadcast()
后臺(tái)自動(dòng)更新
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() {
//邏輯操作
}
}