android kotlin - Notification direct reply action example

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.widget.Button
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.RemoteInput


class MainActivity : Activity() {
    @RequiresApi(Build.VERSION_CODES.S)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // get the context
        val context = this

        // get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)


        // Create and register notification channel api 26+
        val channelId = "My_Channel_ID"
        val notificationId = 1
        createNotificationChannel(channelId)


        // button click listener
        button.setOnClickListener {
            // The direct reply action, introduced
            // in Android 7.0 (API level 24)
            // Create an instance of remote input builder
            val remoteInput: RemoteInput = RemoteInput
                .Builder("KEY_TEXT_REPLY")
                .run {
                    setLabel("Write your message here")
                    build()
                }

            // Create an intent
            val intent = Intent(context, MyBroadcastReceiver::class.java)
            intent.action = "REPLY_ACTION"
            intent.putExtra("KEY_NOTIFICATION_ID", notificationId)
            intent.putExtra("KEY_CHANNEL_ID", channelId)
            intent.putExtra("KEY_MESSAGE_ID", 2)

            // Create a pending intent for the reply button
            val replyPendingIntent: PendingIntent = PendingIntent
                .getBroadcast(
                context,
                101,
                intent,
                PendingIntent.FLAG_MUTABLE or
                        PendingIntent.FLAG_UPDATE_CURRENT
            )

            // Create reply action and add the remote input
            val action: NotificationCompat.Action = NotificationCompat
                .Action.Builder(
                R.drawable.ic_action_backup,
                "Reply",
                replyPendingIntent
            ).addRemoteInput(remoteInput)
                .setAllowGeneratedReplies(true)
                .build()


            // Build a notification and add the action
            val builder = NotificationCompat.Builder(context, channelId)
                .setSmallIcon(R.drawable.ic_action_help_outline)
                .setContentTitle("Jones")
                .setContentText("Hello! how are you?")
                .addAction(action)

            // Finally, issue the notification
            NotificationManagerCompat.from(context).apply {
                notify(notificationId, builder.build())
            }
        }
    }



    // create notification channel
    private fun createNotificationChannel(channelId:String) {
        // Create the NotificationChannel,
        // but only on API 26+ (Android 8.0) because
        // the NotificationChannel class is new and
        // not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            val name = "My Channel"
            val channelDescription = "Channel Description"
            val importance = NotificationManager.IMPORTANCE_DEFAULT

            val channel = NotificationChannel(channelId,name,importance)
            channel.apply {
                description = channelDescription
            }

            // Finally register the channel with system
            val notificationManager = getSystemService(
                Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#DCDCDC"
    android:id="@+id/rootLayout"
    android:padding="24dp">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Notification"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
MyBroadcastReceiver.kt

package com.cfsuman.kotlintutorials

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.RemoteInput


class MyBroadcastReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        intent?.apply {
            if ("REPLY_ACTION" == action){
                val message = replyMessage(this)
                val messageId = getIntExtra("KEY_MESSAGE_ID",0)
                Toast.makeText(context,"$messageId : $message",
                    Toast.LENGTH_LONG).show()
            }

            context?.apply {
                val notificationId = getIntExtra("KEY_NOTIFICATION_ID",0)
                val channelId = getStringExtra("KEY_CHANNEL_ID")

                // Build a notification and add the action

                val builder = channelId?.let {
                    NotificationCompat.Builder(this, it)
                        .setSmallIcon(R.drawable.ic_action_help)
                        .setContentTitle("Title")
                        .setContentText("message sent!")
                }

                // Finally, issue the notification
                NotificationManagerCompat.from(this).apply {
                    if (builder != null) {
                        notify(notificationId, builder.build())
                    }
                }
            }
        }
    }


    private fun replyMessage(intent: Intent): CharSequence? {
        val remoteInput = RemoteInput.getResultsFromIntent(intent)
        return remoteInput?.getCharSequence("KEY_TEXT_REPLY")
    }
}
AndroidManifest.xml [add]

<receiver android:name=".MyBroadcastReceiver"/>
AndroidManifest.xml [Permission]

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />