【问题标题】:AlarmManager inconsistency报警管理器不一致
【发布时间】:2016-02-06 13:46:47
【问题描述】:

我正在使用AlarmManager 在屏幕关闭时发送广播。这在大多数设备上都可以正常工作,但在某些设备(例如三星 Galaxy S4)上,接收广播需要 30、40 甚至 120 秒,而不是指定的 20 秒。我无权访问发生这种情况的设备,因此无法检查 logcat。

这就是我设置AlarmManager的方式:

AlarmManager mAlarmManager=(AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
long mInterval = 20 * 1000;
Intent i = new  Intent();
i.setAction(MY_ACTION);
mPendingIntent = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + mInterval, mPendingIntent);

这是接收者,在清单中注册:

private class MyIntentReceiver extends BroadcastReceiver {

    private static final String TAG = "MyIntentReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(MY_ACTION)) {

            PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
            wl.acquire();

            Log.e(TAG, "onReceive");

            //Carry out my action...


            wl.release();

        }
    }

}

【问题讨论】:

  • 两个问题:您在onReceive() 中花费的时间不应超过几毫秒,并且在您在onReceive() 中时已经存在WakeLock。如果您将控制权传递给其他组件(例如,//Carry out my action 确实委托给IntentService),则需要您自己的WakeLock,尽管然后在您所在的位置释放WakeLock 是不正确的。如果您要委派给另一个组件,请使用 my WakefulIntentService 或 Android 支持包的 WakefulBroadcastReceiver
  • 谢谢,马克。我已将代码更改为 WakefulBroadcastReceiver/IntentService-construct,但 S4 上的不一致仍然存在(它可以在其他设备上工作,和以前一样)。如果我增加间隔(例如 30 或 40 秒而不是 20 秒),则不一致会呈指数级增加(即在执行我的操作之前比预期的时间长 1-2 分钟)。我对此感到困惑,因为我认为使用 RTC_WAKEUP 可以确保使用实际时间,而不仅仅是“设备唤醒”时间?
  • 应该是。如果你能创建一个可重现的测试用例,把它上传到某个地方,我会看一看。我有一台 S4,尽管它可能与您的 S4 型号不同(三星在一些设备上应用了“S4”)。或者,尝试this WakefulIntentService samplethis WakefulBroadcastReceiver sample 并尝试根据其中之一重现您的症状。
  • 谢谢,马克,我很感激!我会试试你的样品,然后通知你。

标签: android broadcastreceiver alarmmanager


【解决方案1】:

我将AlarmManager.set() 方法的参数更改为AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),而不是基于CommonsWare's sample 的初始AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),它现在也可以在S4 上使用。我不知道为什么ELAPSED_REALTIME_WAKEUP 不起作用,因为它的名称中特别带有WAKEUP,并且可以在我测试过的所有其他设备上运行。

【讨论】:

    【解决方案2】:

    AlarmManager 的行为随着 API 19 的到来而改变。在阅读更新后的 Javadoc 之前,在对曾经运行良好的应用程序进行故障排除方面浪费了很多时间。

    注意:从 API 19 (KITKAT) 开始,警报传递不准确:操作系统将切换警报以最大限度地减少唤醒和电池使用。有新的 API 来支持需要严格交付保证的应用程序;见setWindow(int, long, long, PendingIntent)setExact(int, long, PendingIntent)targetSdkVersion 早于 API 19 的应用程序将继续看到以前的行为,即所有警报都在请求时准确传递。

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 2020-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多