您的位置:首页 > 移动开发 > Android开发

源码android6.0 系统应用时钟--详细的闹钟分析

2017-04-05 10:57 281 查看
共勉----不积跬步,无以至千里。

一、时钟整体看

注册表信息:

权限调用:

        开机启动的广播              RECEIVE_BOOT_COMPLETED

        屏幕保持唤醒                WAKE_LOCK

        手机震动                    VIBRATE

        修改全局系统设置            WRITE_SETTING

        禁用键盘锁                  DISABLE_KEYGUARD

        读写手机状态和身份          READ_PHONE_STATE

        允许访问底层电源管理        DEVICE_POWER

        读写外存储                  READ_EXTERNAL_STORAGE

<application/>中用到了android:uiOptions=”splitActionBarWhenNarrow”为屏幕较小分配较好的空间

 

时钟整体的设计:

ActionBar+ViewPager+Fragment

入口类DeskClock(不全面)

Activity生命周期来说:

onCreate:

1、 利用了Action判断显示到哪个Tab中,默认为时间界面

2、 InitViews方法对控件的初始化

3、 TabAdapter为适配器,其中ActionBar有一个AddTab(动态增加Tab方法)

4、 SetHomeTimeZone方法:

onPrepareOptionsMenu动态添加选项菜单:每点击一下去刷新一下菜单,本身有设置(夜间、帮助被隐藏了)——个人项目需求

摘要:

Android系统闹钟定时功能框架,总体来说就是用数据库存储定时数据,有一个状态管理器这些定时状态的触发和更新都交给它来处理,他就像电脑的CPU、人的大脑。像闹钟这种应用程序,每天重复定时,或者一周选择其中几天,闹钟响了5分钟后,再次响铃,这时候就需要一种好的办法来管理这些数据和状态,下面就来分析一下Android系统闹钟的具体实现。

二、时钟之闹钟

1、 基本结构

Alarm代表一条定时数据

AlarmInstance代表一条定时项目的实例,一个AlarmInstance对应一个alarm但比Alarm多了更多的状态信息

AlarmStateManager状态管理器,对定时项目进行调度,添加、删除、更改状态,是一个广播类,定时到点后发广播到这里,进行下一步处理。

AlarmService响应结果,也就是定时到达后要做的事,响铃、停止铃声

ClockDataHelper里面创建了三个表,ALARMS_TABLE,INSTANCE_TABLE,CITIES_TABLE前两个分别对应上面的Alarm和AlarmInstance

ClockDataHelper类中的三个表:Alarm表、AlarmInstance表、Cityies表

代码示例:



                             本地数据库创建的Alarms表

代码示例:



                             本地数据库创建的Alarminstance表

代码示例:



                             本地数据库创建的Cities表

