Android使用AlarmManager设置定时任务

  • 内容
  • 评论
  • 相关

赶了两天的APP。。。就为了这玩意儿。老早以前就想过用这东西来实现功能的,但是一直有问题。直到前两天有时间了开始着手刷刷这BUG。也算是对这玩意儿的一次重新学习吧。

AlarmManager顾名思义也就是一个提醒管理器,属于Android系统的一项服务,你可以通过这个服务来设置指定时间执行指定的任务。AlarmManager会在你指定的时间启动Activity/发送广播,等等,以完成你需要执行的操作任务。总的来说,这东西就跟闹钟是差不多一个意思的,到了点了然后启动某项你指定的任务

在Simple Netkeeper的编写过程中为了完成后台拨号功能,也用到了这玩意儿。由于是后台操作,因此我选择了使用广播接收器(BroadcastReceiver)来完成这个操作。基本思路是:用户设置/开机启动设置-》加载任务时间-》设置Alarm,指定时间启动-》Receiver收到消息启动服务。

因为我是用接收器来做这项工作,接收器的定义就成了首要部分。

在Android系统中,BroadcastReceiver用于接收系统发送的广播消息(这东西感觉好像和C++里面的消息机制是差不多的),广播消息又分为几种,在此不做过多的阐述。接收器实例化收到消息后调用onReceive回调方法,提供Context和Intent两项参数。其中Intent是广播发送者所指定的,里面携带了发送者所提供的信息,以及指定的行为(Action),Action是一串字符串。在广播发送过程中为了避免收到部分不需要的广播遭受不必要的干扰,因此设置Action可以很好的避免这种情况。可以通过 intent.getAction()方法来获取发送者所指定的行为。

因此对于广播接收器的任务可以大致认为是:收到广播-》判断行为-》执行操作。

在Simple Netkeeper中执行后台定时任务的接收器代码如下(版本1.3.0.55)

(为了方便代码重用,我将启动/停止服务的方法写成了静态方法,以避免过度的重复代码造成维护困难。)

在上述代码中你可以看到我启动后台拨号的流程是:判断行为-》建立新的线程-》判断WIFI状态-》检查时间-》检查配置文件-》执行拨号-》启动下一次服务(startBackgroundService方法中包含了时间判断部分)。

在这里,由于BroadcastReceiver和Activity类似,其中的代码都是在主线程中运行,因此根据开发建议,不应该在主线程中有耗时的行为(比如设备请求/网络请求),因为这种请求可能会导致ANR的发生。我使用了新线程处理任务,但是建议使用AsyncTask来处理异步任务以保证多数情况下的线程安全。

代码码完了,你得让系统知道吧,修改 manifest ,注册接收器

intent-filter起到对广播的一种过滤作用,然而我现在并不是太理解,为了避免误导大众我就不说多的了。

好了,接收器做完了,总该有个方法启动这项任务了吧?还记得大明湖畔的startBackgroundService方法么

啥?不记得了?我再贴一次

其实这里面最关键的代码就是前面7行和最后一行的set方法。

首先,获取AlarmManager的实例,之前说过这玩意儿是Android系统的一项服务,因此使用Context的getSystemService(ALARM_SERVICE)来获取。

然后建立一个新的Intent实例,构造方法为( Context ,接收器类),如果需要添加信息的话,使用putExtra方法添加,接收器是可以通过getExtra获取到的,然后是设置Action(之前说过了避免干扰)。

接着建立PendingIntent的实例,并使用getBroadcast方法来获取这个实例。这里要注意:所有对Intent的设置必须发生在建立PendingIntent之前,否则建立PendingIntent之后再修改Intent的数据是不会有任何作用的,这里我就吃过亏 - -,改了半天发现Action是null,结果还有这顺序问题,我也是醉了

最后,用AlarmManager设置你的任务。三个参数分别为 执行模式,时间,PendingIntent。执行模式一般选择RTC_WAKEUP,我记得这个是表示到时间了唤醒设备执行任务。

调用方法设置之后,到了指定时间接收器就会接受到广播,然后执行后面的任务了。

然而我也不知道为什么之前坑了我这么久这会儿这么快就搞完了,草草草草草