Android中的定时任务一般有两种实现方式,一种是使用Java API里的Timer类,另一种是使用Android的Alarm机制。
这两种方式在多数情况下都能实现类似的效果,但Timer有一个明显的短板,它并不太适用与那些需要长期在后台运行的定时任务。As we know,为了能让电池更加耐用,每种手机都会有自己的休眠策略:比如手机不用的时候智能的断开wifi连接,根据光线强弱自动调节屏幕亮度,根据手机长时间无操作时自动的让CPU进入到休眠状态等,当进入休眠状态时,这就有可能导致Timer中的定时任务无法正常运行。而Alarn机制则不存在这种情况,它具有唤醒CPU的功能,即可以保证每次需要执行定时任务的时候CPU都能正常工作。需要注意的是,这里的唤醒CPU和唤醒屏幕不是同一个概念,不能混淆。
这里我们只说Alarm机制的方式,代码如下:
public class AutoUpdateService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
// 每次服务启动的时候调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
doSomething();//这是定时所执行的任务
}
}).start();
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int anHour =8 * 60 * 60 * 1000;// 这是8小时的毫秒数 为了少消耗流量和电量,8小时自动更新一次
long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
Intent intent2 = new Intent(this, AutoUpdateReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent2, 0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);</span>
return super.onStartCommand(intent, flags, startId);
}
注意这里的
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);此处实现了定时任务。
首先我们通过调用Context的getSystemService()方法来获取AlarmManager的实例,这里需要传入的参数是ALARM_SERVICE.
接下来调用AlarmManager的set()方法就可以设置一个定时任务了,比如设定一个任务在5秒钟后执行,就可以写成 long triggerAtTime = SystemClock.elapsedRealtime() + 5*1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
其中第一个参数是一个整形参数,用于指定AlarmManager的工作类型,有四种值可以选,分别是 ELAPSED_REALTIME、ELAPSED_REALTIME_WAKEUP、RTC和RTC_WAKEUP。其中ELAPSED_REALTIME表示让定时任务的触发时间从系统开机开始算起,但不会唤醒CPU。ELAPSED_REALTIME_WAKEUP同样表示让定时任务的触发时间从系统开机开始算起,但会唤醒CPU。RTC表示让定时任务的触发时间从1970年1月1日0点开始算起,但不会唤醒CPU。RTC_WAKEUP同样表示让定时任务的触发时间从1970年1月1日0点开始算起,但会唤醒CPU。使用SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数,使用System.currentTimeMillis()方法可以获取到1970年1月1日0点至今所经历时间的毫秒数。
然后看一下第二个参数,这个参数就好理解多了,就是定时任务触发的时间,以毫秒为单位。如果第一个参数使用的是ELAPSED_REALTIME或ELAPSED_REALTIME_WAKEUP,则这里传入开机至今的时间再加上延迟执行的时间。如果第一个参数使用的是RTC或RTC_WAKEUP,则这里传入1970年1月1日0点至今的时间再加上延迟执行的时间。
第三个参数是一个PendingIntent,这里我们一般会调用getBroadcast()方法来获取一个能够执行广播的PendingIntent。这样当定时任务被触发的时候,广播接收器的onReceive()方法就可以得到执行。当然设定一个任务在10秒钟后执行还可以写成:
longtriggerAtTime = System.currentTimeMillis() + 10 * 1000;
manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime, pendingIntent);
然后创建PendingIntent指定处理定时任务的广播接收器AutoUpdateReceiver。
import service.AutoUpdateService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AutoUpdateService.class);
context.startService(i);
}
}
当启动AutoUpdateService后,就会在onStartCommand()方法里设定一个定时任务,这样每8个小时AutoUpdateReceiver的onReceive()方法就会得到执行,这样就又会启动AutoUpdateService服务,形成了永久的循环,保证服务每隔一段时间就会启动一次,这样就完成了一个长期在后台运行的服务。
我们在哪里启动服务呢,这要看具体的情况了,一般的话,当我们打开程序的时候启动一次就好了
比如写在Activity的onCrete()方法里
Intent intent =new Intent(this,AutoUpdateService.class);
startService(intent);
最后,既然我们用到了服务和广播接收器,那么就得在AndroidManifest.xml中注册才行。
<service android:name="service.AutoUpdateService" ></service>
<receiver android:name="receiver.AutoUpdateReceiver" ></receiver>
本文参考资料:《第一行代码》
最后 :如果上面有不妥的地方,欢迎指出