android 4.4.4 系统原生闹钟源码解析(附源码)

最近看了一下android 4.4系统原生闹钟的代码,做个总结。并将源码提取出,做了些精简,重新组织打包,这样可直接运行安装,也不与手机自带冲突,方便学习。原生闹钟,十分稳定,可能的冲突事件都考虑并处理,只要美化 界面,就是个不错的闹钟Apk.  

                             

   进入正题,如何写一个闹钟应用,需要考虑哪些。我从以下几点做个简单介绍。
   1.闹钟实现原理,如何实现动作定时触发?
   2.闹钟alarm如何设置,包含哪些元素?
   3.如何管理闹钟设置-alarm?
   4.如何管理一个闹钟事件-alarmInstance?
  5.举例分析,如何实现一个闹钟在每周一,周三,早上8点响起?
  6.开关机,时区时间改变,来电等冲突事件都做哪些处理?

针对以上问题,详细介绍如下。只介绍大致流程,处理细节请阅读代码,注释已十分详尽。
      
1.闹钟实现原理,如何实现动作定时触发?
  1. <span style="font-size:14px;"><span style="font-size:14px;">Intent stateChangeIntent = createStateChangeIntent(context,  
  2.                 ALARM_MANAGER_TAG, instance, newState);  
  3.         PendingIntent pendingIntent = PendingIntent.getBroadcast(context,  
  4.                 instance.hashCode(), stateChangeIntent,  
  5.                 PendingIntent.FLAG_UPDATE_CURRENT);  
  6.         AlarmManager am = (AlarmManager) context  
  7.                 .getSystemService(Context.ALARM_SERVICE);  
  8.   
  9.         if (Utils.isKitKatOrLater()) {   //这里需要做个判断,android 4.4之后接口有变化        
  10.             am.setExact(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);  
  11.         } else {  
  12.             am.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);  
  13.         }</span></span>  
       通过上述方法,可在指定时间使pendingIntnet发送广播,然后程序实现BrodcastReceiver,接收此广播;
       这样就可在指定时间,作出动作;

2.闹钟alarm如何设置,包含哪些元素?


     
  一条闹钟设置alarm包含:时间设置(几点几分),标签(名字),重复(是否单次使用),重复日期,是否振动,铃声设置;
  
其中重复日期设置--daysofweek,  源码中的设计如下,通过一个整数表示所有情况:
  1111111:通过移位与或运算来确定某天是否被选中;
  Days of week code as a single int.
  0x00(0000000): no day
  0x01(0000001): Monday
  0x02(0000010) :Tuesday
  0x04(0000100): Wednesday
  0x08(0001000): Thursday
  0x10(0010000): Friday
  0x20(0100000): Saturday
  0x40(1000000): Sunday
  0x7f(1111111) :Everyday

这样假如星期一,星期三被选中,就是0000101;
周一周三八点闹钟设置为:hour=8,minute=0, daysofweek=5,enabled=true; 
 
 3.如何管理闹钟设置-alarm?
     当然数据库,原生又实现了contentProvider,通过uri进行添加,删除,更新。体现了android的统一性;
     这个自己看代码;

  4.如何管理一个闹钟事件-alarmInstance?
      每一个生效的闹钟设置-alarm,会生成一个闹钟事件-alarmInstance;  一个闹钟事件对应一个生效闹钟(alarm.enabled=true);
      一个闹钟事件包括:
     1.  alarmTime(闹钟触发时间,根据alarm设置结合当前时间计算而来)
     2. state( 闹钟事件状态),源码中一个闹钟事件分为7个状态;
       状态流程:
举例:设置闹钟时间为8点整,则产生一个闹钟事件-alarmInstance 的alarmTime为8点;
(1)SILENT_STATE:(6:00点以前,没有任何提示); 
下一状态为:LOW_NOTIFICATION_STATE  
(2)LOW_NOTIFICATION_STATE(6:00-7:30,通知栏有提示预定闹钟,通知可去除)
下一状态为:HIGH_NOTIFICATION_STATE
(3)HIGH_NOTIFICATION_STATE(7:30-7:59,通知栏有提示预定闹钟,通知不可去除)
下一状态为:FIRED_STATE
(4)FIRED_STATE(8:00,闹钟触发)
下一状态为:SNOOZE_STATE(选择稍后再响) 或 DISMISSED_STATE(选择关闭)或 MISSED_STATE
(未做任何操作,直到响声结束)
(5)SNOOZE_STATE(8:00--设置的暂停时间,闹钟暂停)
下一状态为:FIRED_STATE
(6)MISSED_STATE(闹钟响起无任何操作,设置的闹钟响起时间过后,通知栏提示错过闹钟);
下一状态为:DISMISSED_STATE
(7)DISMISSED_STATE(闹钟关闭)
    
