您的位置:首页 > 移动开发 > Android开发

Android之AlarmManager

2016-05-30 10:31 429 查看
本文只是记录一些零碎的东西

最近项目里需要做消息的推送,大概看了一下,在手机平台上,常用的方法有2种。一种是定时去服务器上查询数据,也叫

Polling,还有一种手机跟服务器之间维护一个 TCP 长连接,当服务器有数据时,实时推送到客户端,也就是我们说的 Push。

网上现在很多免费的推送SDK,比如,极光推送,使用也很简单,官网上文档很详细,究其实现原理,原来是基于Android提供的AlarmManager,定时运行任务,Google的API 在:https://developer.android.com/reference/android/app/AlarmManager.html,极光推送经过很多次迭代,其算法优化的特别好,将手机的能耗降到很低,这点值得称赞。

AlarmManager 是 Android 系统封装的用于管理 RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,可以在 CPU 休

眠时正常运行,在预设的时间到达时,通过中断唤醒 CPU。这意味着,如果我们用 AlarmManager 来定时执行任务,CPU 可以正常

的休眠,只有在需要运行任务时醒来一段很短的时间。

AlarmManager这个类提供对系统闹钟服务的访问接口。Google文档里说的很清楚

从API 19开始,AlarmManager的机制都是非准确传递,操作系统将会转换闹钟,来最小化唤醒和电池使用。

去除了重复处理的函数

setRepeating(int type,long startTime,long intervalTime,PendingIntent pi)
该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,第三个参数表示闹钟两次执行的

间隔时间,第三个参数表示闹钟响应动作。

建议采用如下方法: void setWindow (int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation)

没有了repeat,就是设置了闹钟只能响一次了,应该是比较省电的。因为setWindow这个方法允许应用程序利用电池优化。

重复设置的问题好解决,我们的任务开始后重新设置一下Alarm就可以了。

官方还有一句话:but will be cleared if it is turned off and rebooted。重启好解决,监听开机广播就可以了,应用程序被kill,能想到

的只是通过服务自启动来实现,要不就把应用持久化到内存中(不建议)

int type : 闹钟类型

ELAPSED_REALTIME:闹钟在睡眠状态下不可用,使用的是相对系统启动时间

ELAPSED_REALTIME_WAKEUP:闹钟在睡眠状态下可用,使用的是相对系统启动时间

RTC:闹钟在睡眠状态下不可用,使用的是真实时间

RTC_WAKEUP:闹钟在睡眠状态下可用,使用的是真实时间

long windowStartMillis:闹钟开始时间

long windowLengthMillis:闹钟间隔

PendingIntent operation :闹钟的动作,在这里实现我们想实现的任务,google也给我们提供好了

Activity :PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)

Broadcast:PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)

Service:PendingIntent.getService(Context context, int requestCode, Intent intent, int flags)

pendingIntent的第4个参数

FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的PendingIntent对象,那么就将先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。

FLAG_NO_CREATE:如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象而是直接返回null。

FLAG_ONE_SHOT:该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。

FLAG_UPDATE_CURRENT:如果系统中有一个和你描述的PendingIntent对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。

一个简单的以广播形式调用的封装

<span style="font-size:14px;">/**
*  以服务形式 开启 Alarm
* @param context   The Context in which this PendingIntent should perform the broadcast
* @param requestCode    Private request code for the sender
* @param timeInMillis   时间开始节点
* @param interval   持续时间
* @param intent   Intent to be broadcast
*/
public static void setAlarmTime(Context context, int requestCode, long timeInMillis,int interval, Intent intent) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent sender = PendingIntent.getBroadcast(context, requestCode,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setWindow(AlarmManager.RTC_WAKEUP, timeInMillis, interval, sender);
}
}
/**
* Alarm 取消
* @param context
* @param action
* @param requestCode
*/
public static void cancelAlarm(Context context, String action, int requestCode) {
Intent intent = new Intent(action);
PendingIntent pi = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent
.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi);
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: