{"id":13658556,"url":"https://github.com/line/abc-kmm-notifications","last_synced_at":"2025-04-24T11:32:04.154Z","repository":{"id":57726198,"uuid":"417353838","full_name":"line/abc-kmm-notifications","owner":"line","description":"Remote Notification Manager for Kotlin Multiplatform Mobile iOS and Android","archived":false,"fork":false,"pushed_at":"2023-03-20T22:40:11.000Z","size":212,"stargazers_count":56,"open_issues_count":2,"forks_count":2,"subscribers_count":9,"default_branch":"main","last_synced_at":"2024-08-02T05:09:04.781Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/line.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-10-15T03:11:28.000Z","updated_at":"2024-07-09T18:49:16.000Z","dependencies_parsed_at":"2024-01-17T03:26:14.168Z","dependency_job_id":null,"html_url":"https://github.com/line/abc-kmm-notifications","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/line%2Fabc-kmm-notifications","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/line%2Fabc-kmm-notifications/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/line%2Fabc-kmm-notifications/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/line%2Fabc-kmm-notifications/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/line","download_url":"https://codeload.github.com/line/abc-kmm-notifications/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223952527,"owners_count":17230906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T05:01:00.662Z","updated_at":"2024-11-10T12:30:24.349Z","avatar_url":"https://github.com/line.png","language":"Kotlin","funding_links":[],"categories":["Libraries"],"sub_categories":["📱 Device"],"readme":"![abc-kmm-notifications: Remote Notification Manager](images/cover.png)\n\n[![Kotlin](https://img.shields.io/badge/kotlin-1.5.21-blue.svg?logo=kotlin)](http://kotlinlang.org)\n[![KMM](https://img.shields.io/badge/KMM-0.2.7-lightgreen.svg?logo=KMM)](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile)\n[![AGP](https://img.shields.io/badge/AGP-7.0.1-green.svg?logo=AGP)](https://developer.android.com/studio/releases/gradle-plugin)\n[![Gradle](https://img.shields.io/badge/Gradle-7.0.2-blue.svg?logo=Gradle)](https://gradle.org)\n[![Platform](https://img.shields.io/badge/platform-ios,android-lightgray.svg?style=flat)](https://img.shields.io/badge/platform-ios-lightgray.svg?style=flat)\n\nRemote Notification Manager for [Kotlin Multiplatform Mobile](https://kotlinlang.org/docs/mpp-intro.html)\n\n## Features\n\n- Super easy to use APNs and FCM in one interface\n- Dramatically reduce code to write\n- Support for generic model mapping\n- Support FCM for iOS\n- Migration Support for React Native\n\n## Requirements\n- iOS\n  - Deployment Target 10.0 or higher\n- Android\n  - minSdkVersion 21\n\n## Installation\n\n### Gradle Settings\n\nAdd below gradle settings into your KMP (Kotlin Multiplatform Project)\n\n#### build.gradle.kts in root\n\n```kotlin\nbuildscript {\n    repositories {\n        gradlePluginPortal()\n        google()\n        mavenCentral()\n    }\n    dependencies {\n        classpath(\"com.android.tools.build:gradle:7.0.1\")\n        classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21\")\n        classpath(\"org.jetbrains.kotlin:kotlin-serialization:1.5.21\")\n        classpath(\"com.google.gms:google-services:4.3.5\")\n    }\n}\n```\n#### build.gradle.kts in shared\n```kotlin\nplugins {\n    id(\"com.android.library\")\n    kotlin(\"multiplatform\")\n    kotlin(\"plugin.serialization\")\n}\n\nval abcNotifications = \"com.linecorp.abc:kmm-notifications:0.4.1\"\nval kotlinxSerialization = \"org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2\"\n\nkotlin {\n    sourceSets {\n        ios {\n            binaries\n                .filterIsInstance\u003cFramework\u003e()\n                .forEach {\n                    it.transitiveExport = true\n                    it.export(abcNotifications)\n                }\n        }\n        android()\n\n        val commonMain by getting {\n            dependencies {\n                implementation(abcNotifications)\n                implementation(kotlinxSerialization)\n            }\n        }\n        val androidMain by getting {\n            dependencies {\n                implementation(abcNotifications)\n                api(abcNotifications)\n            }\n        }\n        val iosMain by getting {\n            dependencies {\n                implementation(abcNotifications)\n                api(abcNotifications)\n            }\n        }\n    }\n}\n```\n\n#### build.gradle.kts in androidApp\n```kotlin\nplugins {\n    id(\"com.google.gms.google-services\")\n}\n```\n\n## Usage\n\n### Definition of payload and map function with generic in commonMain of your project\n```kotlin\n@Serializable\ndata class Data(\n  val notificationType: String = \"\",\n  val id: Int = 0,\n)\n\n@Throws(Throwable::class)\nfun NotificationElement.payload() = decodedPayload\u003cData\u003e()\n```\n\n### Android\n```kotlin\nABCNotifications\n    .onNewToken(this) {\n        // TODO: send to register ${ABCDeviceToken.value} to server\n    }\n    .onDeletedMessages(this) {\n        // TODO: sync messages to server\n    }\n    .onMessageReceived(this) {\n        // FCM RemoteMessage\n        val remoteMessage = it.remoteMessage\n        \n        // decode to Payload with Data\n        val payload = it.payload()\n\n        // decode to Data\n        val data = it.decodedData\u003cData\u003e()\n\n        // TODO: present a dialog for push notification\n    }\n    .beginListening()\n```\n\n### iOS\n\n```swift\nABCNotifications.Companion()\n    .registerSettings {\n        $0.add(type: .alert)\n        $0.add(type: .badge)\n        $0.add(type: .sound)\n    }\n    .onNewToken(target: self) {\n        // TODO: send to register ${ABCDeviceToken.rawValue} to server\n    }\n    .onMessageReceived(target: self) {\n        guard let payload = try? $0.payload() else { return }\n\n        if $0.isInactive {\n            // TODO: present a view controller on inactive\n        } else {\n            // TODO: present a toast message on active\n        }\n    }.beginListening()\n```\n\n#### Required implementation in AppDelegate\n\n```swift\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -\u003e Bool {\n        ABCNotificationCenterDelegate.Companion().applicationDidFinishLaunching(options: options)\n        return true\n    }\n    \n    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {\n        ABCNotificationCenterDelegate.Companion().applicationDidRegisterForRemoteNotifications(deviceToken: deviceToken)\n    }\n}\n\nextension AppDelegate: UNUserNotificationCenterDelegate {\n    \n    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -\u003e Void) {\n        ABCNotificationCenterDelegate.Companion().userNotificationCenterWillPresent(notification: notification)\n    }\n    \n    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -\u003e Void) {\n        ABCNotificationCenterDelegate.Companion().userNotificationCenterDidReceive(response: response)\n    }\n}\n```\n\n#### FCM on iOS\n\n1. Insert the dependency in shared.podspec\n    ```ruby\n    spec.dependency 'FirebaseMessaging'\n    ```\n2. Insert function into cocoapods definition in build.gradle.kts (shared)\n    ```kotlin\n    cocoapods {\n        noPodspec()\n    }\n    ```\n\n3. Initializing\n    ```swift\n    ABCNotifications.Companion()\n        .allowsFCMOnIOS()\n        .registerSettings {\n            $0.add(type: .alert)\n            $0.add(type: .badge)\n            $0.add(type: .sound)\n        }\n        .onNewToken(target: self) {\n            print(\"onNewToken -\u003e \", ABCDeviceToken.Companion().FCMToken)\n            // TODO: send to register ${ABCDeviceToken.FCMToken} to server\n        }.beginListening()\n    ```\n\n## Advanced\n\n### Shared configuration in commonMain\n```kotlin\n\nfun ABCNotifications.Companion.configure(block: ABCNotifications.Companion.() -\u003e Unit) {\n    apply(block)\n\n    onNewToken(this) {\n        // TODO: send to register ${ABCDeviceToken.value} to server\n    }.beginListening()\n}\n```\n\n### Android\n```kotlin\n\nABCNotifications.configure {\n    onDeletedMessages(this) {\n        // TODO: sync messages to server\n    }\n    onMessageReceived(this) {\n        // FCM RemoteMessage\n        val remoteMessage = it.remoteMessage\n\n        // decode to Payload with Data\n        val payload = it.payload()\n\n        // decode to Data\n        val data = it.decodedData\u003cData\u003e()\n\n        // TODO: present a dialog for push notification\n    }\n}\n```\n\n### iOS\n\n```swift\nABCNotifications.Companion().configure { [unowned self] in\n    $0.registerSettings {\n        $0.add(type: .alert)\n        $0.add(type: .badge)\n        $0.add(type: .sound)\n    }\n    $0.onMessageReceived(target: self) {\n        guard let payload = try? $0.payload() else { return }\n\n        if $0.isInactive {\n            // TODO: present a view controller on inactive\n        } else {\n            // TODO: present a toast message on active\n        }\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fline%2Fabc-kmm-notifications","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fline%2Fabc-kmm-notifications","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fline%2Fabc-kmm-notifications/lists"}