Android中如何实现后台执行定时任务
2016-03-01 21:04
1966 查看
Android中的定时任务一般有两种实现方式,一种是使用Java API里的Timer类,另一种是使用Android的Alarm机制。
这两种方式在多数情况下都能实现类似的效果,但Timer有一个明显的短板,它并不太适用与那些需要长期在后台运行的定时任务。As we know,为了能让电池更加耐用,每种手机都会有自己的休眠策略:比如手机不用的时候智能的断开wifi连接,根据光线强弱自动调节屏幕亮度,根据手机长时间无操作时自动的让CPU进入到休眠状态等,当进入休眠状态时,这就有可能导致Timer中的定时任务无法正常运行。而Alarn机制则不存在这种情况,它具有唤醒CPU的功能,即可以保证每次需要执行定时任务的时候CPU都能正常工作。需要注意的是,这里的唤醒CPU和唤醒屏幕不是同一个概念,不能混淆。
这里我们只说Alarm机制的方式,代码如下:
注意这里的
首先我们通过调用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。
当启动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>
本文参考资料:《第一行代码》
最后 :如果上面有不妥的地方,欢迎指出
这两种方式在多数情况下都能实现类似的效果,但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>
本文参考资料:《第一行代码》
最后 :如果上面有不妥的地方,欢迎指出
相关文章推荐
- android 无法连接真机调试
- Android中使EditText失去焦点,edittext禁止弹出键盘
- android用户界面开发
- Android粒子效果之雨
- Android中屏幕适配的理解
- 第一行代码学习笔记1——Android简介
- Android四大组件之Service
- Android 工程报错解决 Unable to resolve target 'android-17'
- Android配置文件中<uses-sdk>标签
- android:ellipsize属性
- android学习日记03-第一次创建项目错误解决
- Android中的单例模式
- Android 学习资料收集
- DOM解析XML文件
- android sdk下载代理设置
- 【资源】最新Android SDK_API_开发包_离线包_下载
- Android开发学习之路-SnackBar使用心得
- android多语言支持(Locale与Configuration)
- android Service
- Androd startActivities(Intent[] intents)启动的Activity生命周期