使用AlarmManager在特定时间每天重复发送Android通知

3

我需要安卓应用程序在每天早上8点、下午3点和晚上8点提醒用户,所以我在MainActivity的onCreate()函数中使用了以下三行代码。然而,当我运行应用程序时,所有三个通知都一次性地出现了,而不是在想要的时间出现。

    setRepeatedNotification(1,8,0,0); 
    setRepeatedNotification(2,15,0,0); 
    setRepeatedNotification(3,20,0,0);    

为什么会这样呢?我在此处附上setRepeatedNotification函数。谢谢!
private void setRepeatedNotification(int ID, int hh, int mm, int ss) {
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ID, alarmIntent, 0);

    Calendar calendar = Calendar.getInstance();
   // calendar.set();
    calendar.set(Calendar.HOUR_OF_DAY, hh);
    calendar.set(Calendar.MINUTE, mm);
    calendar.set(Calendar.SECOND, ss);

    // Clear previous everyday pending intent if exists.
    if (null != mEverydayPendingIntent) {
        alarmManager.cancel(mEverydayPendingIntent);
    }
    mEverydayPendingIntent = pendingIntent;
    alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mEverydayPendingIntent);
}

1
在你的setRepeating方法中,使用AlarmManager.RTC_WAKEUP而不是AlarmManager.RTC。 - Jay Shah
AlarmReceiver 是如何设置的? - Si8
2个回答

9
以下是更新后的代码:
private void setRepeatedNotification(int ID, int hh, int mm, int ss) {
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    Intent alarmIntent = new Intent(StartActivity.this, AlarmReceiver.class);
    alarmIntent.putExtra("ID",ID);
    Log.d("setRepeatedNotification", "ID:" + ID);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(StartActivity.this, ID, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Calendar calendar = Calendar.getInstance();
    Calendar now = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, hh);
    calendar.set(Calendar.MINUTE, mm);
    calendar.set(Calendar.SECOND, ss);

    //check whether the time is earlier than current time. If so, set it to tomorrow. Otherwise, all alarms for earlier time will fire

    if(calendar.before(now)){
        calendar.add(Calendar.DATE, 1);
    }

    mEverydayPendingIntent = pendingIntent;
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mEverydayPendingIntent);



}

我们可以使用“calendar”对象本身,而不是使用“now”对象,你知道吗? - Learning

6
我看到你的AlarmManager设置存在两个潜在问题。第一个问题出现在设备进入休眠时。
从AlarmManager的文档中可以看到:
如果闹钟被延迟(例如由于非_WAKEUP类型的系统睡眠),则被跳过的重复将尽快传递。此后,将根据原始计划表传递将来的警报;它们不会随时间漂移。例如,如果您设置了每小时顶部的重复闹钟,但是电话从7:45到8:45处于未唤醒状态,则会在电话苏醒后立即发送警报,然后下一个警报将在9:00发送。
因此,如果您设置了闹钟并且设备已经进入休眠,没有使用AlarmManager.RTC_WAKEUP,取决于设备处于休眠状态多长时间,可能会有很长时间的延迟。如果您从未触摸过您的设备,也没有其他闹钟引起唤醒,它可能会导致所有闹钟在设备下一次唤醒的小时内堆积。
另一个潜在问题是,您正在检索代表当前时间的Calendar实例,但然后自己设置小时,分钟和秒。当前日期和当前年份已经根据当前时间自动填充。
同样,从文档中可以看到:
如果所述触发器时间在过去,则根据触发时间相对于重复间隔的距离,立即触发警报。
在这种情况下,如果您的方法在给定日期的晚上8点后被调用,calendar.getTimeInMillis()会返回已经过去的时间戳,导致所有三个闹钟立即触发,因为8 am、3 pm和8 pm已经过去了。在这种情况下,您必须首先评估当前时间是否超过您尝试设置的闹钟间隔,并将1天添加到您正在设置的时间中,以确保闹钟已在未来设置好。

Yu,你是如何设置它的?你能分享一下AlarmReceiver代码吗?我的立即触发了,我猜测是由于@initramfs最后的评论引起的。 - Si8
@initramfs,http://stackoverflow.com/questions/40819966/how-to-set-alarm-for-notification-twice-a-day 你能否请看一下。 - Si8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接