android 之 AlarmManager 系统闹钟(3)

转载 2016年08月31日 16:16:56

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处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小例子

Alarmmanager制作简单闹钟功能

代码: activity_main.xml
  • linhaiyun_ytdx
  • linhaiyun_ytdx
  • 2016年09月12日 12:25
  • 996

AlarmManager闹钟 延迟响应

项目做一个闹钟,需要闹钟可以在时间点准时响应。当闹钟设立数量较少的时候,还算比较可靠,基本都能准时响应。但如果app设立的闹钟的过多,就会有一些闹钟发生延时响应的bug,有时会晚几秒,有时会晚几分钟。...
  • pashanhuxp
  • pashanhuxp
  • 2015年07月30日 18:41
  • 2402

Android基础入门教程——10.5 AlarmManager(闹钟服务)

本节带来的Android中的AlarmManager(闹钟服务),听名字我们知道可以通过它开发手机闹钟类的APP, 而在文档中的解释是:在特定的时刻为我们广播一个指定的Intent,简单说就是我们自...
  • zpj779878443
  • zpj779878443
  • 2015年10月26日 14:22
  • 12691

Android,AlarmManager设置多个闹钟相关问题

Android利用AlarmManager来实现多个闹钟功能,其实很简单,网上有很多关于AlarmManager类的介绍,写的很详细,我这里不做过多描述了,下面来说下我工作中遇到的问题吧。 可能大家...
  • yangge00123
  • yangge00123
  • 2015年06月15日 22:47
  • 2099

Android AlarmManager加入与取消闹钟提醒, Notification不显示的问题

关于日程提醒,用Android系统的AlarmManager,将提醒时间加入系统闹钟并同广播关联,在闹钟到点提醒时,触发广播,然后弹出通知栏通知日程,以下为设置闹钟的代码 private void ...
  • androidforwell
  • androidforwell
  • 2016年12月16日 18:47
  • 4617

关于AlarmManager设置重复闹钟延迟的问题

AlarmManager,闹钟
  • clzh2013
  • clzh2013
  • 2016年12月26日 09:55
  • 624

Android闹钟AlarmManager-通知NotificationManager-自定义通知栏

一:闹钟AlarmManager和通知NotificationManager
  • luz682328zul
  • luz682328zul
  • 2017年02月15日 20:47
  • 890

Android中AlarmManager详解以及利用PendingIntent设置闹钟

AlarmManager是提供一种访问系统闹钟服务的方式,允许你去设置在将来的某个时间点去执行你的应用程序。当你的闹钟响起(时间到)时,在它上面注册的一个意图(Intent)将会被系统以广播发出,然后...
  • qq_28330221
  • qq_28330221
  • 2017年03月12日 12:27
  • 3579

android AlarmManager详解,Alarm的设定和取消。

设定alarm的话,大概需要用到如下几步: 1.创建一个Intent 2.创建一个PendingIntent 3.得到ALARM_SERVICE的AlarmManager 4....
  • lisineng
  • lisineng
  • 2015年03月27日 10:43
  • 7416

Android提供的系统服务之--AlarmManager(闹钟服务)

本节引言: 本节主要介绍的是Android系统服务中的---AlarmManager(闹钟服务), 除了开发手机闹钟外,更多的时候是作为一个全局的定时器,通常与Service 结合,在特定时间启...
  • syf6568362
  • syf6568362
  • 2015年12月25日 09:41
  • 2719
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android 之 AlarmManager 系统闹钟(3)
举报原因:
原因补充:

(最多只允许输入30个字)