闹钟管理器AlarmManager(整理)
来源:互联网 发布:个人短信群发平台知乎 编辑:程序博客网 时间:2024/05/17 05:52
在Android中,可以使用闹钟管理器来触发事件,包括广播BroadcastReceiver,服务Service和活动Activity。这些事件可以在特定的时刻或者以固定的时间间隔来触发。
使用闹钟管理器一般有以下几个步骤:
1、获取到闹钟管理器的服务,即AlarmManager;
2、确定设置闹钟的时刻;
3、创建要调用的接收程序,可以是广播BroadcastReceiver,服务Service和活动Activity;
4、创建一个挂起的Intent(即PendingIntent),它可传递给闹钟管理器来调用设置的该接收程序;
5、使用第2步中的时间和第4步中的Intent来设置闹钟;
6、在第3步中的接收闹钟管理器的调用。
接下来是对每个步骤进行说明:
1、获取闹钟管理器,AlarmManager
这是比较简单的,调用系统服务就可以得到AlarmManager。
AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
2、创建闹钟的时刻
为了快捷方便,特别创建了一个Utils类,在里面提供创建各种类型的时刻。
public class Utils {/** * 创建secs秒后闹钟时间 * @param secs * @return */public static Calendar getTimeAfterInSecs(int secs){Calendar cal = Calendar.getInstance();cal.add(Calendar.SECOND,secs);return cal;}public static Calendar getCurrentTime(){Calendar cal = Calendar.getInstance();return cal;}/** * 创建在某个固定小时时刻的闹钟 * @param hours * @return */public static Calendar getTodayAt(int hours){Calendar today = Calendar.getInstance();Calendar cal = Calendar.getInstance();cal.clear();int year = today.get(Calendar.YEAR);int month = today.get(Calendar.MONTH);//represents the day of the monthint day = today.get(Calendar.DATE);cal.set(year,month,day,hours,0,0);return cal;}public static String getDateTimeString(Calendar cal){SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");df.setLenient(false);String s = df.format(cal.getTime());return s;}}3、创建接受闹钟的接收程序,这里暂时使用一种类型BroadCastReceiver
public class TestReceiver extends BroadcastReceiver { private static final String tag = "TestReceiver"; @Override public void onReceive(Context context, Intent intent) { Log.d("TestReceiver", "intent=" + intent); String message = intent.getStringExtra("message"); Log.d(tag, message); }}4、创建闹钟的PendingIntent
首先需要创建只想TestReceiver的Intent
Intent intent = new Intent(mContext, TestReceiver.class); intent.putExtra("message", "Single Shot Alarm");接下来创建挂起的PendingIntent:
PendingIntent pi = PendingIntent.getBroadcast( mContext, //context 1, //request id, used for disambiguating this intent intent, //intent to be delivered PendingIntent.FLAG_ONE_SHOT); //pending intent flags
5、设置闹钟
Calendar cal = Utils.getTimeAfterInSecs(30);AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);
这样就可以在TestReiver中接收到闹钟消息了。
以上是关于闹钟管理器的简单使用,接下来将增加关于设置重复闹钟和取消闹钟的使用。
一、设置重复闹钟
设置重复闹钟的前面几个步骤都是一样的,只是在最后设置闹钟的时候有所变化
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5*1000, //5 secs pi);关于这个方法的参数说明:第一个:警报的类型,这里采用闹钟来唤醒设备;第二个:第一次闹钟执行的时刻;第三个:在闹钟第一次执行后,每隔多久开始重复执行;第四个:挂起的PendingIntent。
二、取消闹钟
要取消闹钟,必须首先挂起一个Intent,然后调用cancel()方法,将参数传递给闹钟管理器。
Intent intent = new Intent(this.mContext, TestReceiver.class); //To cancel, extra is not necessary to be filled in //intent.putExtra("message", "Repeating Alarm"); PendingIntent pi = this.getDistinctPendingIntent(intent, 2); // Schedule the alarm! AlarmManager am = (AlarmManager) this.mContext.getSystemService(Context.ALARM_SERVICE); am.cancel(pi);
protected PendingIntent getDistinctPendingIntent(Intent intent, int requestId) { PendingIntent pi = PendingIntent.getBroadcast( mContext, //context requestId, //request id intent, //intent to be delivered 0); //pending intent flags //PendingIntent.FLAG_ONE_SHOT); return pi; }
在创建Intent的时候,如果是为了取消闹钟,可以不用再Intent中设置任何消息参数和数据,只需要保证最后的指向接收程序一致。然后创建的PendingIntent也必须和原来一致,必须确保采用设置闹钟时相同的方式来构造它,包括请求代码,即上面的requestId和接收程序。
三、设置多个闹钟
如果了解了上面关于设置单个闹钟和重复闹钟的设置过程,可能会认为只需要创建多个不同的cal时刻,然后分别设置到闹钟里面,就能实现了。其实不然,里面涉及到一些陷进。
先看下面的代码:
/* * Same intent cannot be scheduled multiple times. * If you do, only the last one will take affect. * * Notice you are using the same request id. */ public void scheduleSameIntentMultipleTimes() { //Get the instance in time that is //30 secs from now. Calendar cal = Utils.getTimeAfterInSecs(30); Calendar cal2 = Utils.getTimeAfterInSecs(35); Calendar cal3 = Utils.getTimeAfterInSecs(40); Calendar cal4 = Utils.getTimeAfterInSecs(45); //If you want to point to 11:00 hours today. //Calendar cal = Utils.getTodayAt(11); //Get an intent to invoke //TestReceiver class Intent intent = new Intent(mContext, TestReceiver.class); intent.putExtra("message", "Single Shot Alarm"); PendingIntent pi = this.getDistinctPendingIntent(intent, 1); // Schedule the alarm! AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi); am.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), pi); am.set(AlarmManager.RTC_WAKEUP, cal3.getTimeInMillis(), pi); am.set(AlarmManager.RTC_WAKEUP, cal4.getTimeInMillis(), pi); }上面这部分代码,使用了同一个PendingIntent,设置了4个不同的闹钟时间,这样的效果就是:只有最后一个闹钟会被触发,前面的所有闹钟都会被忽略掉。
而要实现多个闹钟的实现是如下:
/* * Same intent can be scheduled multiple times * if you change the request id on the pending intent. * Request id identifies an intent as a unique intent. */ public void scheduleDistinctIntents() { //Get the instance in time that is //30 secs from now. Calendar cal = Utils.getTimeAfterInSecs(30); Calendar cal2 = Utils.getTimeAfterInSecs(35); Calendar cal3 = Utils.getTimeAfterInSecs(40); Calendar cal4 = Utils.getTimeAfterInSecs(45); //If you want to point to 11:00 hours today. //Calendar cal = Utils.getTodayAt(11); //Get an intent to invoke //TestReceiver class Intent intent = new Intent(mContext, TestReceiver.class); intent.putExtra("message", "Single Shot Alarm"); // Schedule the alarms! AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), getDistinctPendingIntent(intent,1)); am.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), getDistinctPendingIntent(intent,2)); am.set(AlarmManager.RTC_WAKEUP,cal3.getTimeInMillis(), getDistinctPendingIntent(intent,3)); am.set(AlarmManager.RTC_WAKEUP,cal4.getTimeInMillis(), getDistinctPendingIntent(intent,4)); }每个挂起的Intent,也就是PendingIntent不同,也就是让每个PendingIntent的RequestId不同。产生这种原因是因为在AlarmManager中设置闹钟时,对于相同的Intent,是通过不同的请求Id来创建的。
在相同类型的Intent上设置闹钟时,只有最后一个闹钟时生效的。
以下是AlarmMangerService的部分源码,可以看到为什么不能使用相同的PendingIntent了。
public void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation) {.....synchronized (mLock) { Alarm alarm = new Alarm(); alarm.type = type; alarm.when = triggerAtTime; alarm.repeatInterval = interval; alarm.operation = operation; // Remove this alarm if already scheduled. removeLocked(operation); //当使用相同的operation的时候u,就会先把已有的删除,这样的话,直到最后一个才会生效。 if (localLOGV) Slog.v(TAG, "set: " + alarm); int index = addAlarmLocked(alarm); if (index == 0) { setLocked(alarm); } } }
最后一点是关于闹钟的持久化问题,它们是不能保存到设备重新启动之后,也就是说当设备重新启动后,之前设置的闹钟将全部失效。
下面是一个详细的闹钟例子,可以作为参考
http://pan.baidu.com/s/1kTHlOG3
下面是关于android中闹钟的调用流程,知道进入到Android的底层,可以看看:
http://blog.csdn.net/crycheng/article/details/7804813
- 闹钟管理器AlarmManager(整理)
- AlarmManager闹钟管理器
- android中的闹钟管理器AlarmManager&PendingIntent
- 闹钟 AlarmManager PendingIntent
- 闹钟 AlarmManager PendingIntent
- 闹钟 AlarmManager PendingIntent
- AlarmManager全局定时器/闹钟
- Android--闹钟AlarmManager详解
- AlarmManager手机闹钟服务
- AlarmManager(手机闹钟服务)
- 手机闹钟服务 AlarmManager
- Android闹钟-AlarmManager
- Android AlarmManager闹钟实现
- AlarmManager全局定时器/闹钟
- AlarmManager 全局闹钟
- AlarmManager闹钟 延迟响应
- Android闹钟 AlarmManager基础
- Android---AlarmManager闹钟设置
- 对大数据开发经验
- boost::dynamic_bitset
- 网络安装centos
- 高效整洁CSS代码原则
- VMware虚拟机 ping出现 DUP!
- 闹钟管理器AlarmManager(整理)
- MD5 校验两个文件是否一样
- 【Oracle优化笔记】访问索引的方法
- android 全屏,无标题栏
- imo电子白板共享时无法插入文档的解决办法
- UIActivityIndicatorView活动指示器
- CodeForces 214E - Relay Race(二取方格数)
- Unix chroot最佳实践
- HOG特征与opencv类实现