Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing Notification click listener #20

Merged
merged 4 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ override fun onCreate(savedInstanceState: Bundle?) {
}

```

##### iOS
Call `NotifierManager.onApplicationDidReceiveRemoteNotification(userInfo: userInfo)` on application's `didReceiveRemoteNotification` method.

Expand All @@ -228,7 +229,20 @@ Call `NotifierManager.onApplicationDidReceiveRemoteNotification(userInfo: userIn
return UIBackgroundFetchResult.newData
}

```
```


#### Detecting notification click and get payload data
Make sure you follow previous step for getting payload data properly.
```kotlin
NotifierManager.addListener(object : NotifierManager.Listener {
override fun onNotificationClicked(data: PayloadData) {
super.onNotificationClicked(data)
println("Notification clicked, Notification payloadData: $data")
}
})
```


#### Other functions
```kotlin
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ plugins {

allprojects {
group = "io.github.mirzemehdi"
version = "0.4.0"
version = "0.5.0"
val sonatypeUsername = gradleLocalProperties(rootDir).getProperty("sonatypeUsername")
val sonatypePassword = gradleLocalProperties(rootDir).getProperty("sonatypePassword")
val gpgKeySecret = gradleLocalProperties(rootDir).getProperty("gpgKeySecret")
Expand Down
2 changes: 2 additions & 0 deletions kmpnotifier/api/kmpnotifier.api
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ public final class com/mmk/kmpnotifier/notification/NotifierManager {

public abstract interface class com/mmk/kmpnotifier/notification/NotifierManager$Listener {
public abstract fun onNewToken (Ljava/lang/String;)V
public abstract fun onNotificationClicked (Ljava/util/Map;)V
public abstract fun onPayloadData (Ljava/util/Map;)V
public abstract fun onPushNotification (Ljava/lang/String;Ljava/lang/String;)V
}

public final class com/mmk/kmpnotifier/notification/NotifierManager$Listener$DefaultImpls {
public static fun onNewToken (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/lang/String;)V
public static fun onNotificationClicked (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/util/Map;)V
public static fun onPayloadData (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/util/Map;)V
public static fun onPushNotification (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/lang/String;Ljava/lang/String;)V
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.mmk.kmpnotifier.extensions

import android.content.Intent
import androidx.core.os.bundleOf
import com.mmk.kmpnotifier.Constants.ACTION_NOTIFICATION_CLICK
import com.mmk.kmpnotifier.Constants.KEY_ANDROID_FIREBASE_NOTIFICATION
import com.mmk.kmpnotifier.notification.NotifierManager
import com.mmk.kmpnotifier.notification.NotifierManagerImpl
import com.mmk.kmpnotifier.notification.configuration.NotificationPlatformConfiguration
Expand Down Expand Up @@ -36,11 +38,22 @@ public fun NotifierManager.onCreateOrOnNewIntent(intent: Intent?) {
if (intent == null) return
val extras = intent.extras ?: bundleOf()
val payloadData = mutableMapOf<String, Any>()

val isNotificationClicked =
extras.containsKey(ACTION_NOTIFICATION_CLICK)
|| extras.containsKey(KEY_ANDROID_FIREBASE_NOTIFICATION)
|| payloadData.containsKey(ACTION_NOTIFICATION_CLICK)

extras.keySet().forEach { key ->
val value = extras.get(key)
value?.let { payloadData[key] = value }
value?.let { payloadData[key] = it }
}
if (extras.containsKey("google.sent_time")) NotifierManagerImpl.onPushPayloadData(payloadData)


if (extras.containsKey(KEY_ANDROID_FIREBASE_NOTIFICATION))
NotifierManagerImpl.onPushPayloadData(payloadData.minus(ACTION_NOTIFICATION_CLICK))
if (isNotificationClicked)
NotifierManagerImpl.onNotificationClicked(payloadData.minus(ACTION_NOTIFICATION_CLICK))
}

internal fun NotifierManagerImpl.shouldShowNotification(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.mmk.kmpnotifier.firebase

import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.mmk.kmpnotifier.Constants
import com.mmk.kmpnotifier.extensions.shouldShowNotification
import com.mmk.kmpnotifier.notification.Notifier
import com.mmk.kmpnotifier.notification.NotifierManager
Expand All @@ -27,7 +28,8 @@ internal class MyFirebaseMessagingService : FirebaseMessagingService() {
notifierManager.onPushNotification(title = it.title, body = it.body)
}
if (message.data.isNotEmpty()) {
notifierManager.onPushPayloadData(message.data)
val data = message.data + mapOf( Constants.ACTION_NOTIFICATION_CLICK to Constants.ACTION_NOTIFICATION_CLICK)
notifierManager.onPushPayloadData(data)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.net.Uri
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import com.mmk.kmpnotifier.Constants.ACTION_NOTIFICATION_CLICK
import com.mmk.kmpnotifier.extensions.notificationManager
import com.mmk.kmpnotifier.notification.configuration.NotificationPlatformConfiguration
import com.mmk.kmpnotifier.permission.PermissionUtil
Expand All @@ -21,7 +22,7 @@ internal class AndroidNotifier(
) : Notifier {

override fun notify(title: String, body: String): Int {
val notificationID = Random.nextInt(0,Int.MAX_VALUE)
val notificationID = Random.nextInt(0, Int.MAX_VALUE)
notify(notificationID, title, body)
return notificationID
}
Expand Down Expand Up @@ -66,7 +67,9 @@ internal class AndroidNotifier(
}

private fun getPendingIntent(deepLink: String = ""): PendingIntent? {
val intent = getLauncherActivityIntent()
val intent = getLauncherActivityIntent()?.apply {
putExtra(ACTION_NOTIFICATION_CLICK, ACTION_NOTIFICATION_CLICK)
}
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

val flags =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.mmk.kmpnotifier

internal object Constants {
const val KEY_ANDROID_FIREBASE_NOTIFICATION = "google.sent_time"
const val KEY_IOS_FIREBASE_NOTIFICATION = "gcm.message_id"
const val ACTION_NOTIFICATION_CLICK = "com.mmk.kmpnotifier.notification.ACTION_NOTIFICATION_CLICK"
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ public object NotifierManager {
* @param body Notification body message
*/
public fun onPushNotification(title:String?,body:String?) {}

/**
* Called when notification is clicked
* @param data Push Notification Payload Data
*/
public fun onNotificationClicked(data: PayloadData) {}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import com.mmk.kmpnotifier.notification.configuration.NotificationPlatformConfig
import org.koin.core.component.get

internal object NotifierManagerImpl : KMPKoinComponent() {

private val listeners = mutableListOf<NotifierManager.Listener>()

fun initialize(configuration: NotificationPlatformConfiguration) {
Expand Down Expand Up @@ -45,6 +44,12 @@ internal object NotifierManagerImpl : KMPKoinComponent() {
listeners.forEach { it.onPushNotification(title = title, body = body) }
}

fun onNotificationClicked(data: PayloadData) {
println("Notification is clicked")
if (listeners.size == 0) println("There is no listener to notify onPushPayloadData")
listeners.forEach { it.onNotificationClicked(data) }
}

private fun requireInitialization() {
if (LibDependencyInitializer.isInitialized().not()) throw IllegalStateException(
"NotifierFactory is not initialized. " +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.mmk.kmpnotifier.extensions

import com.mmk.kmpnotifier.Constants.KEY_IOS_FIREBASE_NOTIFICATION
import com.mmk.kmpnotifier.notification.NotifierManager
import com.mmk.kmpnotifier.notification.NotifierManagerImpl
import com.mmk.kmpnotifier.notification.PayloadData
import com.mmk.kmpnotifier.notification.configuration.NotificationPlatformConfiguration
import platform.UserNotifications.UNMutableNotificationContent
import platform.UserNotifications.UNNotificationContent
Expand All @@ -20,12 +22,9 @@ import platform.UserNotifications.UNNotificationContent
* ```
*/
public fun NotifierManager.onApplicationDidReceiveRemoteNotification(userInfo: Map<Any?, *>) {
val payloadData = userInfo.keys
.filterNotNull()
.filterIsInstance<String>()
.associateWith { key -> userInfo[key] }

if (payloadData.containsKey("gcm.message_id")) NotifierManagerImpl.onPushPayloadData(payloadData)
val payloadData = userInfo.asPayloadData()
if (payloadData.containsKey(KEY_IOS_FIREBASE_NOTIFICATION))
NotifierManagerImpl.onPushPayloadData(payloadData)
}

