Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click on android notification icon does not trigger broadcast receiver

I have an app hooked with push notifications. When the user click on the notification, I want a broadcast receiver to be triggered instead of an activity.

I looked at these threads and looks like this is perfectly possible and common.

Android Notification Action is not fired (PendingIntent)

Send broadcast on notification click

However I can't get it to work. I see the notification, but when I click on it and it never triggers my Broadcast receiver.

Here what I have tried:

  1. I created a custom receiver:

    public class NotificationOnClickReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(final Context context, Intent intent) {
            Log.d(Constants.Engine.LOGGER_TAG_GCM,
                    NotificationOnClickReceiver.class.toString() + " triggered");
        }
    }
    
  2. I registered this receiver dynamically on my global Application (not activity)

    mNotificationOnClickReceiver = new NotificationOnClickReceiver();
    IntentFilter intentFilterOnClick = new IntentFilter(Constants.Engine.BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK);
    getApplicationContext().registerReceiver(mNotificationOnClickReceiver, intentFilterOnClick);
    Log.e(Constants.Engine.LOGGER_TAG_DBG, "mNotificationOnClickReceiver = " + mNotificationOnClickReceiver.toString());
    

The filter is just a string constant (I wonder if this is the problem)

    public static final String BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK = "push_notification.onclick";
  1. Receiver intent setup:

    // When the user taps on the notification bar, this is the receiver that I want to be called
    Intent pushNotificationIntent;
    Log.e(Constants.Engine.LOGGER_TAG_DBG, "Notification called!");
    pushNotificationIntent = new Intent(this, NotificationOnClickReceiver.class);
    // Not sure if this causing the problem
    pushNotificationIntent.setAction(Constants.Engine.BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK);
    // ensures that each notification and intent are unique
    int uniqueCode = new Random().nextInt(Integer.MAX_VALUE);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            context,
            uniqueCode,
            pushNotificationIntent, // Receiver Intent
            PendingIntent.FLAG_CANCEL_CURRENT);
    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
            .setSmallIcon(mIconId)
            .setContentTitle(context.getString(R.string.myString))
            .setContentText("My GCM Alert!")
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);
    
  2. From the logs, things seem to work except that my Broadcast receiver never gets called:

    02-22 15:47:47.092 16863-16863/com.myapp.test E/MYAPP_DBG: mNotificationOnClickReceiver = mytest.broadcastreceivers.NotificationOnClickReceiver@d78f559
    02-22 15:47:53.312 16863-17038/com.myapp.test E/MYAPP_DBG: Notification called!
    

If anyone has this working, can you point me out a sample code? I don't see where my bug is.

thank you!

like image 508
gmmo Avatar asked Feb 23 '17 00:02

gmmo


2 Answers

This would appear to be the problem:

pushNotificationIntent = new Intent(this, NotificationOnClickReceiver.class);

You're actually creating an explicit Intent for the broadcast PendingIntent. Explicit Intents do not work with dynamically registered Receivers, as they target a Receiver class, rather than an instance.

You'll need to use an implicit Intent instead, which you can do by simply instantiating the Intent with the action String, rather than a Context and Class. For example:

pushNotificationIntent = new Intent(Constants.Engine.BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK);

Please note that if your app's process is killed before the Notification is clicked, that dynamically registered Receiver instance will die, too, and the Notification's broadcast won't really do anything.

Depending on the desired behavior, it might be preferable to instead statically register your Receiver class in the manifest, and stay with the explicit Intent. Doing this will allow your app to receive the Notification broadcast even if its process has been killed.

To do that, you'd just need to add a <receiver> element for your NotificationOnClickReceiver in the manifest.

<receiver android:name="NotificationOnClickReceiver" />

Though you can still set an action on that broadcast Intent, you don't need an <intent-filter> for it here, as the explicit Intent is directly targeting the class anyway. If the Receiver is only for that one function, you don't necessarily need the action, and can just remove that altogether.

You can then remove the code you have in step 2, as you'd no longer need the dynamically registered instance.

like image 61
Mike M. Avatar answered Nov 05 '22 23:11

Mike M.


To send a broadcast use this sendBroadcast(new Intent("NotificationClicked"));

Now to recieve the broadcast, mention this in your manifestunder application tag

<receiver android:name=".NotificationOnClickReceiver" >
            <intent-filter>
                <action android:name="NotificationClicked" >
                </action>
            </intent-filter>
        </receiver>
like image 22
Abhriya Roy Avatar answered Nov 05 '22 21:11

Abhriya Roy