之前我們已經簡單說了定時任務的幾種方式,詳見:定時任務
今天我們來看看如何用Android的Alarm機制來做定時任務的,還是之前的定時任務:從1到10每隔1秒進行數數,廢話不多說,直接上代碼:
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
LogUtil.loge("創建");
}
@Override
public void onDestroy() {
super.onDestroy();
LogUtil.loge("銷毀");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
long count = intent.getLongExtra("count", 0);
if(count<10){
count++;
LogUtil.loge("count: " + count);
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
long triggerAtTime = SystemClock.elapsedRealtime() + 1000;
intent.putExtra("count",count);
//因使用更換了intent中的count值,這里需要用FLAG_UPDATE_CURRENT這個Flag
PendingIntent pendingIntent=PendingIntent.getService(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
//Android 4.4 版本開始,Alarm 任務的觸發時間將會變得不準確,如果對時間要求嚴格,可用setExact()方法來替代set()
if (Build.VERSION.SDK_INT >=19){
manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);
} else{
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);
}
}
}
}
}
我們是直接利用IntentService來做具體定時任務的實現,相關注意要點注釋已經說明了,然后調用方法也非常簡單,如下:
Intent intent=new Intent(context,MyIntentService.class);
startService(intent);
這樣確實能夠實現定時任務,但后來筆者閱讀了相關文檔,發現AlarmManager還支持設置周期性定時任務,那么,上面的代碼肯定是可以進行優化的,畢竟沒必要每次執行完定時任務后,再重新啟動一個定時任務,直接用周期性定時任務會更合理些,說改就改,還是直接上代碼:
public class MyIntentService2 extends IntentService {
private static long count=0;
public MyIntentService2() {
super("MyIntentService2");
}
@Override
public void onCreate() {
super.onCreate();
LogUtil.loge("創建");
}
@Override
public void onDestroy() {
super.onDestroy();
LogUtil.loge("銷毀");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
if(count<10){
count++;
LogUtil.loge("count: " + count);
}else {
//關閉Alarm
AlarmManager manager = (AlarmManager) Global.getContext().getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(Global.getContext(),MyIntentService2.class);
PendingIntent pendingIntent=PendingIntent.getService(Global.getContext(),0,i,PendingIntent.FLAG_UPDATE_CURRENT);
if(pendingIntent!=null){
manager.cancel(pendingIntent);
}
LogUtil.loge("關閉Alarm");
}
}
}
}
再看看調用的方法,代碼如下:
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
long triggerAtTime = SystemClock.elapsedRealtime();
Intent intent=new Intent(context,MyIntentService2.class);
PendingIntent pendingIntent=PendingIntent.getService(Global.getContext(),0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime,1000, pendingIntent);
注意到我們用的是setInexactRepeating,據說這個方法優化了很多,最主要的是省電。同時,既然是周期性定時任務,那么,當周期性定時任務完成之后,請注意關閉Alarm。