internal fun NotifierManager.onUserNotification(notificationContent: UNNotificationContent) {
Expand All @@ -37,6 +36,10 @@ internal fun NotifierManager.onUserNotification(notificationContent: UNNotificat
NotifierManager.onApplicationDidReceiveRemoteNotification(userInfo)
}

internal fun NotifierManager.onNotificationClicked(notificationContent: UNNotificationContent) {
NotifierManagerImpl.onNotificationClicked(notificationContent.userInfo.asPayloadData())
}

internal fun NotifierManager.shouldShowNotification(notificationContent: UNNotificationContent): Boolean {
val configuration =
NotifierManagerImpl.getConfiguration() as? NotificationPlatformConfiguration.Ios
Expand All @@ -47,6 +50,14 @@ internal fun NotifierManager.shouldShowNotification(notificationContent: UNNotif
}
}


internal fun Map<Any?, *>.asPayloadData(): PayloadData {
return this.keys
.filterNotNull()
.filterIsInstance<String>()
.associateWith { key -> this[key] }
}

private fun UNNotificationContent.isPushNotification(): Boolean {
return userInfo.containsKey("gcm.message_id")
return userInfo.containsKey(KEY_IOS_FIREBASE_NOTIFICATION)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mmk.kmpnotifier.notification

import com.mmk.kmpnotifier.extensions.onApplicationDidReceiveRemoteNotification
import com.mmk.kmpnotifier.extensions.onNotificationClicked
import com.mmk.kmpnotifier.extensions.onUserNotification
import com.mmk.kmpnotifier.extensions.shouldShowNotification
import com.mmk.kmpnotifier.permission.IosPermissionUtil
Expand Down Expand Up @@ -65,6 +66,7 @@ internal class IosNotifier(
) {
val notificationContent = didReceiveNotificationResponse.notification.request.content
NotifierManager.onUserNotification(notificationContent)
NotifierManager.onNotificationClicked(notificationContent)
if (NotifierManager.shouldShowNotification(notificationContent)) withCompletionHandler()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ object AppInitializer {
super.onPayloadData(data)
println("Push Notification payloadData: $data")
}

override fun onNotificationClicked(data: PayloadData) {
super.onNotificationClicked(data)
println("Notification clicked, Notification payloadData: $data")
}
})
}
}
Loading