AlarmManager在不同时间触发

时间:2014-09-13 17:38:22

标签: android alarmmanager

我已经在Google Play中创建并部署了一个闹钟应用。和往常一样,我在8个不同的真实设备(我不使用模拟器)中执行了大量的测试,运行不同的api级别,有根/无根,不同的时区,以及其他功能。

问题是,在达到超过10,000次下载后,一些用户抱怨在指定时间前1小时发出警报,而另一些用户(4倍数量)则抱怨警报在1小时后发生。我从世界不同的地方得到这个,我也从同一个地方得到5颗星。 我立刻想到我在我的代码的某些地方错误地使用了时区,但事实是我只是在使用

GregorianCalendar gc = new GregorianCalendar();

那种实例化是我通过我所有代码使用的实例。我使用系统AlarmManager设置闹钟,如:

    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context.getApplicationContext(), AlarmReceiver.class);
    GregorianCalendar gc = new GregorianCalendar();
    long triggerAtMillis = 0;
    if(nextAlarm != null){
        triggerAtMillis = System.currentTimeMillis() 
                + 60*1000*alarmDifference(nextAlarm, gc.get(Calendar.HOUR_OF_DAY), gc.get(Calendar.MINUTE), true)
                - 1000*gc.get(Calendar.SECOND);

    }else{
//          Log.d("", "nextAlarm: NULL");
    return;
    }

    PendingIntent operation = PendingIntent.getBroadcast(context.getApplicationContext(), REQUEST_CODE_ALARM_BROADCAST, intent, 0);
    am.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);

alarmDifference方法非常简单:

public static int alarmDifference(Alarm alarm, int hour, int minute, boolean inverse) {
    int hours = hour - alarm.getHour();
    if(inverse){
        hours *= -1;
    }
    if(hours < 0)
        hours += 24;

    int minutes = minute - alarm.getMinute();
    if(inverse){
        minutes *= -1;
    }

    if(hours==0 && minutes<0){
        hours = 23; //this happens if we set the time to the current hour
    }

    if(minutes < 0)
        minutes += 60;

//  Log.d("", "Time left: "+ hours+" hours, " + minutes+" minutes");
    return hours*60 + minutes;

}

我的目标是api级别17,因此我不会遇到系统不遵守交付时间的问题,并且必须使用 AlarmManager.setExact(...)

要唤醒我的服务我正在使用WakefulBroadcastReceiver,所以我不必自己处理WakeLock。

我在网站上做了大量的研究,尝试过不同的方法而没有任何运气。

提前致谢。

2 个答案:

答案 0 :(得分:1)

您可以尝试使用next来查找问题:

在您的应用中加载来自互联网服务的世界时间(例如,http://developer.yahooapis.com/TimeService/V1/getTime?appid=YahooDemo),并与设备上的时区进行比较。您可以在全局或应用中的设备中确定问题所在。

答案 1 :(得分:0)

我很确定问题出在这一行:

triggerAtMillis = System.currentTimeMillis() 
                + 60*1000*alarmDifference(nextAlarm, gc.get(Calendar.HOUR_OF_DAY), gc.get(Calendar.MINUTE), true)
                - 1000*gc.get(Calendar.SECOND);

此操作保证以原子方式发生。换句话说,

  • gc.get(Calendar.HOUR_OF_DAY)
  • gc.get(Calendar.MINUTE)

可以在不同的时间发生,例如当时钟从14:59:99变换到15:00:00,所以你可能会得到14小时和00分钟,或15小时和59分钟

相反,我会从不可变的时间戳值中提取小时/分钟/秒。