AlarmManager并不总是执行BroadcastReceiver

时间:2015-08-12 17:23:11

标签: android broadcastreceiver alarmmanager wakelock

所以我有一个BroadcastReceiver和AlarmManager。

假设我像这样创建Pending Intents:

Intent i;
i = new Intent(context, MyReceiver.class);
i.setAction(MyReceiver.ACTION_1);
i.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
pendingIntent1 = PendingIntent.getBroadcast(context, 1, i, PendingIntent.FLAG_UPDATE_CURRENT);

i = new Intent(context, MyReceiver.class);
i.setAction(MyReceiver.ACTION_2);
i.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
pendingIntent2 = PendingIntent.getBroadcast(context, 2, i, PendingIntent.FLAG_UPDATE_CURRENT);

安排警报如下:

now = SystemClock.elapsedRealtime();
long time1 = now + 10 * 1000;
long time2 = time1 + 60 * 1000;

am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, time1, pendingIntent1);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, time2, pendingIntent2);

我现在正在经历我的广播接收器非常可靠地获得ACTION_1的广播,而ACTION_2通常没有被传送。因此onReceive很少或永远不会执行持有动作ACTION_2的意图。怎么回事?我想,*_WAKEUP确保广播正在传送?

[2015年9月15日更新]   - 出于测试目的,我试图在onReceive方法中打印出日志消息。还是行不通。   - 我现在尝试在AlarmManager上使用setExact。还是行不通。   - 我甚至尝试过使用WakefulBroadcastReceiver。还是行不通。   - 但我发现,当处于电池充电状态时,设备可靠地唤醒。 可能导致此问题的原因是什么? 我已经读到,如果警报管理员通过未决意图触发广播接收器,保证会执行广播接收器(并且没有做太多的事情)在onReceive)。我的手机上是否有一些积极的节能政策,我无法真正反对(没有获得长唤醒锁定,请参阅评论)?

[2015年9月19日更新]我刚刚在Google Play上测试了一些闹钟应用程序(https://play.google.com/store/apps/details?id=com.alarmclock.xtreme.free),它也无法可靠地唤醒手机。我猜,这真的是一个错误而不是我的错。我想,我会坚持使用唤醒锁解决方案。

4 个答案:

答案 0 :(得分:6)

我遇到了同样的问题,我发现的解决方案是仅通过操作字符串创建意图,并在清单中注册该接收器操作。尝试将意图改为这样的事情:

i = new Intent("com.app.ACTION_ONE");

然后在您的清单文件中添加以下内容:

<intent-filter>
    <action android:name="com.app.ACTION_ONE" />
</intent-filter>

我的猜测是,如果你没有向接收者注册至少1个动作,那么当应用程序终止时,他就会死掉。

希望它有效,祝你好运。

答案 1 :(得分:2)

您是否注册了BroadcastReceiver(或来自Manifest)?

 registerReceiver(new MyReceiver(), new IntentFilter(MyReceiver.class.getName()));

我上次使用的方法几乎相同,但使用AlarmManager.RTC_WAKEUP - 如果您不想将设备从深度睡眠状态唤醒,请使用AlarmManager.RTC

long time = System.currentTimeMillis() + 10*1000;
alarmMgr.set(AlarmManager.RTC_WAKEUP, time, alarmIntent);

alarmIntent like:

alarmIntent = PendingIntent.getBroadcast(this, 0, new Intent(MyReceiver.class.getName()), PendingIntent.FLAG_CANCEL_CURRENT);

答案 2 :(得分:1)

很少有事情值得注意:

  1. 您正在使用AlarmManager.set()方法,如果您希望在准确时间触发警报,则无法保证交付时间使用AlarmManager.setExact()

  2. 你广播的意图对我来说没有意义。这是隐含的,但广播不应该是。这样的意图可能会引起奇怪的Android行为。如果您想要隐式意图,请将其直接发送给处理它的服务。在接收器的情况下,我建议使用:

    Intent intent = new Intent(Contants.Action1);
    
  3. 如果你的接收器是以明显意图定义的,那么即使你的应用程序的所有活动都已经死了,如果接收器动态地注册它,它只能在它被装箱的线程存活时才能接收意图。

  4. 不同版本的Android尝试以稍微不同的方式优化警报,但目标是同时触发尽可能多的警报,以达到更好的电池性能。

  5. 所有这些都可能令人困惑。但是如果接收器正确注册,保证会传递意图。

答案 3 :(得分:0)

在sony设备上查看“Stamina Mode”的设置。 尝试停用Stamina模式或将您的应用添加到耐力模式开启时允许的应用白名单中。

希望这有帮助。