如何将定时器列表适配到闹钟管理器中以推送通知

5
我试图从Sqlite中检索时间列表(包括小时和分钟),以便通过通知在闹钟管理器中执行提醒。我的方法是将存储在Sqlite中的所有预定时间循环到闹钟管理器中,根据时间列表执行通知,但通知没有提示音。 但是,当我指定一个时间(时和分)时,它可以工作。下面是代码示例,可以工作,但我不想这样做:
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 10);
calendar.set(Calendar.MINUTE, 45);
Intent myIntent = new Intent(ListRemainder.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(ListRemainder.this, 0, myIntent, 0);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);

但是如果涉及循环多个时间表,它就不起作用了,而这正是我想要的方法。以下是代码示例,请问我漏掉了什么?

//listOfTime is the one which contains the list of stored scheduled time in Sqlite.
for (int i = 0; i < listOfTime.size(); i++) {
    int hour = Integer.parseInt(listOfTime.get(i).toString().substring(0, 2));
    int minute = Integer.parseInt(listOfTime.get(i).toString().substring(3));
    System.out.print("Hour : " + hour + " Minute : " + minute);
    Log.d("MyActivity", "Alarm On");
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, hour);
    calendar.set(Calendar.MINUTE, minute);
    Intent myIntent = new Intent(ListRemainder.this, AlarmReceiver.class);
    pendingIntent = PendingIntent.getBroadcast(ListRemainder.this, 0, myIntent, 0);
    alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
}

如果在每次迭代中创建一个唯一的PendingIntent(给getBroadcast的第二个参数赋一个唯一值),会发生什么? - Elletlar
1个回答

1

getBroadcast的原型如下:

getBroadcast(Context context, int requestCode, Intent intent, int flags)

为每个PendingIntent设置唯一的“requestCode”应该允许调度多个闹钟:
PendingIntent.getBroadcast(context, uniqueValue, intent, PendingIntent.FLAG_UPDATE_CURRENT);

为了保证用户关键警报的唤醒:

void setAlarmClock (AlarmManager.AlarmClockInfo info, 
            PendingIntent operation)

来自文档: “安排一个代表闹钟的闹钟,用于在其响起时通知用户。预期是当此闹钟触发时,应用程序将进一步唤醒设备以告知用户有关闹钟 - 打开屏幕、播放声音、振动等。因此,系统通常也会使用此处提供的信息,在适当情况下告知用户即将到来的闹钟。”

由于这种类型的闹钟的性质类似于setExactAndAllowWhileIdle(int,long,PendingIntent),因此即使系统处于低功耗空闲(又称doze)模式,这些闹钟也将被允许触发。

总结:

  • 使用setAlarmClock唤醒设备向用户呈现信息。
  • 使用setExactAndAllowWhileIdle在后台执行必须在doze期间完成的工作。但是,这些闹钟的触发可能会延迟1分钟到15分钟左右。
  • 如果可能,使用FCM从远程应用程序实时唤醒设备。实际上,许多应用程序应该使用FCM而不是setExactAndAllowWhileIdle。
  • 如果在doze期间精确同步不重要,则使用setExact。此外,在API 21之前的设备上使用setExact而不是setAlarmClock或setExactAndAllowWhileIdle...

Lutaaya的最终解决方案:

AlarmManager.AlarmClockInfo(calendar.getTimeInMillis(),pendingIntent), pendingIntent);

是的,看起来不错。不需要 PendingIntent.FLAG_UPDATE_CURRENT 标志。如果将来添加了额外的内容,则可能会变得有用。 - Elletlar
可能最好在设备充电时(或屏幕保持开启)进行初始测试,以便在Doze模式不起作用的情况下验证代码。但是,正如您可能已经知道的那样,现在不再可能通过AlarmManager可靠地在一天中选择的小时和分钟唤醒设备。需要使用高优先级的云消息来代替。 - Elletlar
@Ellestar,请问我应该使用哪种高优先级的云消息传递服务呢?因为我正在开发一个小项目,用于提醒糖尿病患者注射胰岛素。 - Lutaaya Huzaifah Idris
请问setExact是什么意思?我应该把它放在哪里?我的当前代码是这样的:pendingIntent = PendingIntent.getBroadcast(ListRemainder.this, i, myIntent, PendingIntent.FLAG_UPDATE_CURRENT); - Lutaaya Huzaifah Idris
它们都是AlarmManager中的API。我建议在Android 6+ [API:21+]设备上,不要调用“alarmManager.set()”,而是使用“alarmManager.setAlarmClock()”。对于旧设备,可以使用“AlarmManager.setExact”,因为setExact不会受到这些旧设备上的doze限制的影响... - Elletlar
显示剩余9条评论

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