Solution 1:

Never use an implicit Intent when an explicit Intent will do. Android O helps enforce this by banning the receipt of implicit Intent broadcasts from manifest-registered receivers.

Step #1: Remove the <intent-filter> from your <receiver> (which also means that you could get rid of android:exported="false", as that is now the default value)

Step #2: Replace new Intent("CANCEL_DOWNLOAD").putExtra("id", id) with new Intent(context, NotificationReceiver.class).putExtra("id", id)

Solution 2:

Thank you very much CommonsWare. It works for me. This is my code

    var notifyIntent = Intent(context, NotificationBroadcastReceiver::class.java)
                notifyIntent.action = "ACTION_UPDATE_BADGE"//hardcode in manifest

                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                    // only for oreo and newer versions
                    notifyIntent = Intent(context, NotificationBroadcastReceiverAndroidO::class.java)
                }
val pendingIntent = PendingIntent.getBroadcast(context, it, notifyIntent, PendingIntent.FLAG_ONE_SHOT)

In manifest

<receiver android:name=".firebase.NotificationBroadcastReceiver">
            <intent-filter>
                <action android:name="ACTION_UPDATE_BADGE" />
            </intent-filter>
        </receiver>

        <receiver android:name=".firebase.NotificationBroadcastReceiverAndroidO">
            <!--Android O not working when having this code
            <intent-filter>
                <action android:name="ACTION_UPDATE_BADGE" />
            </intent-filter>-->
        </receiver>

Create 2 classes:

open class NotificationBroadcastReceiver : BroadcastReceiver() {...}
open class NotificationBroadcastReceiverAndroidO : NotificationBroadcastReceiver() {/*do nothing*/}