Android 8.0 Oreo AlarmManager 带有广播接收器和隐式广播禁令

Android 8.0 Oreo AlarmManager with broadcast receiver and implicit broadcast ban

我有通过闹钟管理器设置的重要提醒(它的功能应该与闹钟应用程序相同)。

以前我的 Android 清单中有以下内容:

    <receiver android:name="com.example.app.AlarmReceiver" >
        <intent-filter>
            <action android:name="${packageName}.alarm.action.trigger"/>
        </intent-filter>
    </receiver>

广播接收者:

public class AlarmReceiver extends BroadcastReceiver {

  @Override public void onReceive(
      final Context context,
      final Intent intent) {
// WAKE LOCK
// BUILD NOTIFICATION etc...
  }

}

闹钟的设置方式:

final PendingIntent operation = PendingIntent.getBroadcast(
          mContext,
          requestCode,
          intent,
          PendingIntent.FLAG_CANCEL_CURRENT);

      if (PlatformUtils.hasMarshmallow()) {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);

      } else {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);
      }
}

在 Android 8.0 中,我不能再使用清单中定义的隐式广播。没关系,给出的替代方法是像这样手动注册它:

final BroadcastReceiver receiver = new AlarmReceiver();
final IntentFilter intentFilter = new IntentFilter(ALARM_RECEIVER_INTENT_TRIGGER);
context.registerReceiver(receiver, intentFilter);

我觉得这不合逻辑。

  1. 警报接收器将绑定到上下文的生命周期。当应用程序由于内存压力或设备重新启动而被终止时,这会导致问题。我需要每次都触发警报,因为它们对用户的健康至关重要。

  2. 即使我收听 "android.intent.action.BOOT_COMPLETED" 并注册我的警报接收器,该应用程序很快就会被终止并且不会触发任何警报。我也没有通过

    看到我的闹钟

    adb shell dumpsys 报警

如何创建一个自定义广播接收器来接收隐式广播以在瞄准 Android O (8.0) 时触发警报?有人可以通过代码示例或 link 文档启发我。针对 O 时,Timely 或任何其他闹钟应用如何运行?

稍微修改你的代码,使广播显式而不是隐式,你会没事的(假设 this 是一个 Activity 参考或其他一些 Context):

Intent intent = new Intent(ALARM_RECEIVER_INTENT_TRIGGER);
intent.setClass(this, AlarmReceiver.class);

Oreo 中的限制是隐式 广播Intent 注册,也就是说您向它发送的广播只会指定动作、类别或数据。通过指定接收广播的 class 使其成为 explicit 广播。

如果你们习惯了检查警报是否已经被注册,请不要忘记在这个验证中做同样的事情:

public boolean isAlarmBroadcastRegistered(Context context, String action, Class clazz) {
    Intent intent = new Intent(action);
    intent.setClass(context, clazz);
    return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE) != null;
}