Pro Android学习笔记(一零五):Alarm Manager(3):request code

来源:互联网 发布:房产拍卖淘宝司法拍卖 编辑:程序博客网 时间:2024/04/30 11:15

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying以及作者@恺风Wei。

我们在接收器中弹出Toast增加了时间标签,更好地跟踪执行时间。我们将进一步了解request code的作用。

实验小例子

提供一个实验例子,在此基础上调整执行的语句,看看执行的情况。

public void scheduleSameIntentMultiTimes(){
    Calendar cal1 = Utils.getTimeAfterInSecs(5);
    Calendar cal2 = Utils.getTimeAfterInSecs(10);
    Calendar cal3 = Utils.getTimeAfterInSecs(15);
    Calendar cal4 = Utils.getTimeAfterInSecs(20);
    Calendar cal5 = Utils.getTimeAfterInSecs(8);
    mReport.reportBack(tag, "1:schedule at " + Utils.getDateTimeString(cal1));
    mReport.reportBack(tag, "2:schedule at " + Utils.getDateTimeString(cal2));
    mReport.reportBack(tag, "3:schedule at " + Utils.getDateTimeString(cal3));
    mReport.reportBack(tag, "4:schedule at " + Utils.getDateTimeString(cal4));
    //mReport.reportBack(tag, "5:schedule repeated at " + Utils.getDateTimeString(cal5)+",间隔5秒");

   
    Intent intent1 = new Intent(mContext,TestReceiver.class);
    intent1.putExtra("message", "1:Same intent multi times");
   
    Intent intent2 = new Intent(mContext,TestReceiver.class);
    intent2.putExtra("message", "2:Same intent multi times");
   
    Intent intent3 = new Intent(mContext,TestReceiver.class);
    intent3.putExtra("message", "3:Same intent multi times");
   
    Intent intent4 = new Intent(mContext,TestReceiver.class);
    intent4.putExtra("message", "4:Same intent multi times");

    Intent intent5 = new Intent(mContext,TestReceiver.class);
    intent5.putExtra("message", "5:repeated");
   
    PendingIntent pi1 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent1, 0);
    PendingIntent pi2 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE+1, intent2, 0);
    PendingIntent pi3 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE+2, intent3, 0);
    PendingIntent pi4 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE+3, intent4, 0);
    //PendingIntent pi5 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE+4, intent5, 0);
   
    AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 
    am.set(AlarmManager.RTC_WAKEUP,cal1.getTimeInMillis(),pi1);
    am.set(AlarmManager.RTC_WAKEUP,cal2.getTimeInMillis(),pi2);
    am.set(AlarmManager.RTC_WAKEUP,cal3.getTimeInMillis(),pi3);
    am.set(AlarmManager.RTC_WAKEUP,cal4.getTimeInMillis(),pi4);
    //am.setRepeating(AlarmManager.RTC_WAKEUP, cal5.getTimeInMillis(), 5000, pi5);   
}

我们设置了5个告警(其中1个在代码中注销,将在后面的测试中使用),对应5个不同的PendingIntent。为了区分所携带的intent,分别设置了不同的extras。

不同的request code

不同的request code可以用于区分不同的alarm,在上面的例子中,我们可以预测四个alarm将依次触发接收器。执行结果如下图:

我们发现,根据我们的设置的告警时间,依次顺序发出告警1,告警2,告警3,告警4,但是仔细查看告警发生的时间,确并不准确,和我们设定的时间不同。我们通过减少alarm的设定,发现设定1个告警、2个告警和3个告警的情况下,发送告警的时间和设定基本符合,由此怀疑这只是模拟器性能不足的缘故。因此,我们接了该真实设备进行调测,发现4个告警的发生时间是准确的。

在request code不同时,alarm管理器能够按我们设置的情况进行告警发送。

request code相同的情况

我们将看看request code一样,会发生什么。首先设置request code相同:

PendingIntent pi1 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent1, 0);
PendingIntent pi2 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent2, 0);
PendingIntent pi3 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent3, 0);
PendingIntent pi4 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent4, 0);
PendingIntent pi5 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent5, 0);

为了避免过多alarm进行干扰,我们注销了代码,只留下需要观察的对象。

代码片段:实验一

PendingIntent pi1 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent1, 0);
PendingIntent pi2 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent2, 0);
... ...
am.set(AlarmManager.RTC_WAKEUP,cal1.getTimeInMillis(),pi1);
am.set(AlarmManager.RTC_WAKEUP,cal2.getTimeInMillis(),pi2);

代码片段:实验二

PendingIntent pi1 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent1, 0);
PendingIntent pi5 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent5, 0);
... ...
am.set(AlarmManager.RTC_WAKEUP,cal1.getTimeInMillis(),pi1);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal5.getTimeInMillis(), 5000, pi5);   