如何管理闹钟事件alarmInstance状态:
         结合上边第一条定时触发原理,写一个BroadcastReceiver类----AlarmStateManager,负责接收广播,并改变闹钟事件的状态;
       比如现在是7:50,设置的闹钟是8点;于是产生一条闹钟事件alarmInstance,根据规则判断当前状态为 HIGH_NOTIFICATION_STATE,然后调用am.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);使其在8:00发送广播,intent包含要alarmInstance设置的状态(FIRED_STATE),同时再次调用上述方法(alarmManager.set)发送广播包含要alarmInstance设置的(MISSED_STATE);
       若闹钟响起时用户选择稍后响起,此时关闭当前闹钟,并将闹钟事件alarmInstance的状态设置为SNOOZE_STATE,调用(alarmManager.set),设置下次状态为FIRED_STATE;
        若闹钟响起时用户选择关闭,则关闭当前闹钟,删除此闹钟事件alarmInstance;  同时通过此闹钟事件对应的闹钟设置alarm,根据其重复日期,计算下次闹钟事件时间,并生成新的alarmInstance,设置其初始状态,并调用(alarmManager.set),使其在指定时间收到广播并修改对应状态;
若闹钟响起,用户不做任何操作,则到时会接收到之间预发送的广播,并将闹钟事件状态设置为MISSED_STATE;

   alarmInstance也是用数据库,然后实现contentProvider,通过uri进行添加,删除,更新。

5.举例分析,如何实现一个闹钟在每周一,周三,早上8点响起?
     
假设现在是周一7点50:
      1.增加闹钟设置alarm:  hour=8,minute=0; repeat=true; daysofweek=5 (0000101); enabled=ture;
      2.生成闹钟事件alarmInstance :  alarmTime=今天8点, state=HIGH_NOTIFICATION_STATE( 当前状态);
      3.通过alarmManager.set发送定时广播,pendingIntent中包含下次触发的状态为FIRED_STATE
      4.时间到,alarmStateManager收到广播播放铃声;此时选择关闭闹钟;此闹钟事件alarmInstance结束删除,然后根据对应alarm是计算得出下次闹钟时间是周三8点;于是生成新的闹钟事件alarmInstance : alarmTime=周三8点,state=SILENT_STATE;通过alarmManager.set发送定时广播,包含下次要触发的状态,循环······

6.开关机,时区saf时间改变,来电等冲突事件都做哪些处理?
  
1.重新开机后,之前闹钟事件发出的定时广播全部失效;所以要接受开机广播,然后根据alarm设置调整每个alarmInstance的状态,并重新发送定时广播;
    其余就不在啰嗦啦,具体看代码吧;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 4.4.4 系统中,你可以使用以下代码来格式化 SD 卡: ```java import android.os.Environment; import android.os.storage.StorageManager; import android.os.storage.StorageVolume; import java.io.File; import java.lang.reflect.Method; public class SDCardUtils { public static void formatSDCard() { File sdCard = Environment.getExternalStorageDirectory(); StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE); Class<?> storageVolumeClazz = null; try { storageVolumeClazz = Class.forName("android.os.storage.StorageVolume"); Method getVolumeList = storageManager.getClass().getMethod("getVolumeList"); Method getUuid = storageVolumeClazz.getMethod("getUuid"); Method getPath = storageVolumeClazz.getMethod("getPath"); Method format = storageManager.getClass().getMethod("format", String.class); Object[] storageVolumes = (Object[]) getVolumeList.invoke(storageManager); for (Object storageVolume : storageVolumes) { String path = (String) getPath.invoke(storageVolume); if (path.equals(sdCard.getAbsolutePath())) { String uuid = (String) getUuid.invoke(storageVolume); format.invoke(storageManager, uuid); break; } } } catch (Exception e) { e.printStackTrace(); } } } ``` 请注意,这段代码中使用了反射来调用隐藏的 API。在 Android 4.4.4 中,这是一种常见的处理方式。然而,从 Android 5.0(API 级别 21)开始,该方法已被标记为不推荐使用,并且在 Android 10(API 级别 29)中已被移除。因此,在较新的 Android 版本中,你可能需要使用其他方法来格式化 SD 卡。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值