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

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处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
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值