Search code examples
androidpush-notificationbroadcastreceiverandroid-pendingintent

differentiate between button clicks using pending intent


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" -> {
                    
                }
            }
        }
    }

Solution

  • 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.