AlarmManager过早触发PendingIntent

时间:2012-06-02 20:26:34

标签: android alarmmanager android-pendingintent

我现在已经搜索了3天,但在其他地方找不到解决方案或类似的问题/问题。这是交易:

1小时内触发 - >工作正确

2小时内触发 - >在1:23

进入

在1天内触发 - >进入~11:00

那么为什么AlarmManager如此不可预测且总是太快?或者我做错了什么?是否有另一种方式可以正常工作?

这是我在AlarmManager中注册PendingIntent(剥离)的方式:

AlarmManager alarmManager = (AlarmManager)parent.getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(parent, UpdateKlasRoostersService.class);
PendingIntent pendingIntent = PendingIntent.getService(parent, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

//Set startdate of PendingIntent so it triggers in 10 minutes
Calendar start = Calendar.getInstance();
start.setTimeInMillis(SystemClock.elapsedRealtime());
start.add(Calendar.MINUTE, 10);

//Set interval of PendingIntent so it triggers every day
Integer interval = 1*24*60*60*1000;

//Cancel any similar instances of this PendingIntent if already scheduled
alarmManager.cancel(pendingIntent);

//Schedule PendingIntent
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, start.getTimeInMillis(), interval, pendingIntent);
//Old way I used to schedule a PendingIntent, didn't seem to work either
//alarmManager.set(AlarmManager.RTC_WAKEUP, start.getTimeInMillis(), pendingIntent);

如果有人有解决方案,这将是非常棒的。谢谢你的帮助!

更新: 2小时前它以2小时的间隔触发它,但之后它在1:20小时后触发。这变得非常奇怪。我将使用日志文件跟踪触发器,并在明天将其发布到此处。

更新: PendingIntent计划每3小时运行一次。从日志的第二行开始,似乎旧计划的PendingIntent仍在运行:

[2012-5-3 2:15:42 519] Updating Klasroosters
[2012-5-3 4:15:15 562] Updating Klasroosters
[2012-5-3 5:15:42 749] Updating Klasroosters
[2012-5-3 8:15:42 754] Updating Klasroosters
[2012-5-3 11:15:42 522] Updating Klasroosters

但是,我确定在安排新的PendingIntent之前我取消了预定的PendingIntent。并且每个PendingIntent都不会以相同的方式重新创建,因此它应该完全相同。如果没有,这个线程问题就不再适用了。

4 个答案:

答案 0 :(得分:1)

使用日历时,您会考虑日历使用的时间为Milli秒。也许你应该将Milli第二个字段和秒字段设置为零,这样它就会出现在点上。

同样在一天中使用此

会更容易
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(0);
cal.add(Calendar.DAY_OF_MONTH, 1);

此外,当您使用getInstance时,不会将日历时间设置为创建时间,因此不需要再次设置时间吗?

答案 1 :(得分:1)

重写:我最终看到了你的错误,但不可预测。

我确实改变了这个:

PendingIntent.getService(parent, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

到此:

PendingIntent.getService(parent, 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);

在与你一样的假设下以某种方式旧的意图是广播。我从没见过侥幸......

我见过的唯一一次是在我最初的通话中。另一种方法可能是跟踪currentprevious日历对象,如果间隔不符合您的预期,则忽略此“早期”广播。 (虽然这种方法似乎是多余的,考虑到警报应该如何工作,但它有助于防止这些无关的呼叫考虑警报 的工作方式......)

希望有所帮助,如果我发现其他任何事情,我会通知您。

答案 2 :(得分:1)

我知道这个问题有点陈旧,但我自己也有同样的问题。我发现如果我试图在方法之外声明Calendar变量,它将无法正常播放并且警报会提前触发。由于您的课程被剥离了,因此很难确切地说出您正在调用日历实例的位置。

如果我这样设置,那么它会按时启动:

protected void nextAlarm(Context context, int seconds){
    Calendar nextAlarm = Calendar.getInstance();

    Intent intent = new Intent(context, MyClass.class);
    PendingIntent pending = PendingIntent.getBroadcast(context, MainActivity.REPEATING_ALARM, intent, PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager amanager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    nextAlarm.add(Calendar.SECOND, seconds);

    amanager.set(AlarmManager.RTC_WAKEUP, nextAlarm.getTimeInMillis(), pending);

}

答案 3 :(得分:1)

确保您的服务onStartCommand返回START_NOT_STICKY,否则将自动重新尝试:

public class UpdateKlasRoostersService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        buildUpdate();
        return START_NOT_STICKY;
    }
}