Android下的定时任务
Android中的定时任务一般有两种实现方式,一种是使用JavaAPI里的Timer类,另一种是使用android的Alarm机制。
这两种方式在多数情况下都能实现类似的效果,但Timer有一个明显的短板,它并不太适用与那些需要长期在后台运行的定时任务。As we know,为了能让电池更加耐用,每种手机都会有自己的休眠策略:比如手机不用的时候智能的断开wifi连接,根据光纤强弱自动调节屏幕亮度,根据手机长时间无操作时自动的让CPU进入到休眠状态等,当进入休眠状态时,这就有可能导致Timer中的定时任务无法正常运行。而Alarn机制则不存在这种情况,它具有唤醒CPU的功能,即可以保证每次需要执行定时任务的时候CPU都能正常工作。需要注意的是,这里的唤醒CPU和唤醒屏幕不是同一个概念,不能混淆。
Timer类
第一个参数就是TimerTask类型的对象,我们实现TimerTask的run()方法就是要周期执行的一个任务;
第二个参数有两种类型,第一种是long类型,表示多长时间后开始执行,另一种是Date类型,表示从那个时间后开始执行;
第三个参数就是执行的周期,为long类型。
schedule方法还有一种两个参数的执行重载,第一个参数仍然是TimerTask,第二个表示为long的形式表示多长时间后执行一次,为Date就表示某个时间后执行一次。
//true 说明这个timer以daemon方式运行(优先级低,程序结束timer也自动结束)
java.util.Timer timer = new java.util.Timer(true);
TimerTask task = new TimerTask() {
public void run() {
//每次需要执行的代码放到这里面。
}
}; //以下是几种调度task的方法: //time为Date类型:在指定时间执行一次。
timer.schedule(task, time); //firstTime为Date类型,period为long,表示从firstTime时刻开始,每隔period毫秒执行一次。
timer.schedule(task, firstTime, period); //delay 为long类型:从现在起过delay毫秒执行一次。
timer.schedule(task, delay); //delay为long,period为long:从现在起过delay毫秒以后,每隔period毫秒执行一次。
timer.schedule(task, delay, period);
Alarm机制
.首先获取到AlarmManager的实例。
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE)
然后调用AlarmManager的set()方法就可以设置一个定时任务了。 long triggerAtTime = SystemClock.elapsedRealtime() + * ; manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtime,pendingIntent);
set()方法中第一个参数是一个整型参数,用于指定AlarmManager的工作类型,有4种值可选,分别是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。
pendingIntent是一种特殊的Intent。主要的区别在于Intent的执行立刻的,而pendingIntent的执行不是立刻的。pendingIntent执行的操作实质上是参数传进来的Intent的操作,但是使用pendingIntent的目的在于它所包含的Intent的操作的执行是需要满足某些条件的。主要的使用的地方和例子:通知Notificatio的发送,短消息SmsManager的发送和警报器AlarmManager的执行等等。 PendingIntent中 getActivity(Context, int, Intent, int) 跳转到一个activity组件
getBroadcast(Context, int, Intent, int) 发送一个广播组件
getService(Context, int, Intent, int) 启动一个服务组件
这里我们一般会调用getService()方法或者getBroadcast()方法来获取一个能够执行服务或者广播的PendingIntent。这样当定时任务被触发的时候。服务的onStartCommand()方法或者广播的onReceive()方法就可以得到执行。
如果想要实现一个长时间在后台定时运行的服务该怎么做呢?
只需要定义一个服务,并将触发定时任务的代码写到onStartCommand()方法中。
@Override
public int onStartCommand(Intent intent,int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
//在这里执行具体逻辑
}
}).start();
AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE);
int anHour = * * ; //这是一小时的毫秒数。
long triggerAtTimer = SystemClock.elapsedRealtime() + anHour;
Intent i = new Intent(this,LongRunningService.class);
PendingIntent pi = PendingIntent.getService(this,,i,);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTimer,pi);
return super.onStartCommand(intent,flags,startId);
}
我们首先是在onStartCommand()方法中开启了一个子线程,这样就可以在这里执行具体的逻辑操作了,之所以要在子线程里执行逻辑操作,是因为逻辑操作也是需要耗时的,如果放在主线程里执行可能会对
定时任务的准确性造成轻微的影响。
创建线程代码之后,先是获取到了AlarmManager的实例, 然后定义任务的触发时间为一个小时后,再使用PendingIntent指定处理定时任务的服务为LongRunningService,最后调用set()方法完成设定。
一旦启动LongRunningService,就会在onStartCommand()方法里设定了一个定时任务,这样一个小时后,将会再次启动LongRunningService。从而形成一个永久的循环,保证LongRunningService的onStartCommand()方法可以每隔一个小时就执行一次。
如果想要启动定时服务的时候调用以下代码即可。
Intent intent = new Intent(context,LongRunningService.class);
context.startService(intent);
需要注意的是,从Android4.4开始,Alarm任务的触发时间将会变得不准确,有可能会延迟一段时间后任务才能执行,这是系统在耗电性方面的优化,系统会自动检测目前有多少Alarm任务存在,然后将触发时间相近的几个任务放在一起执行,这样就可以大幅度减少CPU被唤醒的次数,从而减少耗电量。
如果要求Alarm任务的执行时间必须准确无误,只需要使用AlarmManager的setExact()方法来替代set()方法。就基本上可以保证任务能够准时执行了。
Android下的定时任务的更多相关文章
- Android下/data/data/<package_name>/files读写权限
今天将更新模块拿到android上面测试的时候,发现在创建writablepath.."upd/"目录的时候出现Permission Denied提示BTW:我使用的是lfs来创建 ...
- Android下Cocos2d创建HelloWorld工程
最近在搭建Cocos2d的环境,结果各种问题,两人弄了一天才能搞好一个环境-! -_-!! 避免大家也可能会遇到我这种情况,所以写一个随笔,让大家也了解下如何搭建吧- 1.环境安装准备 下载 tadp ...
- Android下读取logcat的信息
有时我们需要在程序执行进程中遇到一些异常,需要收集一logcat的信息,android下就可以使用以下方法获取: private static String getLogcatInfo(){ Stri ...
- Android下OpenCV的环境搭建
目录(?)[-] 前言 系统环境 相关工具 Android ADT环境搭建 Android SDK环境变量的配置 Android NDK的安装与配置 OpenCV for Android 环境搭建 基 ...
- Android下添加新的自定义键值和按键处理流程
Android下添加新的自定义键值和按键处理流程 说出来不怕大家笑话,我写这篇博客的原因在于前几天去一个小公司面试Android系统工程师,然后在面试的时候对方的技术总监问了我 ...
- Android下的数据储存方式(三)
Android下最好的数据储存方式:关系型数据库sqlite. 数据库的创建:使用SqliteOpenHelper类 结合SqliteOpenHelper类和SQLiteDatabase类的帮 ...
- 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)
1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...
- windows 下的定时任务
linux 下的定时任务是crontab 以前都是linux的定时任务,这次在windows做了定时任务,简单记录一下 windows 2008下的定时任务配置: 控制面板->管理工具-> ...
- 转:RTC搭建android下三层应用程序访问服务器MsSql-客户端
原文:http://www.cnblogs.com/delphi007/p/3346084.html android下stringgrid已知问题: 通过点击时获取对应行的值有问题,在win下调试正常 ...
随机推荐
- 7.学完linux系统运维到底可以做什么?
linux运维到底可以做什么?(略有改动原文.排版) 运维,很容易从字面理解为运营.维护. 很多朋友认为,在互联网公司中linux系统运维的工作就是安装系统,部署服务.处理紧急故障,为公司里的开发人员 ...
- 文献管理器endnote学习笔记
目录 文献管理器endnote学习笔记 一.文献信息输入(将文献信息添加到文献管理软件endnote的多种方法) 1.在线检索(方便快捷,但有些网站无法直接检索) 2.网站输出(所有网站都支持的方式, ...
- ElasticSearch 本机可以访问,外网无法访问----问题解决
问题:本机可以访问,外网无法访问 config/elasticsearch.yml network.host: 0.0.0.0 使用普通用户zuoys,重启es,报错如下: [1]: max file ...
- Python语言学习前提:循环语句
一.循环语句 1.循环语句:允许执行下一个语句或语句组多次 2. 循环类型 3. 循环控制语句 4. while 循环语句 a.while循环语句:在某个条件下,循环执行某段程序,以处理需要重复处理的 ...
- Linux集群软件安装实战
一.需求和思路 1. 需求描述 公司有N个节点的集群,需要统一安装一个软件(jdk)需要开发一个脚本程序,实现对集群中的N个节点批量自动下载.安装jdk 2. 思路 1)编写一个启动脚本,用来发送一个 ...
- Angular(一)
Angular开发者指南(一)入门介绍 什么是AngularAngularJS是动态Web应用程序的结构框架. 它允许您使用HTML作为模板语言,并允许您扩展HTML的语法以清晰,简洁地表达应用程 ...
- Linux基础篇八:VIM
新知识: 普通模式光标跳转: G ##光标跳转到末端 (shift +g) gg ##光标跳转到开端 Ngg 15gg ##光标跳转到当前文本中的15行 $ ##光标移动到当前 ...
- 吴裕雄--天生自然python Google深度学习框架:深度学习与深层神经网络
- linux中的文件解压命令
http://apps.hi.baidu.com/share/detail/37384818 download ADT link http://dl.google.com/android/ADT-0. ...
- Andriod常用控件介绍&相关属性(初学方便查询)
一.TextView(显示控件) android:id(给当前控件定义唯一的标识符)——示例:android:id = "@+id/text_view" android:layou ...