简体   繁体   English

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

[英]Android daily repeating notification at specific time of a day using AlarmManager

I need to the Android app to send notification to remind users at 8am, 3pm and 8pm every day. 我需要Android应用程序发送通知,以便在每天上午8点,下午3点和晚上8点提醒用户。 So I use the following three lines in onCreate() of the MainActivity, when the application starts. 因此,当应用程序启动时,我在MainActivity的onCreate()中使用以下三行。 However, when I run the app, all three notification are coming at once instead of at the wanted time. 但是,当我运行应用程序时,所有三个通知都会立即发生,而不是在需要的时间。

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

Why is that? 这是为什么? I also attach the setRepeatedNotification function here. 我还在这里附加了setRepeatedNotification函数。 Thank you! 谢谢!

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);
}

I see two potential problems with your setup with AlarmManager. 我看到你使用AlarmManager设置的两个潜在问题。 The first arises when the device goes to sleep. 第一个出现在设备进入睡眠状态时。

From AlarmManager's documentation: 从AlarmManager的文档:

If an alarm is delayed (by system sleep, for example, for non _WAKEUP alarm types), a skipped repeat will be delivered as soon as possible. 如果警报延迟(例如,通过系统休眠,对于非_WAKEUP警报类型),将尽快传递跳过的重复。 After that, future alarms will be delivered according to the original schedule; 之后,将根据原计划发送未来的警报; they do not drift over time. 他们不随时间漂移。 For example, if you have set a recurring alarm for the top of every hour but the phone was asleep from 7:45 until 8:45, an alarm will be sent as soon as the phone awakens, then the next alarm will be sent at 9:00. 例如,如果您在每小时的顶部设置了定期闹钟,但手机在7:45至8:45之间处于睡眠状态,则一旦手机唤醒就会发出警报,然后将在下一次发出警报9:00。

As you can see, if you've set an alarm and the device has gone to sleep, without using AlarmManager.RTC_WAKEUP there could be a long delay depending on how long the device has been in sleep for. 如您所见,如果您已设置闹钟并且设备已进入休眠状态,而不使用AlarmManager.RTC_WAKEUP则可能会有很长的延迟,具体取决于设备处于休眠状态的时间。 If you've never touched your device and no other alarms caused a wakeup, it could cause all your alarms to stack up upon the next hour that the device is awake for. 如果您从未接触过设备,并且没有其他警报导致唤醒,则可能导致所有警报在设备清醒的下一个小时内堆叠起来。


Another potential issue I see is that you are retrieving a Calendar instance representing the time right now, but then setting the hour, minute and second by yourself. 我看到的另一个潜在问题是你正在检索一个代表现在时间的Calendar实例,然后自己设置小时,分钟和秒。 The current day and the current year have been automatically populated from the current time. 从当前时间开始自动填充当前日期和当前年份。

Again, from the documentation (emphasis mine): 再次,从文档(强调我的):

If the stated trigger time is in the past, the alarm will be triggered immediately , with an alarm count depending on how far in the past the trigger time is relative to the repeat interval. 如果指定的触发时间是过去的,则将立即触发警报 ,警报计数取决于过去触发时间相对于重复间隔的距离。

In this case, if your method was invoked past 8 pm on the given day, calendar.getTimeInMillis() will return a timestamp in the past for all three alarms, causing them to be triggered immediately since 8 am, 3 pm and 8 pm have already past in that day. 在这种情况下,如果您的方法是在给定日期的晚上8点之后调用的,则calendar.getTimeInMillis()将返回所有三个警报的过去时间戳,从而导致它们从上午8点,下午3点和晚上8点立即触发那天已经过去了 In this case, you must first evaluate whether the current time is past the alarm interval you are trying to set and add 1 day more onto the time you are setting to make sure the alarm has been set in the future. 在这种情况下,您必须首先评估当前时间是否超过您尝试设置的警报间隔,并在您设置的时间上再添加1天,以确保将来设置警报。

Here is the updated code: 这是更新的代码:

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);



}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM