一直尝试使用系统的AlarManager来实现 "闹钟" 或 "定时服务" 功能
发现android L 优化过以后,有几点难点
1.无法精确到秒,系统的AlarManager有1-5分钟的延迟,查了API发现,是为了省电而设计的
2.无法取消,调用AlarManager.cancel无法取消闹铃,即使使用相同的pendingintent 依然无法取消,研究了很久还是取消不成功,下面是错误代码示例:
public static void cancelAlarm(Context context, int id) { // Intent intent = new Intent(context,LoongggAlarmReceiver.class); // PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); Intent intent = new Intent(ALARM_ACTION); intent.setClass(context,LoongggAlarmReceiver.class); intent.setData(Uri.parse("content://calendar/calendar_alerts/1")); PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent .FLAG_UPDATE_CURRENT );//FLAG_NO_CREATE , FLAG_CANCEL_CURRENT ,FLAG_UPDATE_CURRENT if(pi == null){ Log.e("AlarmManagerUtil","pi="+pi); return; } // PendingIntent pi = PendingIntent.getBroadcast(context, id, new Intent(context, LoongggAlarmReceiver.class), 0); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); am.cancel(pi); }
3.系统的AlarManager无法实现闹铃循环,虽然有setRepeating方法能循环,但无法适配所有型号手机的版本
public static void setAlarm(Context context, int flag, int hour, int minute, int id, int week, String tips, int soundOrVibrator) { AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Calendar calendar = Calendar.getInstance(); long intervalMillis = 5*60*1000; calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get (Calendar.DAY_OF_MONTH), hour, minute, 0); if (flag == 0) { intervalMillis = 0; } else if (flag == 1) { intervalMillis = 24 * 3600 * 1000; } else if (flag == 2) { intervalMillis = 24 * 3600 * 1000 * 7; } Intent intent = new Intent(ALARM_ACTION); intent.setClass(context,LoongggAlarmReceiver.class); intent.setData(Uri.parse("content://calendar/calendar_alerts/1")); intent.putExtra("intervalMillis", intervalMillis); intent.putExtra("msg", tips); intent.putExtra("id", id); intent.putExtra("soundOrVibrator", soundOrVibrator); PendingIntent sender = PendingIntent.getBroadcast(context, id, intent, PendingIntent .FLAG_UPDATE_CURRENT );//FLAG_UPDATE_CURRENT , FLAG_CANCEL_CURRENT if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // RTC_WAKEUP am.setWindow(AlarmManager.RTC_WAKEUP, calMethod(week, calendar.getTimeInMillis()), intervalMillis, sender); } else { if (flag == 0) { am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender); } else { am.setRepeating(AlarmManager.RTC_WAKEUP, calMethod(week, calendar.getTimeInMillis ()), intervalMillis, sender); } } }
4.当后台被杀死后,必须自己做守护进程,否则闹铃无法正常使用,这是非常致命的,因为一般android用户会经常清理后台软件, 如果你的项目里闹钟只是一个辅助功能,而不是核心,还要自己来写写守护进程,太麻烦了
下面为大家推荐一个github上的demo,实现一个非常全面的闹钟功能
https://github.com/CarloRodriguez/AlarmOn
1.实现了按星期选择闹铃是否启用
2.实现了闹铃循环
3.实现了精确到秒
4.实现了灭屏后,唤醒屏幕, 并调出自己的界面,让用户快捷点击按钮停止闹铃, 或稍后几分钟提醒我
5.实现了闹铃音量由小渐渐变大
6.能设置多个闹铃
7.对用户的闹铃设置,做了本地存储
8.自由调整震动及音乐,可选择SD卡上的音乐
Demo下载地址
demo截图示例: