23闹钟管理

   在Android中,可以使用闹钟管理器来触发事件,包括广播BroadcastReceiver,服务Service和活动Activity。这些事件可以在特定的时刻或者以固定的时间间隔来触发。

       使用闹钟管理器一般有以下几个步骤:

        1、获取到闹钟管理器的服务,即AlarmManager;

        2、确定设置闹钟的时刻;

        3、创建要调用的接收程序,可以是广播BroadcastReceiver,服务Service和活动Activity;

        4、创建一个挂起的Intent(即PendingIntent),它可传递给闹钟管理器来调用设置的该接收程序;

        5、使用第2步中的时间和第4步中的Intent来设置闹钟;

        6、在第3步中的接收闹钟管理器的调用。

        接下来是对每个步骤进行说明:

1、获取闹钟管理器,AlarmManager

      这是比较简单的,调用系统服务就可以得到AlarmManager。

[java]  view plain  copy
  1. AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);  

2、创建闹钟的时刻

      为了快捷方便,特别创建了一个Utils类,在里面提供创建各种类型的时刻。

[java]  view plain  copy
  1. public class Utils   
  2. {         
  3.     /** 
  4.      * 创建secs秒后闹钟时间 
  5.      * @param secs 
  6.      * @return 
  7.      */  
  8.     public static Calendar getTimeAfterInSecs(int secs)  
  9.     {  
  10.         Calendar cal = Calendar.getInstance();  
  11.         cal.add(Calendar.SECOND,secs);  
  12.         return cal;  
  13.     }  
  14.     public static Calendar getCurrentTime()  
  15.     {  
  16.         Calendar cal = Calendar.getInstance();  
  17.         return cal;  
  18.     }  
  19.     /** 
  20.      * 创建在某个固定小时时刻的闹钟 
  21.      * @param hours 
  22.      * @return 
  23.      */  
  24.     public static Calendar getTodayAt(int hours)  
  25.     {  
  26.         Calendar today = Calendar.getInstance();  
  27.         Calendar cal = Calendar.getInstance();  
  28.         cal.clear();  
  29.           
  30.         int year = today.get(Calendar.YEAR);  
  31.         int month = today.get(Calendar.MONTH);  
  32.         //represents the day of the month  
  33.         int day = today.get(Calendar.DATE);  
  34.         cal.set(year,month,day,hours,0,0);  
  35.         return cal;  
  36.     }  
  37.     public static String getDateTimeString(Calendar cal)  
  38.     {  
  39.         SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");  
  40.         df.setLenient(false);  
  41.         String s = df.format(cal.getTime());  
  42.         return s;  
  43.     }  
  44. }  
3、创建接受闹钟的接收程序,这里暂时使用一种类型BroadCastReceiver

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class TestReceiver extends BroadcastReceiver   
  2. {  
  3.     private static final String tag = "TestReceiver";   
  4.     @Override  
  5.     public void onReceive(Context context, Intent intent)   
  6.     {  
  7.         Log.d("TestReceiver""intent=" + intent);  
  8.         String message = intent.getStringExtra("message");  
  9.         Log.d(tag, message);  
  10.     }  
  11. }  
4、创建闹钟的PendingIntent

      首先需要创建只想TestReceiver的Intent

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Intent intent = new Intent(mContext, TestReceiver.class);  
  2. ent.putExtra("message""Single Shot Alarm");  
    接下来创建挂起的PendingIntent:

[java]  view plain  copy
  1. PendingIntent pi =   
  2. ndingIntent.getBroadcast(  
  3. mContext,   //context  
  4.       1,            //request id, used for disambiguating this intent  
  5.       intent,       //intent to be delivered   
  6.       PendingIntent.FLAG_ONE_SHOT);  //pending intent flags  

5、设置闹钟

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Calendar cal = Utils.getTimeAfterInSecs(30);  
  2. AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);  
  3. am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);  

这样就可以在TestReiver中接收到闹钟消息了。

以上是关于闹钟管理器的简单使用,接下来将增加关于设置重复闹钟和取消闹钟的使用。


一、设置重复闹钟

     设置重复闹钟的前面几个步骤都是一样的,只是在最后设置闹钟的时候有所变化

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. am.setRepeating(AlarmManager.RTC_WAKEUP,   
  2.                 cal.getTimeInMillis(),   
  3.                 5*1000//5 secs   
  4.                 pi);  
     关于这个方法的参数说明:第一个:警报的类型,这里采用闹钟来唤醒设备;第二个:第一次闹钟执行的时刻;第三个:在闹钟第一次执行后,每隔多久开始重复执行;第四个:挂起的PendingIntent。


二、取消闹钟

     要取消闹钟,必须首先挂起一个Intent,然后调用cancel()方法,将参数传递给闹钟管理器。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Intent intent =   
  2.         new Intent(this.mContext, TestReceiver.class);  
  3.       
  4.     //To cancel, extra is not necessary to be filled in  
  5.     //intent.putExtra("message", "Repeating Alarm");  
  6.   
  7.     PendingIntent pi = this.getDistinctPendingIntent(intent, 2);  
  8.       
  9.     // Schedule the alarm!  
  10.     AlarmManager am =   
  11.         (AlarmManager)  
  12.            this.mContext.getSystemService(Context.ALARM_SERVICE);  
  13.     am.cancel(pi);  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected PendingIntent getDistinctPendingIntent(Intent intent, int requestId)  
  2.     {  
  3.         PendingIntent pi =   
  4.             PendingIntent.getBroadcast(  
  5.               mContext,     //context  
  6.               requestId,    //request id  
  7.               intent,       //intent to be delivered  
  8.               0);  
  9.   
  10.         //pending intent flags  
  11.         //PendingIntent.FLAG_ONE_SHOT);       
  12.         return pi;  
  13.     }  

      在创建Intent的时候,如果是为了取消闹钟,可以不用再Intent中设置任何消息参数和数据,只需要保证最后的指向接收程序一致。然后创建的PendingIntent也必须和原来一致,必须确保采用设置闹钟时相同的方式来构造它,包括请求代码,即上面的requestId和接收程序。


