【问题标题】:Android AlarmManager triggers every "round" 10 minutesAndroid AlarmManager 每“回合”10 分钟触发一次
【发布时间】:2017-04-23 17:02:12
【问题描述】:

我在我的应用程序中使用 AlarmManager 如下:

alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), AlarmManager.INTERVAL_HALF_DAY, intent);

我希望在每次触发后 12 到 24 小时内触发警报。但是,HTC 设备上的行为非常奇怪:

每次触发警报时,我们都会向我们的服务器发送一个 HTTP 请求。在所有设备上,我们看到随着时间的推移均匀地向服务器发出请求,但在 HTC 设备上,每“轮”10 分钟(XX:10, XX:20, ...)就会出现峰值:

这些尖峰的原因可能是什么?为什么它只会出现在 HTC 设备上?

【问题讨论】:

  • 在哪个特定的 API 上?该图代表什么,您的服务器上的 HTTP 请求?
  • @FrédéricLetellier API 级别 24。是的,这些是 HTTP 请求。
  • 在应用程序中的哪个时间点安排此警报?
  • @TimCastelijns 仅在重启时(我听 BOOT_COMPLETE)
  • @Ori Wasserman 你取消之前的意图了吗?

标签: android alarmmanager


【解决方案1】:

我们看不到您的其余代码,但是您是否取消了之前的意图,如下所示:

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(context, TimeAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), AlarmManager.INTERVAL_HALF_DAY, pendingIntent);

否则可能是HTC对AlarmManager的管理不善,尝试这些不同的调查(这可能看起来很荒谬,但最好挑战每个项目):

  • System.currentTimeMillis() 添加一点延迟,而不是单独给System.currentTimeMillis()
  • 使用值43200000(常量值)而不是AlarmManager.INTERVAL_HALF_DAY
  • 试试thisCalendar
  • 尝试setInexactRepeating的其他参数

我没有发现任何关于这个主题的已知和列出的错误。如果你的调查没有给出任何结果,你可能什么也做不了。在这种情况下,您只需为 HTC 设置一个不以这种方式使用 AlarmManager 的解决方法。

【讨论】:

  • 我们看不到你的其余代码你可以要求它,这样你就不必猜测解决方案;)
  • 关于寻找其他解决方案的话题,请考虑使用 JobScheduler 来处理此类任务,而不是 AlarmManager。
  • @Ori Wasserman:我同意 MCEley 的观点,与其挖掘警报管理器导致问题的原因,不如尝试使用作业调度程序 API 来代替。
  • @Tal Kanel 在我看来,最好调试现有问题,而不是立即切换到 JobScheduler 的解决方法。 JobScheduler 在某些设备上受制于其他制造商特定的错误并非不可能。为了长期确保质量,解决问题总比忽视问题好!
  • @Frédéric Letellier - 我使用 FLAG_UPDATE_CURRENT,而不是取消。关于您建议的其他选项:1 和 3 - 我很难相信这会解决任何问题,因为这只会影响第一个警报,而问题主要出在“重复”部分。 2 - 这是一个常数,因此它作为这个数字编译到 APK 中。 4 - RTC_WAKEUP 是最适合我的用例的参数,因此更改它会影响警报的逻辑。
【解决方案2】:

首先取消之前的警报

private void cancelAlarm(Context context, Class aClass) {
        Intent intent = new Intent(context, aClass);
        PendingIntent pintent = PendingIntent.getService(context, REQUEST_CODE, intent, FLAG_UPDATE_CURRENT);
        AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarm.cancel(pintent);
    }

然后像这样创建新闹钟

public static void setAlarmManager(Context context, Class aClass, String time) {
        Intent intent = new Intent(context, aClass);
        PendingIntent pintent = PendingIntent.getService(context, REQUEST_CODE, intent, FLAG_UPDATE_CURRENT);
        AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

//        alarm.cancel(pintent);

//        "auto_sync":"1","sync_time":"04:05"
        String timeArr[] = time.split(":");
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeArr[0]));
        calendar.set(Calendar.MINUTE, Integer.parseInt(timeArr[1]));

        alarm.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), INTERVAL, pintent);
    }

设备警报管理器管理不善。在这种情况下,使用 SharedPreferences 在创建或更新新警报管理器时保存以前的时间。当您尝试运行日常操作时,该保存的值也很有用。

【讨论】:

    【解决方案3】:

    我看到你已经尝试过 AlarmManager.RTC_WAKEUP,你能试试 AlarmManager.ELAPSED_REALTIME_WAKEUP 吗?

    启动你的闹钟,因为手机打开

    <receiver android:name=".YourBootReceiver"> 
        <intent-filter> 
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            <action android:name="your.package.BOOT_FIRSTTIME"/>
        </intent-filter> 
    </receiver>
    

    在用户激活警报时使用 your.package.BOOT_FIRSTTIME。

    然后,像这样配置您的 AlarmManager:

    24 小时以毫秒为单位是 86400000

    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 86400000, pendingIntent);

    【讨论】:

      【解决方案4】:

      将间隔添加到第二个参数,即 triggerAtMillis 帮助了我

      alarm.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis()+interval, interval, pendingIntent);
      

      查看here了解更多详情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多