I have registered a BroadcastReceiver in my manifest, what now?
Don’t panic. Remember that while it may be frustrating to migrate your existing code to be Android O compatible, it’s not a major change and it’s all for the greater good.
Determine if the BroadcastReceiver is implicit or explicit
According to the documentation, any Broadcast that’s not directly related to your app is an implicit Broadcast. Like the documentation states, ACTION_PACKAGE_REPLACED is an implicit broadcast, since it notifies you of every newly installed package.
Likewise, any Broadcast that’s directly related to your app is an explicit one. So ACTION_MY_PACKAGE_REPLACED is an explicit Broadcast, since it notifies you when only your app is updated.
Most of the Broadcasts you can listen to are implicit ones.
Check if your app is affected
Android Developer documentation provides a list of implicit Broadcasts that aren’t affected and will continue to work normally. That means if your app only registers listeners for these implicit Broadcasts in the AndroidManifest, and these only, you’re safe.
The most common unaffected ones are ACTION_BOOT_COMPLETED, ACTION_HEADSET_PLUG and ACTION_CONNECTION_STATE_CHANGED for Bluetooth state changes, with many others.
JobScheduler to the rescue
If you listened for network connection, charger or device idle events, the chances are you want to use JobScheduler for your task instead.
JobScheduler plays nicely with the Android system and Doze battery optimizations. It allows executing tasks based on conditions that you can define. For example, you can schedule a Job to be executed once the charger gets connected and the device has a working network connection while being in idle mode.
JobScheduler is only supported on Android Marshmallow (API 21) and up. If your app has a minSdkVersion below 21, there’s libraries with similar APIs that provide backwards compatibility. The officially recommended one is FirebaseJobDispatcher.
We at Codemate are currently having great success with Evernote’s Android-Job library. Android-Job uses JobScheduler on devices that have Marshmallow or greater and falls back to GCMNetworkManager or AlarmManager depending on if the system has Google Play Services installed or not.
Context.registerReceiver() has always got your back
Whether your Broadcast is implicit or explicit, you can always register it by using the Context.registerReceiver() method inside your Activity, Service, Fragment or even a custom View.
So, for example if your AndroidManifest had a receiver for listening charger events:
You would remove that receiver from your AndroidManifest.xml and the BatteryReceiver class completely, and move listening logic inside your Activity, Service, Fragment, whatever:
The difference of registering BroadcastReceivers with Context.registerReceiver() is that you must eventually also unregister it, while receivers defined in you manifest will wake up your app no matter what. When to unregister depends on where you first register your receiver.
If done inside an Activity / Fragment, a good place to unregister is the onDestroy callback. Inside a Service, unregister when you don’t need to receive those events any more.