警报管理器意外广播 [英] Alarm Manager broadcasts unexpectedly

查看:106
本文介绍了警报管理器意外广播的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a application which should fire up an alarm at a specified time stored in the database. The time is stored like (HH:mm) format, 24-hour format.

这里是代码。

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是分钟。

_c: context variable h is the hour (24-hour format) and m is the minutes.

我想在凌晨4:30触发警报,但警报在03:09:35 AM立即触发。

I wanted to fire the alarm at 4:30 am but it got fired immediately at 03:09:35 AM.

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

How to schedule alarms only one time at that specific time (no-repeating)?

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

PS: I am tending towards using alarms because the application needs repeating alarms all at dynamic times based on database queries.

推荐答案

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

今天我运行此命令时,输出为

When I ran this today, the output was

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

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

To check whether the millisecond value of 1 522 882 800 000 was correct I converted it to an Instant. Instants always print in UTC, so the time printed agrees with 4:30 AM in Asia/Kolkata time zone (offset +05:30). You will probably want to add a check to see if the time is already passed, and if so, add one day so the alarm happens at the specified time tomorrow. LocalDate and some of the other classes have a plusDays method for that.

如果您从数据库中以 04:30 之类的字符串形式获取警报时间,请像这样解析它:

If you get your alarm time as a string like 04:30 from the database, parse it like this:

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

其余部分相同。

我正在使用并建议使用 java.time (现代的Java日期和时间API)。因为 SimpleDateFormat 非常麻烦,它的朋友 Date Calendar 也早已过时。

I am using and recommending java.time, the modern Java date and time API. Because SimpleDateFormat is notoriously troublesome, and its friends Date and Calendar are long outdated too. The modern API is so much nicer to work with.

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

There are two bugs in your calculation of the alarm time:


  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小时前的警报时间。

  1. While your parsing produces a Date that prints as for example Thu Jan 01 04:30:00 IST 1970 and thus looks right, this is deceiving. The 04:30:00 is in your local time zone. When you use date.getTime(), you get the number of milliseconds since the epoch, and the epoch is defined in UTC, not in your time zone. For example, I used Asia/Kolkata time zone and got milliseconds of -3 600 000, equal to minus 1 hour.
  2. Calendar.getInstance().getTimeInMillis() gives the time now. When adding your milliseconds to this time, you specify an alarm time that number of milliseconds from now — in my example an alarm time 1 hour ago.



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



是的, java.time 在较新的Android设备。它只需要至少Java 6

Question: Can I use java.time on Android?

Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.


  • 在Java 8和更高版本以及较新的Android设备上,现代API

  • 在Java 6和7中获得ThreeTen Backport,即新类的Backport(JSR 310的ThreeTen;请参见底部的链接)。

  • 在(较旧的)Android上,请使用Android版的ThreeTen Backport。叫做ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间类。

  • In Java 8 and later and on newer Android devices the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
  • Oracle tutorial: Date Time explaining how to use java.time.
  • Java Specification Request (JSR) 310, where java.time was first described.
  • ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
  • ThreeTenABP, Android edition of ThreeTen Backport
  • Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.

这篇关于警报管理器意外广播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