2

I am showing a custom notification (FCM). custom notification has two buttons approve and deny.

I have managed to create pending intent and a broadcast receiver and now I know in onReceive when the button is clicked.

How can i differentiate between button clicks in onReceive, I tried to pass extras on the intent, but intent.getStringExtra("clicked") gave me null value.

what is the right way of knowing which button is clicked approve , deny

This is the code I tried. Thanks for your help in advance R

      override fun onMessageReceived(message: RemoteMessage) {
        Log.d("FCMService", "onMessageReceived START ${isAppOnForeground()}")
        if(!isAppOnForeground()) {
            val notificationLayout = RemoteViews(
                packageName,
                R.layout.plugin_requires_approval_notification_small
            )
            val notificationLayoutExpanded = RemoteViews(
                packageName,
                R.layout.plugin_requires_approval_notification_large
            )

            val title = message.data[MSG_TITLE]
            val subTitle = message.data[MSG_SUB_TITLE]

            notificationLayout.setTextViewText(R.id.tvTitle, title)
            notificationLayout.setTextViewText(R.id.tvSubTitle, subTitle)

            notificationLayoutExpanded.setTextViewText(R.id.tvTitle, title)
            notificationLayoutExpanded.setTextViewText(R.id.tvSubTitle, subTitle)

// Apply the layouts to the notification
            val customNotification = NotificationCompat.Builder(
                this,
                CarInfoProcessingService.NOTIFICATION_CHANNEL_ID
            )
                .setSmallIcon(R.mipmap.ic_launcher)
                .setStyle(NotificationCompat.DecoratedCustomViewStyle())
                .setCustomContentView(notificationLayout)
                .setCustomBigContentView(notificationLayoutExpanded)
                .setAutoCancel(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .build()

            val switchIntent = Intent(this, SwitchButtonListener::class.java)
            switchIntent.putExtra("clicked", "btnApprove")
            val pendingSwitchIntent = PendingIntent.getBroadcast(
                this, 0,
                switchIntent, 0
            )
     //TWO BUTTONS WITH SAME PENDING SWITCH INTENT
            notificationLayoutExpanded.setOnClickPendingIntent(R.id.btnApprove, pendingSwitchIntent)
            notificationLayoutExpanded.setOnClickPendingIntent(R.id.btnDeny, pendingSwitchIntent)

            val notificationManager =
                getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(0, customNotification)
        }
        Log.d("FCMService", "onMessageReceived END")
    }

    class SwitchButtonListener : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            Log.d("fcmService", "onReceive ${intent.getStringExtra("clicked")}")
        }
    }

Manifest

 <receiver android:name=".messaging.FcmService$SwitchButtonListener"  android:exported="true">
            <intent-filter>
                <action android:name="Button_Clicked"/>
            </intent-filter>
        </receiver>

EDIT : Updated code that might help others

    override fun onMessageReceived(message: RemoteMessage) {
        Log.d("FCMService", "onMessageReceived START ${isAppOnForeground()}")
        if(!isAppOnForeground()) {
            val notificationLayout = RemoteViews(
                packageName,
                R.layout.plugin_requires_approval_notification_small
            )
            val notificationLayoutExpanded = RemoteViews(
                packageName,
                R.layout.plugin_requires_approval_notification_large
            )

            val title = message.data[MSG_TITLE]
            val subTitle = message.data[MSG_SUB_TITLE]

            notificationLayout.setTextViewText(R.id.tvTitle, title)
            notificationLayout.setTextViewText(R.id.tvSubTitle, subTitle)

            notificationLayoutExpanded.setTextViewText(R.id.tvTitle, title)
            notificationLayoutExpanded.setTextViewText(R.id.tvSubTitle, subTitle)

// Apply the layouts to the notification
            val customNotification = NotificationCompat.Builder(
                this,
                CarInfoProcessingService.NOTIFICATION_CHANNEL_ID
            )
                .setSmallIcon(R.mipmap.ic_launcher)
                .setStyle(NotificationCompat.DecoratedCustomViewStyle())
                .setCustomContentView(notificationLayout)
                .setCustomBigContentView(notificationLayoutExpanded)
                .setAutoCancel(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .build()

            val approveIntent = Intent(this, CustomNotificationListener::class.java)
            approveIntent.putExtra("onClickListener", "approve")
            val pendingApproveIntent = PendingIntent.getBroadcast(
                this,
                0,
                approveIntent,
                PendingIntent.FLAG_UPDATE_CURRENT
            )
            notificationLayoutExpanded.setOnClickPendingIntent(R.id.btnApprove, pendingApproveIntent)

            val denyIntent = Intent(this, CustomNotificationListener::class.java)
            denyIntent.putExtra("onClickListener", "deny")
            val pendingDenyIntent = PendingIntent.getBroadcast(
                this,
                1,
                denyIntent,
                PendingIntent.FLAG_UPDATE_CURRENT
            )

            notificationLayoutExpanded.setOnClickPendingIntent(R.id.btnDeny, pendingDenyIntent)

            val notificationManager =
                getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(0, customNotification)
        }
        Log.d("FCMService", "onMessageReceived END")
    }

    class CustomNotificationListener : BroadcastReceiver() {
        @Inject
        lateinit var chargeSessionRepo: ChargeSessionRepository

        private var lastChargeStatus: ChargeStatusDTO? = null

        override fun onReceive(context: Context, intent: Intent) {
            Log.d("fcmService", "onReceive ${intent.getStringExtra("onClickListener")}")
            when(intent.getStringExtra("onClickListener")) {
                "approve" -> {
                    
                }
                "deny" -> {
                    
                }
            }
        }
    }
BRDroid
  • 3,920
  • 8
  • 65
  • 143
  • "How can i differentiate between button clicks in onReceive" -- use two separate `PendingIntent` objects with different IDs (the second parameter to `PendingIntent.getBroadcast()` and different underlying `Intent` objects (e.g., different extras). – CommonsWare Mar 26 '22 at 12:58
  • Hello @CommonsWare thank you for responding, so should I be creating a new class which extends BroadcastReceiver which will be new listener? – BRDroid Mar 26 '22 at 13:14
  • The two `Intent` objects can point to the same class if you want. That class would examine the extras to see which broadcast it received. – CommonsWare Mar 26 '22 at 13:28
  • when I try to get the extras, `${intent.getStringExtra("clicked")}`, I receive a null object – BRDroid Mar 26 '22 at 13:44
  • Presumably you created the `PendingIntent` in a previous run of the app without the extra. You are passing `0` for the last parameter to `PendingIntent.getBroadcast()`. That means "do not create a `PendingIntent` if one already exists in the system for this ID". Instead, pass `PendingIntent.FLAG_UPDATE_CURRENT`. – CommonsWare Mar 26 '22 at 13:46
  • thank you so much @CommonsWare that works thanks a TON, you are always very helpful and very knowledgable – BRDroid Mar 26 '22 at 13:52

1 Answers1

2

You need to use two distinct, up-to-date PendingIntent objects, wrapped around different Intent objects (e.g., ones with differing extras).

For "distinct", you need the IDs of the PendingIntent objects to be different. The ID is the second parameter to the PendingIntent.getBroadcast() call.

For "up-to-date", you need to update any existing PendingIntent that your code might have created previously. For that, pass PendingIntent.FLAG_UPDATE_CURRENT as the fourth parameter to the PendingIntent.getBroadcast() call.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491