Remote Notification Manager for Kotlin Multiplatform Mobile
Add below gradle settings into your KMP (Kotlin Multiplatform Project)
buildscript {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.0.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21")
classpath("org.jetbrains.kotlin:kotlin-serialization:1.5.21")
classpath("com.google.gms:google-services:4.3.5")
}
}
plugins {
id("com.android.library")
kotlin("multiplatform")
kotlin("plugin.serialization")
}
val abcNotifications = "com.linecorp.abc:kmm-notifications:0.4.1"
val kotlinxSerialization = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2"
kotlin {
sourceSets {
ios {
binaries
.filterIsInstance<Framework>()
.forEach {
it.transitiveExport = true
it.export(abcNotifications)
}
}
android()
val commonMain by getting {
dependencies {
implementation(abcNotifications)
implementation(kotlinxSerialization)
}
}
val androidMain by getting {
dependencies {
implementation(abcNotifications)
api(abcNotifications)
}
}
val iosMain by getting {
dependencies {
implementation(abcNotifications)
api(abcNotifications)
}
}
}
}
plugins {
id("com.google.gms.google-services")
}
@Serializable
data class Data(
val notificationType: String = "",
val id: Int = 0,
)
@Throws(Throwable::class)
fun NotificationElement.payload() = decodedPayload<Data>()
ABCNotifications
.onNewToken(this) {
// TODO: send to register ${ABCDeviceToken.value} to server
}
.onDeletedMessages(this) {
// TODO: sync messages to server
}
.onMessageReceived(this) {
// FCM RemoteMessage
val remoteMessage = it.remoteMessage
// decode to Payload with Data
val payload = it.payload()
// decode to Data
val data = it.decodedData<Data>()
// TODO: present a dialog for push notification
}
.beginListening()
ABCNotifications.Companion()
.registerSettings {
$0.add(type: .alert)
$0.add(type: .badge)
$0.add(type: .sound)
}
.onNewToken(target: self) {
// TODO: send to register ${ABCDeviceToken.rawValue} to server
}
.onMessageReceived(target: self) {
guard let payload = try? $0.payload() else { return }
if $0.isInactive {
// TODO: present a view controller on inactive
} else {
// TODO: present a toast message on active
}
}.beginListening()
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ABCNotificationCenterDelegate.Companion().applicationDidFinishLaunching(options: options)
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
ABCNotificationCenterDelegate.Companion().applicationDidRegisterForRemoteNotifications(deviceToken: deviceToken)
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
ABCNotificationCenterDelegate.Companion().userNotificationCenterWillPresent(notification: notification)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
ABCNotificationCenterDelegate.Companion().userNotificationCenterDidReceive(response: response)
}
}
Insert the dependency in shared.podspec
spec.dependency 'FirebaseMessaging'
Insert function into cocoapods definition in build.gradle.kts (shared)
cocoapods {
noPodspec()
}
Initializing
ABCNotifications.Companion()
.allowsFCMOnIOS()
.registerSettings {
$0.add(type: .alert)
$0.add(type: .badge)
$0.add(type: .sound)
}
.onNewToken(target: self) {
print("onNewToken -> ", ABCDeviceToken.Companion().FCMToken)
// TODO: send to register ${ABCDeviceToken.FCMToken} to server
}.beginListening()
fun ABCNotifications.Companion.configure(block: ABCNotifications.Companion.() -> Unit) {
apply(block)
onNewToken(this) {
// TODO: send to register ${ABCDeviceToken.value} to server
}.beginListening()
}
ABCNotifications.configure {
onDeletedMessages(this) {
// TODO: sync messages to server
}
onMessageReceived(this) {
// FCM RemoteMessage
val remoteMessage = it.remoteMessage
// decode to Payload with Data
val payload = it.payload()
// decode to Data
val data = it.decodedData<Data>()
// TODO: present a dialog for push notification
}
}
ABCNotifications.Companion().configure { [unowned self] in
$0.registerSettings {
$0.add(type: .alert)
$0.add(type: .badge)
$0.add(type: .sound)
}
$0.onMessageReceived(target: self) {
guard let payload = try? $0.payload() else { return }
if $0.isInactive {
// TODO: present a view controller on inactive
} else {
// TODO: present a toast message on active
}
}
}