Android 8.0 Oreo AlarmManager with broadcast receiver and implicit broadcast ban

ViciDroid picture ViciDroid · Sep 19, 2017 · Viewed 15.7k times · Source

I have critical reminders that are set via the Alarm Manager (It should function the same way as an alarm clock application).

Previously I had the following in my Android Manifest:

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

The broadcast receiver:

public class AlarmReceiver extends BroadcastReceiver {

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

}

How the alarm is set:

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);
      }
}

With Android 8.0 I can no longer use an implicit broadcast as defined in the Manifest. That's fine, the alternative given is to register it manually like so:

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

This does not seem logical to me.

  1. The alarm receiver will be tied to the lifetime of the context. This causes an issue when say the application is killed due to memory pressure or when the device is restarted. I need my alarms to fire every time as they are critical for the health of the user.

  2. Even if I listen to "android.intent.action.BOOT_COMPLETED" and register my alarm receiver the app is killed shortly after and no alarm is fired. I also don't see my alarm via

    adb shell dumpsys alarm

How do I create a custom broadcast receiver that receives an implicit broadcast to fire an alarm while targeting Android O (8.0)? Can someone enlighten me with a code example or link to documentation. How does Timely or any other alarm clock app function while targeting O?

Answer

Larry Schiefer picture Larry Schiefer · Sep 19, 2017

Revise your code slightly to make the broadcast explicit rather than implicit and you'll be fine (assuming this is an Activity reference or some other Context):

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

The restriction in Oreo is on implicit broadcast Intent registration, which is to say it you are sending it broadcasts will only action, category, or data specified. You make it an explicit broadcast by specifying the class which is to receive the broadcast.