I have an app where I'm displaying notifications from chat apps after reading the with a Notification listener service and storing them in a room database.
Now I want to open the specific chat the notification is for in that app when the user clicks on it in my app UI (displayed in a recycler view). Right now, I'm just launching the apps by package name.
Is it possible to simulate clicking on the notification or trigger whatever action the notification has?
@RequiresApi(Build.VERSION_CODES.O)
override fun onNotificationPosted(sbn: StatusBarNotification) {
Log.d(TAG, "oN NOTIFY")
if (isConnected) {
val notification = sbn.notification
val extras = notification.extras
val packageName = sbn.packageName
// Extract the message content
val title = extras.getString(Notification.EXTRA_TITLE) ?: ""
val message = extras.getString(Notification.EXTRA_TEXT) ?: extras.getString(Notification.EXTRA_SUB_TEXT) ?: ""
// Check if the notification is from a chat app and contains chat notification
if (conversationApps.contains(packageName)
&& invalidNotificationText.none { message.contains(it) }) {
// Extract the sender/group image
val senderImageIcon = extras.getParcelable<Parcelable>(Notification.EXTRA_LARGE_ICON) ?: extras.getParcelable<Parcelable>(Notification.EXTRA_PICTURE)
Log.e(TAG, senderImageIcon.toString())
val senderImageBitmap: Bitmap? = makeBitmap(senderImageIcon)
val senderImageByteArray =
senderImageBitmap?.let { getByteArrayFromBitmap(it) } ?: byteArrayOf()
// Extract the app icon
val pm = applicationContext.packageManager
val appIcon = pm.getApplicationIcon(packageName)
val appIconBitmap: Bitmap? = makeBitmap(appIcon)
val appIconByteArray =
appIconBitmap?.let { getByteArrayFromBitmap(it) } ?: byteArrayOf()
// Create conversation object
val conversation = ConversationEntity(
0,
packageName,
title,
message,
senderImageByteArray,
appIconByteArray,
)
CoroutineScope(Dispatchers.IO).launch {
delay(500)
conversationRepository.deleteByPackageNameAndMessage(packageName, title, message)
conversationRepository.insertConversation(conversation)
}
}
}
}
I've actually been able to solve the issue.
To reply a notification with a reply action, I'm "recreating" the reply action from the notification with code from Rob J's article. I actually copied most of the implementation from this github repository shared under another Stack overflow question.
Creating the reply action looks like this:
override fun onNotificationPosted(sbn: StatusBarNotification) {
val action: Action? = NotificationUtils.getQuickReplyAction(sbn.notification, getPackageName())
...
}
and you can send the reply like this:
action.sendReply(myApplicationContext, "replyText")
Additionally, to open the chat (Without replying the message), I'm getting the contentIntent
(a Pending Intent) from the notification
in onNotificationPosted
like so:
override fun onNotificationPosted(sbn: StatusBarNotification) {
val notification = sbn.notification
val contentIntent = notification.contentIntent
...
}
To open the notification's respective app, I just call the send()
method on the pending intent.
contentIntent.send()