我要做的是Android上的基本闹钟应用。当我通过UI设置日期和时间时(比如2012-09-26 14:37),我希望当时的闹钟响起,不管时区如何。该设置被序列化为两个单独的值 - 日期值和从一天开始的偏移量(以毫秒为单位)。
我也错误地使用Joda库进行日期/时间操作。 API看起来非常类似于.NETs DateTime API,但是仍然遇到与默认Java框架API相同的二元性问题,其中对象值是UTC,但它的属性是在本地时间(这个概念让我大吃一惊btw) )。它似乎也无法自动获取Android的时区变化。
这是我所拥有的摘要:
// part of reminder class
public DateTime getNextAlarm()
{
DateTime now = DateTime.now();
DateTime next = date.withMillisOfDay(time);
while (next.compareTo(now) <= 0)
next = next.plusDays(repeat);
return next;
}
// inside worker thread
workerEnabled = true;
while (workerEnabled)
{
try
{
Thread.sleep(10000);
}
catch (InterruptedException e)
{
workerEnabled = false;
return;
}
DateTimeZone tz = DateTimeZone.forTimeZone(TimeZone.getDefault());
if (nextAlarm != null && nextAlarm.withZoneRetainFields(tz).compareTo(new DateTime(tz)) < 0)
{
nextAlarm = reminder.getNextAlarm();
// perform alarm action
}
}
在应用程序运行时(设置完成后)我尝试切换时区时,一切都很好,很花哨。这是奇怪的东西开始的地方。我甚至无法描述究竟出了什么问题,除此之外无论我做什么都不行。
我想我正在寻找的是关于如何在Joda或标准API中使用Java / Android进行时区独立数学的一般方向。
答案 0 :(得分:2)
我使用AlarmManager
在一天的特定时间下载文件。来自帮助类的示例代码我有......
public void createDownloadAlarm() {
Intent i = new Intent(MyApp.ACTION_DOWNLOAD_FILES);
PendingIntent operation = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 1);
cal.set(Calendar.MINUTE, 30);
cal.set(Calendar.SECOND, 0);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, operation);
}
使用Calendar.getInstance()
然后使用set(...)
方法会创建一个警报,该警报将在任何时区的确切时间触发。
要执行您所描述的内容,我会将上述代码与监听BroadcastReceiver
的{{1}}结合使用 - 将其在清单中注册为ACTION_TIMEZONE_CHANGED
。
在android.intent.action.TIMEZONE_CHANGED
中我会调用上面显示的方法,该方法应该(理论上)取消之前的警报,并在时区更改时为当地时间设置一个新警报。 / p>
答案 1 :(得分:0)
事实证明,Jodatime不会处理Android上的时区变化。重新启动应用程序会有所帮助,但该解决方案不适用于始终运行的后台服务。我最终使用Calendar / Date API重写代码,即使它很难看也很痛苦。