做了个系统应用闹钟,记录下,防止再次踩坑,分别有三种闹钟.单次,每天重复,周期性,比如周一,周二周三触发,这种.
具体的关键实现,方法里面都有注释,上个效果图:工作日暂无实现。
//单次闹钟,只会触发一次
public void setSingleAlarm(int clockId,int hour,int minute) {
Intent intent = new Intent();
intent.setAction(CommonConstant.ACTION_SINGLE_CLOCK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mActivity, clockId, intent, PendingIntent.FLAG_CANCEL_CURRENT);//以数据库id为标识,设置闹钟id(RequestCode)
AlarmManager alarmManager = (AlarmManager) mActivity.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
if (System.currentTimeMillis() > calendar.getTimeInMillis()) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
MagicLog.d("setSingleAlarm 闹钟超时,加一天:" + calendar.getTimeInMillis());
}
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
MagicLog.d("---setSingleAlarm ok:" + calendar.getTimeInMillis());
}
//每天都重复的闹钟
public void setRepeatAlarm(int clockId, int hour, int minute) {
Intent intent = new Intent();
intent.setAction(CommonConstant.ACTION_REPEAT_CLOCK);
intent.putExtra("clockId", clockId);
intent.putExtra("hour", hour);
intent.putExtra("minute", minute);
//PendingIntent 参数说明下,第2个参数RequestCode:就相当于闹钟id,唯一性的,要取消闹钟也要传相同的,或者重复设置相同的id会覆盖前一个闹钟
PendingIntent pendingIntent = PendingIntent.getBroadcast(mActivity, clockId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mActivity.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
//这里是关键,和当前系统时间对比,超了代表明天才触发闹钟加一天
if (System.currentTimeMillis() > calendar.getTimeInMillis()) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
MagicLog.d("setRepeatAlarm 闹钟超时,加一天:" + calendar.getTimeInMillis());
}
//android6.0后使用这个方法,精确的闹钟,别的方法达不到精确的目的
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
MagicLog.d("---setRepeatAlarm ok:" + calendar.getTimeInMillis());
}
/**
* 周期重复闹钟,支持多个周期组闹钟,
* 系统的Calendar对应的week星期
* 2:星期1 , 3星期2 , 4星期3, 5星期四, 6星期5, 7星期6, 1星期日
*
* @param dbDataId 数据id,如果有多个周期组闹钟的话,没有就随便传一个
*/
public void setPeriodAlarm(int dbDataId, int hour, int minute) {
//这里模拟星期数据->星期1-星期7
String[] period = new String[]{"2", "3", "4", "5", "6", "7", "1"};
//做周期闹钟的关键,是给每个星期都设置一个闹钟,比如闹钟是周1,周2,周3,那么就要设置3个闹钟,
//以PendingIntent.getBroadcast()的参数RequestCode来区分
for (int i = 0; i < period.length; i++) {
setPeriodAlarmAgain(dbDataId, Integer.parseInt(period[i]), hour, minute);
}
}
public void setPeriodAlarmAgain(int dbDataId, int week, int hour, int minute) {
Intent intent = new Intent();
intent.setAction(CommonConstant.ACTION_PERIOD_CLOCK);
//此处闹钟id = 数据库id + 周期, 如果有多个周期组闹钟, 就可以代表唯一性,方便覆盖或者关闭闹钟
int clockId = dbDataId + week;
intent.putExtra("dbDataId", dbDataId);
intent.putExtra("week", week);
intent.putExtra("hour", hour);
intent.putExtra("minute", minute);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mActivity, clockId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mActivity.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
//这里关键,要给闹钟的时间设置week
calendar.set(Calendar.DAY_OF_WEEK, week);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
//这里也是关键,超过闹钟时间了,代表下周要触发,加7天
if (System.currentTimeMillis() > calendar.getTimeInMillis()) {
calendar.add(Calendar.DAY_OF_MONTH, 7);
MagicLog.d("setPeriodAlarmAgain 闹钟超时,加7天:" + calendar.getTimeInMillis());
}
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
MagicLog.d("---setPeriodAlarmAgain ok:" + calendar.getTimeInMillis());
}
然后是触发的地方接收,处理自己的事情:
//注册Receiver
private void initWatchReceiver() {
IntentFilter filter = new IntentFilter();
//此处3个Action自己随便定义字符串
filter.addAction(CommonConstant.ACTION_SINGLE_CLOCK);//单次闹钟
filter.addAction(CommonConstant.ACTION_REPEAT_CLOCK);//重复闹钟
filter.addAction(CommonConstant.ACTION_PERIOD_CLOCK);//周期闹钟
WatchReceiver mWatchReceiver = new WatchReceiver();
registerReceiver(mWatchReceiver, filter);
}
class WatchReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (CommonConstant.ACTION_SINGLE_CLOCK.equals(intent.getAction())) {
//单次闹钟
MagicLog.d("---单次闹钟触发 ACTION_SINGLE_CLOCK");
//do something
} else if (CommonConstant.ACTION_REPEAT_CLOCK.equals(intent.getAction())) {
//每天的重复闹钟
MagicLog.d("---REPEAT 闹钟触发 ACTION_REPEAT_CLOCK");
//do something
int clockId = intent.getIntExtra("clockId", -2);
int hour = intent.getIntExtra("hour", -2);
int minute = intent.getIntExtra("minute", -2);
MagicLog.d("--REPEAT 接收clockId:" + clockId + "---hour:" + hour + "---minute:" + minute);
//再次设置闹钟
setRepeatAlarm(clockId, hour, minute);//触发后,再次设置,达到重复的目的
} else if (CommonConstant.ACTION_PERIOD_CLOCK.equals(intent.getAction())) {
//周期闹钟
MagicLog.d("---PERIOD 闹钟触发 ACTION_PERIOD_CLOCK");
//do something
int dbDataId= intent.getIntExtra("dbDataId", -2);
int week = intent.getIntExtra("week", -2);
int hour = intent.getIntExtra("hour", -2);
int minute = intent.getIntExtra("minute", -2);
MagicLog.d("--PERIOD 接收dbDataId:" + dbDataId+ "---week:" + week + "---hour:" + hour + "---minute:" + minute);
//再次设置闹钟
setPeriodAlarmAgain(dbDataId, week, hour, minute);
}
}
}
最后就是取消闹钟了
/**
* @param clockId 这个id就是自己的逻辑id了,自己定义好,比如我这闹钟实体存放在数据库的,就以数据库id为准,能够确保唯一性
*/
public void cancelClockAlarm(int clockId) {
realCancelClock(CommonConstant.ACTION_SINGLE_CLOCK, clockId);
realCancelClock(CommonConstant.ACTION_REPEAT_CLOCK, clockId);
//周期
String[] period = new String[]{"2", "3", "4", "5", "6", "7", "1"};
for (int j = 0; j < period.length; j++) {
//此处闹钟id = 数据库id+周期,代表唯一性
realCancelClock(CommonConstant.ACTION_PERIOD_CLOCK, clockId + Integer.parseInt(period[j]));
}
}
private void realCancelClock(String action, int clockId) {
Intent intent = new Intent();
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mActivity, clockId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mActivity.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
MagicLog.d("取消闹钟" + clockId);
}