Android ACTION_DATE_CHANGED广播

Zac*_*chM 14 android broadcastreceiver android-intent android-broadcast

我有一个Nexus S,当我在手机上手动更改日期时,并不总是广播ACTION_DATE_CHANGED.如果我将日期从2014年2月13日更改为2014年2月14日,我还没有获得ACTION_DATE_CHANGED工作,但如果我将其设置为未来几年,我有时会将其解雇.

我可以(99%)向你保证我不会滥用IntentFilters,BroadcastReceivers等.我只是好奇为什么这个广播记录得如此糟糕.通过SO和Google进行的快速扫描显示,当用户手动更改,或者日期在每天凌晨12:00或两者都滚动时,人们不确定是否会发生这种情况.我的经验表明,它与用户更改非常不一致,我没有尝试过系统更改.

我将通过AOSP代码,并隔离所有被触发的点并报告回来.

编辑:问题:任何人都知道这里发生了什么?:-)

Zac*_*chM 11

这是来自frameworks/base/services/java/android/server/AlarmManagerService.java中的4.0.3_r1的代码.

首先,我们创建一个PendingIntent mDateChangeSender;

private final PendingIntent mDateChangeSender;
Run Code Online (Sandbox Code Playgroud)

然后,在AlarmManagerService.java的构造函数中,我们设置PendingIntent:

Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
mDateChangeSender = PendingIntent.getBroadcast(context, 0, intent, 0);
Run Code Online (Sandbox Code Playgroud)

然后在构造函数中:

mClockReceiver.scheduleDateChangedEvent();
Run Code Online (Sandbox Code Playgroud)

那么什么是mClockReceiver?只是一个BroadcastReceiver侦听Intent.ACTION_TIME_TICK和Intent.ACTION_DATE_CHANGED.在它的onReceive():

...
else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
...
    scheduleDateChangedEvent();
}
Run Code Online (Sandbox Code Playgroud)

然后,我们稍后找到方法scheduleDateChangedEvent():

public void scheduleDateChangedEvent() {
     Calendar calendar = Calendar.getInstance();
     calendar.setTimeInMillis(System.currentTimeMillis());
     calendar.set(Calendar.HOUR, 0);
     calendar.set(Calendar.MINUTE, 0);
     calendar.set(Calendar.SECOND, 0);
     calendar.set(Calendar.MILLISECOND, 0);
     calendar.add(Calendar.DAY_OF_MONTH, 1);
     set(AlarmManager.RTC, calendar.getTimeInMillis(), mDateChangeSender);
}
Run Code Online (Sandbox Code Playgroud)

因此它设置一次性警报,从当前时间开始,然后将小时/分钟/秒/毫秒设置为零,然后添加一天,所以如果是今天下午1:30,下一次它将被解雇将是在10小时30分钟.

这并不是说这里没有错误或任何东西,但它看起来像ACTION_DATE_CHANGED应该每天午夜开火.

现在 - 如果我要改变电话上的日期,可以说10年后的未来.处理时间变化的代码将触发第一个ACTION_DATE_CHANGED事件,然后安排新的ACTION_DATE_CHANGED被触发,在10年+一天的某些时间内.然后,如果我们将日期更改回10年,到正确的日期,警报仍然计划在10年内被解雇,那么ACTION_DATE_CHANGED将不再被解雇(除非您将日期设置为超过10年后的日期 - 尝试一下! ).

tl; dr:这是Android中的一个错误.