【问题标题】:Alarm Manager broadcasts unexpectedly警报管理器意外广播
【发布时间】:2018-09-14 14:51:57
【问题描述】:

我有一个应用程序应该在存储在数据库中的指定时间触发警报。 时间存储为 (HH:mm) 格式,24 小时格式。

这是代码。

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
String temp = h+":"+m;
Date date = sdf.parse(temp);
alarmMgr = (AlarmManager)_c.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(_c, AlarmBroadcastReciever.class);
alarmIntent = PendingIntent.getBroadcast(_c, requestCode, intent, 0);
alarmMgr.set(AlarmManager.RTC_WAKEUP,Calendar.getInstance().getTimeInMillis()+  date.getTime(), alarmIntent);

_c: 上下文变量 h 是小时(24 小时格式),m 是分钟。

我想在凌晨 4:30 发出警报,但它在凌晨 03:09:35 立即响起。

如何在特定时间仅安排一次警报(不重复)?

PS:我倾向于使用警报,因为应用程序需要根据数据库查询在动态时间重复所有警报。

【问题讨论】:

  • 部分是时区问题。你在哪个时区?顺便考虑一下扔掉长期过时且臭名昭著的麻烦SimpleDateFormat 和朋友,并将ThreeTenABP 添加到您的Android 项目中,以便使用java.time,现代Java 日期和时间API。使用起来感觉好多了。

标签: android alarmmanager unix-timestamp milliseconds


【解决方案1】:
    int h = 4;
    int m = 30;
    LocalTime alarmTime = LocalTime.of(h, m);
    ZoneId zone = ZoneId.of("Asia/Kolkata");
    long alarmTimeMillis = LocalDate.now(zone)
            .atTime(alarmTime)
            .atZone(zone)
            .toInstant()
            .toEpochMilli();
    System.out.println(alarmTimeMillis);
    System.out.println(Instant.ofEpochMilli(alarmTimeMillis));

当我今天运行这个时,输出是

1522882800000
2018-04-04T23:00:00Z

为了检查 1 522 882 800 000 的毫秒值是否正确,我将其转换为 Instant。即时始终以 UTC 打印,因此打印的时间与亚洲/加尔各答时区的凌晨 4:30 一致(偏移量 +05:30)。您可能需要添加检查以查看时间是否已过,如果已过,则添加一天,以便在明天的指定时间发生警报。 LocalDate 和其他一些类有一个 plusDays 方法。

如果您从数据库中获取像04:30 这样的字符串,请像这样解析它:

    String alarmTimeString = "04:30";
    LocalTime alarmTime = LocalTime.parse(alarmTimeString);

其余的都一样。

我正在使用并推荐java.time,这是现代 Java 日期和时间 API。因为SimpleDateFormat 是出了名的麻烦,它的朋友DateCalendar 也早已过时。现代 API 更易于使用。

你的代码出了什么问题?

你的闹钟时间计算有两个错误:

  1. 虽然您的解析会生成一个Date,例如打印为Thu Jan 01 04:30:00 IST 1970,因此看起来是正确的,但这是欺骗性的。 04:30:00 是您当地的时区。当您使用date.getTime() 时,您将获得自纪元以来的毫秒数,并且纪元以UTC 定义,而不是您的时区。例如,我使用亚洲/加尔各答时区,得到 -3 600 000 毫秒,等于 1 小时。
  2. Calendar.getInstance().getTimeInMillis() 现在给出时间。将毫秒添加到该时间时,您可以指定距现在毫秒数的闹钟时间 - 在我的示例中为 1 小时前的闹钟时间。

问题:我可以在 Android 上使用 java.time 吗?

是的,java.time 在较旧和较新的 Android 设备上运行良好。它只需要至少 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备上,内置了现代 API。
  • 在 Java 6 和 7 中,获取 ThreeTen Backport,即新类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从 org.threeten.bp 导入日期和时间类以及子包。

链接

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多