我需要所有用户在同一时间被定向到一个活动,无论他们的时区是什么或他们的手机时间设置了什么,所以我需要指定一个特定的时区,无论用户在手机中的时间如何,都要在"AlarmManager"中考虑。但是,"AlarmManager"的"setTimeZone"仅适用于系统应用程序。那么解决方案是什么?
这是我的代码:
Intent intent = new Intent(Start.this, Playing.class);
PendingIntent pendingIntent = PendingIntent.getActivity(Start.this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager) getSystemService(ALARM_SERVICE)).setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
我不是 Android 开发人员,但我阅读文档的方式,这不需要做任何特别的事情。设置闹钟时,您可以指定自纪元以来应响起的毫秒数。纪元的定义独立于时区。因此,如果您只是在所有设备上传递相同的triggerAtMillis
值,则无论时区如何,闹钟都将在所有设备上同时响起。
AlarmManager
也有setTimeZone
方法,但是(1)您不需要它,(2)它将为整个系统设置时区,而您的用户可能不需要。
编辑:使用java.time获取明确定义的时间
由于您从calendar.getTimeInMillis()
获得毫秒,如果您获得错误的时间,那么日历就是问题所在。
您可能希望通过将ThreeTenABP添加到Android项目中来解决此问题,以便可以使用java.time,现代Java日期和时间API,来计算毫秒数。请参阅底部的链接。Calendar
类设计不佳且早已过时,而现代 API 使用起来要好得多,并且通常提供更清晰的代码。例如:
ZoneId alarmZone = ZoneId.of("America/Argentina/Salta");
ZonedDateTime alarmDateTime = ZonedDateTime.of(2019, 4, 10, 14, 30, 0, 0, alarmZone);
long triggerAtMillis = alarmDateTime.toInstant().toEpochMilli();
System.out.println(triggerAtMillis);
输出值本身不是很有趣:
1554917400000
关键是,由于我们已经在代码片段中对时区进行了硬编码,因此无论设备时区如何,该值都将相同,因此您的闹钟将在所有设备上同时响起(前提是它们的时钟设置正确)。
问:我可以在我的Android版本上使用java.time吗?我需要三十ABP吗?
java.time在较旧和较新的Android设备上运行良好。它只需要至少Java6。
- 在 Java 8 及更高版本以及较新的 Android 设备(从 API 级别 26)中,内置了现代 API。
- 在Java 6和7中获取ThreeTen Backport,现代类的反向移植(JSR 310的ThreeTen;请参阅底部的链接)。
- 在(较旧的)Android上使用Android版本的ThreeTen Backport。它被称为ThreeTenABP。并确保从带有子包的
org.threeten.bp
导入日期和时间类。
链接
AlarmManager
文档 .- Oracle 教程:日期时间解释如何使用 java.time。
- Java 规范请求 (JSR) 310,其中首次描述了
java.time
。 - ThreeTen Backport项目,将
java.time
向Java 6和7的反向移植(JSR-310的ThreeTen)。 - ThreeTenABP,ThreeTen Backport 的安卓版
- 问:如何在Android项目中使用ThreeTenABP,并进行了非常详尽的解释。