Android: In-App Push Notifications with Payloads and Handling Click Events

Romman SabbirRomman Sabbir
3 min read

In the world of mobile applications, user engagement and interaction are crucial for success. One effective way to engage users is through push notifications. In this article, we'll delve into the details of generating in-app push notifications with payloads and handling push-click events with precision. We'll examine the main code, a supporting function, and the activity responsible for managing push-click events.

Concept

  • Generate a Push Notification with PendingIntent by passing additional data as payload.

  • Show the push notification to the user.

  • Get push event callback when a user opens or clicks on the notification.

  • Receive the exact payload you passed initially.

  • Tada! Now it's your turn to execute your operation based on the payload.

Let's get into the coding part

The sendInAppPushNotification function is the heart of our notification system.

Let's break down its key components:

fun sendInAppPushNotification(
        context: Context,
        title: String,
        message: String,
        time: Long,
        imageUrl: String,
        action: Actions
    ) {
        try {
            // Setting up the notification
            val channelId: String = MyAppConstants.NOTIFICATION_CHANNEL_ID
            val defaultSoundUri: Uri =
                RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)

            val notificationBuilder: NotificationCompat.Builder =
                NotificationCompat.Builder(context, channelId)
                    .setSmallIcon(R.mipmap.my_ic_launcher_round).setContentTitle(title)
                    .setContentText(message).setAutoCancel(true).setWhen(time)
                    .setStyle(NotificationCompat.BigTextStyle().bigText(message))
                    .setPriority(NotificationCompat.PRIORITY_HIGH).setSound(defaultSoundUri)

            // Setting up the notification intent
            notificationBuilder.setContentIntent(getIntentOfNotification(context, action))

            // Getting the notification manager
            val notificationManager: NotificationManager =
                context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

            // For Android Oreo and above, create a notification channel
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channel = NotificationChannel(
                    channelId,
                    MyAppConstants.NOTIFICATION_CHANNEL_ID,
                    NotificationManager.IMPORTANCE_DEFAULT
                )
                channel.enableLights(true)
                channel.lightColor = R.color.primary_color
                channel.enableVibration(true)
                channel.vibrationPattern = longArrayOf(100, 200, 300)
                notificationManager.createNotificationChannel(channel)
            }

            // Handling image notifications
            if (imageUrl.isEmpty()) {
                notificationManager.notify(
                    System.currentTimeMillis().toInt(), notificationBuilder.build()
                )
            } else {
                Glide.with(context).asBitmap().load(imageUrl)
                    .into(object : CustomTarget<Bitmap?>() {
                        override fun onLoadCleared(placeholder: Drawable?) {
                            // Log the error
                        }

                        override fun onResourceReady(
                            resource: Bitmap,
                            transition: Transition<in Bitmap?>?,
                        ) {
                            // Continue here
                            notificationBuilder.setStyle(
                                NotificationCompat.BigPictureStyle().bigPicture(resource)
                            ).setLargeIcon(resource)
                            notificationManager.notify(
                                System.currentTimeMillis().toInt(), notificationBuilder.build()
                            )
                        }

                    })
            }
        } catch (e: Exception) {
            e.printStackTrace()
            // Log the error
        }
    }
}

Handling Push Click Events: Supporting Function

The getIntentOfNotification function is responsible for creating an PendingIntent when a user clicks a notification:

private fun getIntentOfNotification(context: Context, action: Actions): PendingIntent {
    val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE
    else PendingIntent.FLAG_MUTABLE
    val flags = flag or PendingIntent.FLAG_ONE_SHOT
    // PUSH CLICK EVENT is important
    val intent = Intent(PUSH_CLICK_EVENT).putExtra("key", gson.toJson(action))
    return PendingIntent.getBroadcast(context, 100, intent, flags)
}

Managing Push Click Events: Activity

This part of the code manages what happens when a user clicks on a notification:

private val pushActionReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        // Log the event
        logThis("PUSH_CLICK_EVENT : ${intent?.getStringExtra("key")}")
        // Parse your payload to the Required model using Gson
        val data = gson.fromJson(
                intent?.getStringExtra("key"), YourPayload::class.java)
        // Execute your business logic
    }
}

override fun onStart() {
    super.onStart()
    // Register the broadcast receiver
    ContextCompat.registerReceiver(
        this //activity,
        pushActionReceiver,
        // Below line is most important
        IntentFilter(PUSH_CLICK_EVENT),
        ContextCompat.RECEIVER_NOT_EXPORTED
    )
}

override fun onDestroy() {
    super.onDestroy()
    // Unregister the broadcast receiver
    unregisterReceiver(pushActionReceiver)
}

Conclusion

Creating in-app push notifications with extra information (payloads) and handling user interactions through clicks can significantly enhance our app's user engagement. By understanding and using the code and concepts presented in this guide, we'll be able to implement this feature effectively and create an engaging experience for our users.


That's it for today. Happy Coding...

0
Subscribe to my newsletter

Read articles from Romman Sabbir directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Romman Sabbir
Romman Sabbir

Senior Android Engineer from Bangladesh. Love to contribute in Open-Source. Indie Music Producer.