一、需求介绍
不日前项目有个需求,做个提醒功能,类似市面上闹钟功能。下面附上需求界面
首先对需求进行解析,基本上就是闹钟的功能,只不过简化了一点,就是只有两个闹钟,一个是接小孩上学闹钟提醒,一个是接小孩子放学闹钟提醒。其实功能很鸡肋,完全可以使用系统自带的闹钟代替。但某种程度来说,产品的体验还是用户说了算,站在开发者的角度是不全面且不适合的,于是开始demo之旅了。
二、需求实现原理
基本实现一个需求不会从头开始,从头开始开发周期太长,试错时间成本太高(个人是建议不断的试错),都会找些开源的框架或源码二次开发。既然确定是类似闹钟,就从闹钟原理开始着手。进行一轮百度后,比较合适的基本上是使用AlarmManager的set(int
type, long triggerAtTime, PendingIntent operation)或setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)
type:
AlarmManager.RTC,硬件闹钟,不唤醒手机(也可能是其它设备)休眠;当手机休眠时不发射闹钟。
AlarmManager.RTC_WAKEUP,硬件闹钟,当闹钟发躰时唤醒手机休眠;
AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒手机休眠;当手机休眠时不发射闹钟。
AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,当闹钟发躰时唤醒手机休眠;
triggerAtTime:发生闹钟的时间戳
operation:传入itent,接收的receiver
interval:重复的时间差(毫秒)
下面是set方法使用例子,setRepeating也差不多
Calendar mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(System.currentTimeMillis()+60*1000);//60s后触发
Intent intent = new Intent(AlarmsSetting.ALARM_ALERT_ACTION);
intent.putExtra("type", type);
intent.setClass(context, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, type, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.set(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pi);
alarmsSetting.setNextAlarm(mCalendar.getTimeInMillis());
从网上找了几个闹钟的Demo,有些确实简单,就单单设置了一个闹钟,改造的工作量太大就算了。有些功能确实很齐全,基本和系统闹钟无异,但实现逻辑很复杂,要整合进项目也可以,不过后期维护就比较麻烦,还不如自己从头开发,发现有些工作量,但可以接受。既然核心原理确定了,那就开始真正的开发了。
三、具体实现
UI部分
开关,时间的控件就不说了,大同小异,基本是这样。
比较烦的就是周期记录了,如果从星期一到星期天都进行记录,额。。。那太麻烦了。还不如用排列进行缓存,既有2的7次方128种排列(用二进制进行模拟)。使用Gridview展现,根据postion的值进行对应的调整。如下:
比如我选择了三、五、六,对应的二进制就是0001011=104
当点击五的时候,此时postion=5, 0001011-1<<5 = 0001001。
继续点击二的时候,此时postion=2,0001001+1<<2 = 0011001
类似原理进行数据存储。
代码逻辑部分
一般闹钟是使用sqlite进行数据存储的,但由于只有两个闹钟,数据量比较少,没必要那么麻烦,所以使用SharedPreference。
然后就是关键部分了,如何实现下一次循环是个大问题,这部分做得不好,直接影响程序质量。做法是:
设定闹钟----->闹钟触发----->计算下一次闹钟----->设置下一次的闹钟
基本上是这样循环,看似简单,但实际开发却遇到不少麻烦!
四、主要遇到问题
1、计算下一次闹钟时,需要考虑年、月的进位的情况。(对种种情况的考虑对以后的修仙道路是有帮助的)
2、如果设置的时间比当前系统时间早,也会响。
3、如果已经设置了闹钟,再去调整时间到比闹钟时间晚。虽然已经做了对android.intent.action.TIME_SET情况的过滤,但还是会触发闹钟的。原因是先设置了闹钟Receive,时间一改变,闹钟的Receive肯定比TIME_SET的Receive早,故而先执行。
4、开机、时区、时间重置的情况要考虑;
五、进程守护
以上问题都解决了,还有些小问题就不说了。其实主要的难点在于如何计算下一次的闹钟时间,也是程序是否可用的重点。
源码
四、主要遇到问题