PendingIntent is not working on Android O
A

2

8

I have download notification in my application. I've added "Cancel" button to NotificationCompat.Builder by calling addAction() method. But button not working on Android O device. When I press "Cancel" button nothing happens. But button working on Android < O.

Example Screenshot


My Notification:

NotificationCompat.Builder notification = new NotificationCompat.Builder(context, channelId)
            .setContentTitle(title)
            .setSmallIcon(R.drawable.network_download)
            .setContentText(contentText)
            .setOngoing(true)
            .setContentIntent(null)
            .addExtras(idBundle)
            .addAction(R.drawable.cancel, context.getString(R.string.cancel), getCancelPendingIntent(context, id))
            .setProgress(100, 30, true);

My PendingIntent :

private PendingIntent getCancelPendingIntent(Context context, int id){
    return PendingIntent.getBroadcast(
            context, id, new Intent("CANCEL_DOWNLOAD").putExtra("id", id), PendingIntent.FLAG_UPDATE_CURRENT);
}

Also I have NotificationReceiver :

public static class NotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if ("CANCEL_DOWNLOAD".equals(action) && context != null){
            int id = intent.getIntExtra("id", -1);
            NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            if (mgr != null)
                mgr.cancel(id);
            FtpManager.getInstance(new AppExecutors(), CredentialsManager.getInstance().getCredentials(context))
                    .cancelDownloading();
        }
    }
}

In Manifest file I have :

<receiver
        android:name="eu.warble.pjapp.util.NotificationsManager$NotificationReceiver"
        android:exported="false">
        <intent-filter>
            <action android:name="CANCEL_DOWNLOAD" />
        </intent-filter>
</receiver>
Ashla answered 3/10, 2017 at 16:16 Comment(0)
N
11

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)

Neap answered 3/10, 2017 at 16:39 Comment(5)
CommonsWare, I tried your solution but still notification actions aren't working on Oreo devices (after upgrading notification handling to support notification channeling).Maomaoism
@AndoAiron: I suggest that you ask a separate Stack Overflow question, where you provide a minimal reproducible example and explain your symptoms in detail.Neap
CommonsWare, Thanks for the suggestion. Asked separately as a new question and here is the link "#49980348"Maomaoism
How do you get an action if we change based on your suggestion? I mean if broadcaster has 2 actions, cancel and continue download, lets say? how can we make that happen without intentfilters?Shool
@batmaci: I would use an extra, as I show in Step #2.Neap
V
1

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*/}
Vernita answered 6/9, 2018 at 15:41 Comment(6)
I tested on android 8.0.0 and it works well, but it happens error on android 8.1.0 china device. I'm investigating solution for it.Vernita
I found the root cause for this error on android 8.1. I click on each notification, it still works well. But I click on "group notification", it not working, it only reopens the app.Vernita
I found the root cause. When user click on group notification, the app will be restarted and number of notifications in the group not reduce. It can be the feature default of android Oreo. When user click on any notification in the group, my code works well and number of notifications in group is reduced. Thanks!Vernita
how is this "do nothing" for oreo? are you just ignoring oreo action?Shool
NotificationBroadcastReceiverAndroidO extend NotificationBroadcastReceiver, so we only implement code in NotificationBroadcastReceiver, we don't need implement code in NotificationBroadcastReceiverAndroidOVernita
You don't have to create two receivers! Leave only one and for all versions just send explicit intent (instead of action you set class name) - notifyIntent = Intent(context, NotificationBroadcastReceiverAndroid::class.java) and in manifest - <receiver android:name=".firebase.NotificationBroadcastReceiverAndroid"/>Distaff

© 2022 - 2024 — McMap. All rights reserved.