Skip to content
Notifie
Documentation
DocsSDKs

SDKs

Android SDK

The complete Android surface: initialization, identity, events, and FCM enrolment and handling.

Install

app/build.gradle.kts
implementation("dev.notifie:notifie-android:0.1.0-beta.6")

The SDK's own manifest already contributes INTERNET and POST_NOTIFICATIONS, so events and permission prompts work as soon as the module resolves. Remote push additionally needs Google Services wired up, which the Firebase section below covers by hand; notifie init does the same automatically if you have the CLI installed.

Initialize

Application.kt
import dev.notifie.Notifie

Notifie.initialize(
    context = applicationContext,
    apiKey = BuildConfig.NOTIFIE_KEY
)

Requires an Application context and a non-blank key. Initializing twice with the same key and URL is a no-op, so calling it from Application.onCreate is safe. Every method is @JvmStatic, so Java callers use Notifie.initialize(...) directly.

Identity and events

Kotlin
Notifie.identify("user-42", mapOf("plan" to "pro"))
Notifie.track("checkout_completed", mapOf("amount" to 29.0))

Notifie.reset()   // on logout

install, first_open, app_open, and session_start are collected automatically from the activity lifecycle, along with locale and timezone. Do not track them yourself.

For Firebase Authentication, call Notifie.identify(FirebaseAuth.getInstance().currentUser!!.uid)after sign-in. Notifie links events and device tokens to that stable external ID; it does not read the Firebase user automatically.

Push notifications

Request permission and register
Notifie.enableNotifications { enrollment ->
    when (enrollment) {
        NotificationEnrollment.ENROLLED -> Unit
        NotificationEnrollment.DENIED -> showWhyNotificationsHelp()
        NotificationEnrollment.TOKEN_ERROR -> log("no FCM token: Firebase missing or unreachable")
        NotificationEnrollment.NOT_INITIALIZED -> error("call initialize first")
    }
}

This requests POST_NOTIFICATIONS on API 33 and above, fetches the FCM token, and registers it. The no-argument enableNotifications() overload does the same without reporting the outcome. Unlike iOS, Android may re-prompt, but a user who has refused twice is permanently denied.

The file alone does nothing. The Google Services Gradle plugin is what converts it into the resources Firebase reads, so declare id("com.google.gms.google-services") version "4.4.2" apply false in the root build.gradle.kts and apply id("com.google.gms.google-services") in the app module. Without it TOKEN_ERROR persists no matter how many times the file is re-added.

Handling messages

MessagingService.kt
class MessagingService : FirebaseMessagingService() {
    override fun onMessageReceived(message: RemoteMessage) {
        Notifie.handleRemoteMessage(applicationContext, message)
    }

    override fun onNewToken(token: String) {
        Notifie.registerPushToken(applicationContext, token)
    }
}

handleRemoteMessage presents the notification, records receipt, and ignores any FCM traffic that did not originate from Notifie, so it coexists with your own messages. Register a setBackgroundMessageHandler to observe payloads while the process is backgrounded or terminated.

Opens and deep links

You do not write any code to attribute a tap. The SDK owns the tap, records the open, and then routes it — so notification_opened appears in the dashboard whether or not your app handles the destination.

The destination is an ordinary Android deep link. Whatever you set as the notification's deep link is opened with ACTION_VIEW, so declare an intent filter for your own scheme and the tap lands on that screen:

AndroidManifest.xml
<activity android:name=".OrderActivity" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="myapp" android:host="orders" />
    </intent-filter>
</activity>

A deep link nothing declares is not an error and is not lost: the SDK falls back to opening the app's launcher activity. If the notification carries no deep link at all, the launcher opens directly.

The notification payload travels with the tap as intent extras, so the destination activity can read what was sent — including any customData your backend attached:

OrderActivity.kt
val data = intent.extras?.keySet()?.associateWith {
    intent.extras?.getString(it).orEmpty()
}.orEmpty()

val orderId = data["orderId"]
val link = Notifie.deepLink(data)

Receipts and opens are recorded with stable, invocation-derived event ids and are deduplicated, so an Activity recreation or an out-of-order redelivery does not produce a second open.