三、设置多个闹钟

      如果了解了上面关于设置单个闹钟和重复闹钟的设置过程,可能会认为只需要创建多个不同的cal时刻,然后分别设置到闹钟里面,就能实现了。其实不然,里面涉及到一些陷进。

先看下面的代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.      * Same intent cannot be scheduled multiple times. 
  3.      * If you do, only the last one will take affect. 
  4.      *  
  5.      * Notice you are using the same request id. 
  6.      */  
  7.     public void scheduleSameIntentMultipleTimes()  
  8.     {  
  9.         //Get the instance in time that is   
  10.         //30 secs from now.  
  11.         Calendar cal = Utils.getTimeAfterInSecs(30);  
  12.         Calendar cal2 = Utils.getTimeAfterInSecs(35);  
  13.         Calendar cal3 = Utils.getTimeAfterInSecs(40);  
  14.         Calendar cal4 = Utils.getTimeAfterInSecs(45);  
  15.           
  16.         //If you want to point to 11:00 hours today.  
  17.         //Calendar cal = Utils.getTodayAt(11);  
  18.           
  19.         //Get an intent to invoke  
  20.         //TestReceiver class  
  21.         <span style="color:#FF0000;">Intent intent = new Intent(mContext, TestReceiver.class);  
  22.         intent.putExtra("message""Single Shot Alarm");</span>  
  23.         <span style="color:#FF0000;">PendingIntent pi = this.getDistinctPendingIntent(intent, 1);</span>  
  24.           
  25.         // Schedule the alarm!  
  26.         AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);  
  27.           
  28.         am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);  
  29.         am.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), pi);  
  30.         am.set(AlarmManager.RTC_WAKEUP, cal3.getTimeInMillis(), pi);  
  31.         am.set(AlarmManager.RTC_WAKEUP, cal4.getTimeInMillis(), pi);  
  32.     }  
      上面这部分代码,使用了同一个PendingIntent,设置了4个不同的闹钟时间,这样的效果就是: 只有最后一个闹钟会被触发,前面的所有闹钟都会被忽略掉。

而要实现多个闹钟的实现是如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.      * Same intent can be scheduled multiple times 
  3.      * if you change the request id on the pending intent. 
  4.      * Request id identifies an intent as a unique intent. 
  5.      */  
  6.     public void scheduleDistinctIntents()  
  7.     {  
  8.         //Get the instance in time that is   
  9.         //30 secs from now.  
  10.         Calendar cal = Utils.getTimeAfterInSecs(30);  
  11.         Calendar cal2 = Utils.getTimeAfterInSecs(35);  
  12.         Calendar cal3 = Utils.getTimeAfterInSecs(40);  
  13.         Calendar cal4 = Utils.getTimeAfterInSecs(45);  
  14.           
  15.         //If you want to point to 11:00 hours today.  
  16.         //Calendar cal = Utils.getTodayAt(11);  
  17.   
  18.         //Get an intent to invoke  
  19.         //TestReceiver class  
  20.         Intent intent = new Intent(mContext, TestReceiver.class);  
  21.         intent.putExtra("message""Single Shot Alarm");  
  22.   
  23.         // Schedule the alarms!  
  24.         AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);  
  25.           
  26.         am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), getDistinctPendingIntent(intent,1));  
  27.         am.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), getDistinctPendingIntent(intent,2));  
  28.         am.set(AlarmManager.RTC_WAKEUP, cal3.getTimeInMillis(), getDistinctPendingIntent(intent,3));  
  29.         am.set(AlarmManager.RTC_WAKEUP, cal4.getTimeInMillis(), getDistinctPendingIntent(intent,4));  
  30.     }  
      每个挂起的Intent,也就是PendingIntent不同,也就是让每个PendingIntent的RequestId不同。产生这种原因是因为在AlarmManager中设置闹钟时,对于相同的Intent,是通过不同的请求Id来创建的。

    在相同类型的Intent上设置闹钟时,只有最后一个闹钟时生效的。

     以下是AlarmMangerService的部分源码,可以看到为什么不能使用相同的PendingIntent了。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void setRepeating(int type, long triggerAtTime, long interval,   
  2.             PendingIntent operation) {  
  3. .....  
  4. synchronized (mLock) {  
  5.           <span style="color:#FF0000;">  Alarm alarm = new Alarm();  
  6.             alarm.type = type;  
  7.             alarm.when = triggerAtTime;  
  8.             alarm.repeatInterval = interval;  
  9.             alarm.operation = operation;</span>  
  10.   
  11.             // Remove this alarm if already scheduled.  
  12.             <span style="color:#FF0000;">removeLocked(operation);</span>  //当使用相同的operation的时候u,就会先把已有的删除,这样的话,直到最后一个才会生效。  
  13.   
  14.             if (localLOGV) Slog.v(TAG, "set: " + alarm);  
  15.   
  16.             int index = addAlarmLocked(alarm);  
  17.             if (index == 0) {  
  18.                 setLocked(alarm);  
  19.             }  
  20.         }  
  21.     }  


最后一点是关于闹钟的持久化问题,它们是不能保存到设备重新启动之后,也就是说当设备重新启动后,之前设置的闹钟将全部失效。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值