diff --git a/README.md b/README.md index b2d33b0..3e77c18 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,7 @@ override fun onCreate(savedInstanceState: Bundle?) { } ``` + ##### iOS Call `NotifierManager.onApplicationDidReceiveRemoteNotification(userInfo: userInfo)` on application's `didReceiveRemoteNotification` method. @@ -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 diff --git a/build.gradle.kts b/build.gradle.kts index 0f39b07..5a04e8f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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") diff --git a/kmpnotifier/api/kmpnotifier.api b/kmpnotifier/api/kmpnotifier.api index 1e93403..0960661 100644 --- a/kmpnotifier/api/kmpnotifier.api +++ b/kmpnotifier/api/kmpnotifier.api @@ -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 } diff --git a/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.kt b/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.kt index 0e97130..517b570 100644 --- a/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.kt +++ b/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.kt @@ -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 @@ -36,11 +38,22 @@ public fun NotifierManager.onCreateOrOnNewIntent(intent: Intent?) { if (intent == null) return val extras = intent.extras ?: bundleOf() val payloadData = mutableMapOf() + + 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 { diff --git a/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/firebase/MyFirebaseMessagingService.kt b/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/firebase/MyFirebaseMessagingService.kt index eca2266..0bffd60 100644 --- a/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/firebase/MyFirebaseMessagingService.kt +++ b/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/firebase/MyFirebaseMessagingService.kt @@ -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 @@ -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) } } } \ No newline at end of file diff --git a/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/notification/AndroidNotifier.kt b/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/notification/AndroidNotifier.kt index fd25aa9..6c5bbc2 100644 --- a/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/notification/AndroidNotifier.kt +++ b/kmpnotifier/src/androidMain/kotlin/com/mmk/kmpnotifier/notification/AndroidNotifier.kt @@ -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 @@ -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 } @@ -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 = diff --git a/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/Constants.kt b/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/Constants.kt new file mode 100644 index 0000000..f024017 --- /dev/null +++ b/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/Constants.kt @@ -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" +} \ No newline at end of file diff --git a/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManager.kt b/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManager.kt index 72a45cb..55cffa7 100644 --- a/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManager.kt +++ b/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManager.kt @@ -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) {} } diff --git a/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManagerImpl.kt b/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManagerImpl.kt index 2664fda..daa5b80 100644 --- a/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManagerImpl.kt +++ b/kmpnotifier/src/commonMain/kotlin/com/mmk/kmpnotifier/notification/NotifierManagerImpl.kt @@ -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() fun initialize(configuration: NotificationPlatformConfiguration) { @@ -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. " + diff --git a/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.ios.kt b/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.ios.kt index ebcb2bf..21b6888 100644 --- a/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.ios.kt +++ b/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/extensions/NotifierManagerExt.ios.kt @@ -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 @@ -20,12 +22,9 @@ import platform.UserNotifications.UNNotificationContent * ``` */ public fun NotifierManager.onApplicationDidReceiveRemoteNotification(userInfo: Map) { - val payloadData = userInfo.keys - .filterNotNull() - .filterIsInstance() - .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) { @@ -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 @@ -47,6 +50,14 @@ internal fun NotifierManager.shouldShowNotification(notificationContent: UNNotif } } + +internal fun Map.asPayloadData(): PayloadData { + return this.keys + .filterNotNull() + .filterIsInstance() + .associateWith { key -> this[key] } +} + private fun UNNotificationContent.isPushNotification(): Boolean { - return userInfo.containsKey("gcm.message_id") + return userInfo.containsKey(KEY_IOS_FIREBASE_NOTIFICATION) } \ No newline at end of file diff --git a/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/notification/IosNotifier.kt b/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/notification/IosNotifier.kt index 41e8210..c938ff8 100644 --- a/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/notification/IosNotifier.kt +++ b/kmpnotifier/src/iosMain/kotlin/com/mmk/kmpnotifier/notification/IosNotifier.kt @@ -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 @@ -65,6 +66,7 @@ internal class IosNotifier( ) { val notificationContent = didReceiveNotificationResponse.notification.request.content NotifierManager.onUserNotification(notificationContent) + NotifierManager.onNotificationClicked(notificationContent) if (NotifierManager.shouldShowNotification(notificationContent)) withCompletionHandler() } diff --git a/sample/src/commonMain/kotlin/com/mmk/kmpnotifier/sample/AppInitializer.kt b/sample/src/commonMain/kotlin/com/mmk/kmpnotifier/sample/AppInitializer.kt index 8a4b706..999da65 100644 --- a/sample/src/commonMain/kotlin/com/mmk/kmpnotifier/sample/AppInitializer.kt +++ b/sample/src/commonMain/kotlin/com/mmk/kmpnotifier/sample/AppInitializer.kt @@ -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") + } }) } } \ No newline at end of file