这里说一下几个特殊的字段,对Alarm表,DAYS_OF_WEEK表示一周内需要定时的天(闹钟有一个功能就是选择一周的几天,这里是int值,用位来表示设置的天数,而provider包下有个专门的类Daysofweek来存储和处理

AlarmInstance表中一个Alarm_IO,关联到一个Alarm,可以看到在AlarmInstance表里也有时间,其中这两个时间是不一样的,Alarm表示原始的定时,一个不变的数据,而AlarmInstance则代表了一个使用中的定时项目,或者是一个随时间变化的数据。它的时间是变化的,比如闹钟响了以后延时10分钟,再响就需要改变这里的时间,而基础数据不能变,还需要显示在那里。Alarm_state代表了当前定时项目的状态,具体都是由AlarmStateManager来管理的

要想了解闹钟呢,就要先了解这几个类

1、 Alarm类

这个类是Alarm信息对于数据库的增删改查操作



还有一个就是创建AlarmInstance方法



AlarmInstance类和alarm类一样,他也有对于数据库的增删改查等操作、因为其时间上是动态的因此多了set、get方法





时间上的处理方法:

设置:



获取:



闹钟的几种状态

SILENT_STATE,alarm被激活,但是不需要显示任何东西,下一个状态是LOW_NOTIFICATION_STATE;
LOW_NOTIFICATION_STATE,这个状态表示alarm离触发的时间不远了,时间差是AlarmInstance.LOW_NOTIFICATION_HOUR_OFFSET=-2,也就是2个小时。下一个状态会进入HIGH_NOTIFICATION_STATE,HIDE_NOTIFICATION_STATE,DISMISS_STATE;
HIDE_NOTIFICATION_STATE,这是一个暂时态,表示用户想隐藏掉通知,这个状态会一直持续到HIGH_NOTIFICATION_STATE;
HIGH_NOTIFICATION_STATE,这个状态和LOW_NOTIFICATION_STATE相似,但不允许用户隐藏通知,负责触发FIRED_STATE或者DISMISS_STATE;它的触发时间为30分钟之前
SNOOZED_STATE,像HIGH_NOTIFICATION_STATE,但是会增加一点定时的时间来完成延迟功能;
FIRED_STATE,表示响铃状态,会启动AlarmService直到用户将其变为SNOOZED_STATE或者DISMISS_STATE,如果用户放任不管,会之后进入MISSED_STATE;
MISSED_STATE,这个状态在FIRED_STATE之后,会在通知栏给出一个提醒刚才响铃了;
DISMISS_STATE,这个状态表示定时结束了,会根据定时项目的设置判断是否需要重复,从而决定要删除这个项目还是继续设定一个新的定时。

界面分析

AlarmClockFragment的界面功能分析(从生命周期上分析)

1、OnCreateView

解析Fragment

从Bundle中获取数据:传递了几个参数

startCreatingAlarm方法:创建一个TimePickerDialog,设置闹钟时间,创建一个Alarm实体对象,根据RingtoneManager铃声管理对象获得一个默认铃声的uri,并对Alarm对象进行属性设置

1、 OnResume方法

1、 检查是否有别的app是否有请求到这,去创建一个闹钟,然后清空这个intent

2、 是否从deskclock界面滚到alarm假面的(更新到最新的数据界面)

3、  OnDestroy

    对于对创建的ToastMaster.cancelToast()将Toast置空

onActivityResult:

对在另一个Activity中获取的铃声uri进行设置显示,并把这个铃声设置成默认铃声

bindView方法(Adapter的方法)

1、利用持有者优化、以及对于tag的判空对ListView的优化

  2、expandAlarm对于item中扩展方法

  3、以及对其中控件重复的处理

      对这重复中的处理两种方式 1、对存储状态的获取,然后进行设置

                                2、对其中重复中的控件的监听方法的设置

                                3、对于扩展与收缩的动画的处理

                                4、对其中注册了一个监听视图树的观察者模式

创建一个闹钟的步骤

1、 AlarmClockFragment中的onCreateView方法

 


2、 AlarmClockFragment中的startCreatingAlarm()

 


3、 AlarmClockFragment中的asyncAddAlarm(a)

 






4、 AlarmClockFragment中的setupAlarmInstance方法

 


5、AlarmStateManager的registerInstance()

因为其中要对Alarminstance中State状态判断,但是还没有状态就进入到了else中

 




 

5、 AlarmStateManager的setSilentState方法

 这里就是AlarmStateManager对这些状态的处理要,同时会规划一个定时转换成下一个状态。

 


从这可以看出这个状态将要由silentState——》Low_NoTIFICATION_State,而这个状态是从AlarmInstance中得到的可见为AlarmInstance.getLowNoticationTime()得到的;

 


6、 AlarmStateManager的scheduleInstanceStateChange方法

更新AlarmInstance的状态 信息,通过此方法规定下一个状态

 


在createStateChangeIntent方法中设置了intent中的state属性为Low_NOTIFICATION,并传递了两个属性用户onReceive中的处理属性为:ALARM_GLOBAL_ID_EXTRA、ALARM_STATE_EXTRA

 


7、 AlarmStateManager的onReceiver方法

其为了来接收规划好的推迟Intent的广播,LOW_NOTIFICATION_HOUR_OFFSET值为-2,其在前面可以看出将要在闹钟响之前的前两个小时就会发出这个延迟的广播意图,然后AlarmStateManager将会把这个状态改变为下一个状态

 


其处理方法在HandleIntent方法中,经过处理将要转移到setAlarmState方法中

 


 


 


8、 AlarmStateManager的setAlarmState方法

 


 


9、对于每一个state将转移到相应的setXXXXState方法中,完成下一次状态的转换形成一个定时的循环,直到到达DiSSMISSED_STATE里停用或者删除定时的item,如果需要重复则会获取到下一次的定的时间

例如以下是:由Slience_STATE状态变为了LOW_NOTIFICATION状态,他将要进行下次的规划变为HIGH_NOTIFICATION状态,并且调用setLowNotificationState方法,具体看下面

 


其中的AlarmNotification.showLowPriorityNotification方法,将会在通知栏上创建一个通知,并为此通知设置了一个监测用户移除次通知Notification的事件

 


接下来就如所说,就是进入定时的循环。

如上,都是类同的,下面看一下FIRED_STATE:

开启了AlarmService,

 


就来到了AlarmService.startAlarm方法

 


查看onCommand方法,就会进入startAlarm方法

 


然后进入startAlarm方法中,就会进入到AlarmNotification.showAlarmNotification(this,mCurrentAlarm);

 


接下来就会进入到Notification中的showAlarmNotification方法,接下里就会看到睡眠的这个意图

 


同样下面还有一个消失的意图,还有设置满屏

 


1、当用户按了睡眠时,将会睡眠几分钟,关闭闹铃铃声和振动,将会设置新的闹钟时间,即为:现在时间+睡眠时间(设置那存储的Prefrence中取出),更新数据库中的AlarmInstance,并发送通知和下次的FIRED_STATE



2、用户直接关闭的话,就会进入到DisMiss_STATE状态将会执行unregisterInstance方法(下面介绍)和删除这个AlarmInstance和并根据用户是否设置重复更新下一个闹钟

 


Unregisterinstance方法,关闭铃声和振动等、移除所有和这个AlarmInstance有关的的计时器和通知,下图为其方法

 


3、用户如果不去管闹钟的如下图,会在Preference中获取到timeout的时间,然后去规范推迟意图成为Miss状态

 


这里为获取timeout的时间

 


查看SetMissState方法,将会停止闹钟服务,更新AlarmInstance的实例在数据库,发送通知,并规划推迟意图成为DIsMiss_STATE

 


同样会停止AlarmService的服务,并且会更新数据库中AlarmInstance的状态,并会发送Miss通知,

规划下一DissMissed的意图,并根据用户是否设置重复更新下一个闹钟。

小想法:闹钟声音设计,可以设计一个方法,让闹钟随着时间改变音量逐渐声音变大,叫醒沉睡者!

代码URL=http://download.csdn.net/download/wdyshowtime/9966509

观赏也是种力量,谢谢您的观看。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: