Android闹钟,Android AlarmManager使用心得

做了个系统应用闹钟,记录下,防止再次踩坑,分别有三种闹钟.单次,每天重复,周期性,比如周一,周二周三触发,这种.

具体的关键实现,方法里面都有注释,上个效果图:工作日暂无实现。

//单次闹钟,只会触发一次
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);
    }

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值