代码片段:实验三

PendingIntent pi1 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent1, 0); 
PendingIntent pi5 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent5, 0); 
... ... 
am.setRepeating(AlarmManager.RTC_WAKEUP, cal5.getTimeInMillis(), 5000, pi5);    
am.set(AlarmManager.RTC_WAKEUP,cal1.getTimeInMillis(),pi1);

代码片段:实验四

PendingIntent pi2 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent2, 0);
PendingIntent pi1 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent1, 0);
... ...
am.set(AlarmManager.RTC_WAKEUP,cal1.getTimeInMillis(),pi1);
am.set(AlarmManager.RTC_WAKEUP,cal2.getTimeInMillis(),pi2);

测试结果如下:

在request code相同的情况下,告警的执行时间,和执行模式(单次还是重复)按后设置的告警,告警内容(intent)则按代码中第一次加入该request code的pendingIntent的intent。

关于intent的问题,在之前取消告警中提过:extras不用于判断intent的唯一性。在小例子中,实际上系统会认为intent都是相同的,因此没有进行intent的更新。我们增加一个接收器TestReceiver2,用于确保系统能区分intent,实验五的相关代码如下:

Calendar cal1 = Utils.getTimeAfterInSecs(5);
Calendar cal2 = Utils.getTimeAfterInSecs(10);


Intent intent1 = new Intent(mContext,TestReceiver.class);
intent1.putExtra("message", "1:Same intent multi times");

Intent intent2 = new Intent(mContext,TestReceiver2.class);
intent2.putExtra("message", "2:Same intent multi times");

PendingIntent pi1 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent1, 0);
PendingIntent pi2 = PendingIntent.getBroadcast(mContext, REQUEST_MULTI_CODE, intent2, 0);

AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,cal1.getTimeInMillis(),pi1);
am.set(AlarmManager.RTC_WAKEUP,cal2.getTimeInMillis(),pi2);

试验的结果是:系统能正确执行两次告警触发,如同request code不一样的情况。

根据上面的多个测试,我们的结论是:告警可以通过pendingIntent携带的不同的intent或者request code来进行区分。注意extras不用于区分intent,而是在创建intent对象所携带的参数。如果系统无法区pendingIntent,则按后面设置的告警来执行,但在这过程中并不更新所携带的intent信息。

从源码看,对并不更新所携带intent信息有些奇怪,因为在AlarmManagerService.java的L578(API 19)执行了removeLocked(operation),其中opteration就是PendingIntent对象。但是不清楚服务中这个PendingIntent是如何生产的,也不确定未来的版本会不会进行修订。因此,除非有特别的需求,一般不要使用相同的request code和相同的intent。

注意事项

需要注意,设备重启后,alarm管理器中所设置的都会变成无效。如果我们需要alarm能够在开机后依然有效,就不能光依赖于alarm manager。我们需要对此进行相关的保存,并在重启的时候重新向alarm管理器进行注册。或者设备重启,可以通过监听android.intent.action.BOOT_COMPLETED广播消息。

小例子代码在:Pro Android学习:Alarm Manager小例子

相关链接:我的Android开发相关文章

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 6个月婴儿感冒了怎么办 六个月宝宝有痰怎么办 9月婴儿牛奶过敏怎么办 一用粉底就过敏怎么办 7个月婴儿过敏怎么办 9个月宝宝腹泻怎么办 9个月宝宝拉肚子怎么办 5个月宝宝拉肚子怎么办 九个月大宝宝拉肚子怎么办 九个半月的宝宝拉肚子怎么办 9个月婴儿拉稀怎么办 九个月的宝宝拉肚子怎么办 9个月宝宝拉稀水怎么办 2岁宝宝腹泻拉水怎么办 18个月宝宝拉水怎么办 2个月宝宝拉稀水怎么办 2个月的宝宝腹泻怎么办 2个月的宝宝拉稀怎么办 宝宝不喝补液盐怎么办 4个月宝宝腹泻怎么办 6个月宝宝腹泻怎么办 四个月的宝宝拉肚子怎么办 7个月婴儿便秘怎么办 宝宝9个月拉肚子怎么办 2个月宝宝拉肚子怎么办 4个月宝宝没奶怎么办 宝宝又吐又拉怎么办 冬季车放在外面怎么办 冬天车放在外面怎么办 新车被拖走了要怎么办 门钥匙拔不出来怎么办 婴儿换尿布就哭怎么办 芥末吃多了胃疼怎么办 孕妇吃了甜白酒怎么办 43岁意外怀二胎怎么办 38岁意外怀二胎怎么办 脚崴了没有肿怎么办 我出轨了怎么办很痛苦 老公有了小三老婆应该怎么办 厦门学生卡丢了怎么办 比熊嘴巴毛发黄怎么办