Android 使用广播接收器安排重复警报

Android scheduling repeating alarms with broadcast receiver

我必须在一天的不同时间发送 3 个不同的通知(不同的内容)。 按照官方文档,https://developer.android.com/training/scheduling/alarms.html#type, 我能够在指定时间发送通知,但在更改每个通知的内容时遇到了一些麻烦。下面是设置通知的方法,在MainActivity的onCreate()方法中调用。

public void setNotification() {
    Intent intent = new Intent(this, MyBroadcastReceiver.class);
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    for (int id = 0; id < 3; id++) {
        Calendar calendar = Calendar.getInstance();
        // Defining different pendingIntent
        switch (id){
            case 0:
                calendar.set(Calendar.HOUR_OF_DAY, 9);
                break;
            case 1:
                calendar.set(Calendar.HOUR_OF_DAY, 14);
                break;
            case 2:
                calendar.set(Calendar.HOUR_OF_DAY, 20);
                break;
        }
        if(calendar.getTimeInMillis() < System.currentTimeMillis()){
            calendar.add(Calendar.DATE, 1);
        }
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, intent, 0);
        // setRepeating() schedules an alarm
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
    }
}

我知道我可以使用 Intent.putExtra() 功能发送数据,这些数据可用于识别意图,但如果应用程序被终止,这些数据将会丢失。 即使应用程序未 运行ning 或应用程序被杀死或设备已启动,我也希望它能正常工作。阅读之后,我发现我可以使用 BOOT_COMPLETE 侦听器在设备启动后设置警报。由于在 onCreate() 方法中设置了通知,所以每次我 运行 应用程序时都会出现通知,即使我尝试使用以下代码

来解决这个问题
if(calendar.getTimeInMillis() < System.currentTimeMillis()){
            calendar.add(Calendar.DATE, 1);
        }

目前的 onReceive 方法如下所示

public void onReceive(Context context, Intent intent) {

    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(context)
                    .setSmallIcon(R.mipmap.app_icon)
                    .setContentTitle("Title")
                    .setContentText("Message");
    Intent resultIntent = new Intent(context, MainActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(MainActivity.class);
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(resultPendingIntent);
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(0, mBuilder.build());
}

我需要帮助来决定我应该把 setNotification() 方法放在哪里,以便它一次性注册所有警报,以及如何识别即将到来的意图,以便采取适当的行动。一种方法是定义 3 个不同的 broadcastReceivers 和意图过滤器,并在创建它们时设置意图 URI。是正确的方法还是有其他简单的解决方法?

how to identify which intent is coming so that appropriate actions can be taken

您需要为 Intent 设置一个动作才能在 BroadcastReceiver 中接收数据

Intent intent = new Intent(this, MyBroadcastReceiver.class);
intent.setAction("THIS_IS_MY_ACTION");

BOOT_COMPLETE
取消所有开机报警,重新设置。取消闹钟 在 AlarmManager 上调用 cancel(),使用与您在使用 setRepeating() 设置闹钟时使用的相同 PendingIntent

使用 AlarmManager.

时注意 contextINTENT_FLAGS

使用 getApplicationContext() 作为上下文并保留 request_code 的记录,因为它们将在取消警报时使用,使用 PendingIntent.FLAG_UPDATE_CURRENT

这可能有帮助:-

PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), request_code, intent, PendingIntent.FLAG_UPDATE_CURRENT)

notification is appearing everytime I run the app,

使用 SharedPreference 进行检查,如果未完成则只设置一次。

还有你的代码

if(calendar.getTimeInMillis() < System.currentTimeMillis()){
    calendar.add(Calendar.DATE, 1);
}

应该有点像这样

Calendar calendar = Calendar.getInstance();
// Get the current time in millis
long currentTime = calendar.getTimeInMillis();
// Set the reminder times
switch(id) {
    ..
    ..
}
//Get the reminder time in millis
long intendedTime = calendar.getTimeInMillis();

if (intendedTime < currentTime) {
    // Set from next day and to repeat once a day.
    // you might consider using calendar.add() for adding one day to the current day

    calendar.add(Calendar.DAY_OF_MONTH, 1);
    intendedTime = calendar.getTimeInMillis();

    alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
            intendedTime, AlarmManager.INTERVAL_DAY, pendingIntent);
} else {
    // Set for today and to repeat once a day.
    alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, intendedTime,
            AlarmManager.INTERVAL_DAY, pendingIntent);
}