Kotlin SDK
Install and configure the Android SDK, connect Firebase Messaging, and handle taps.
Requirements: Android 7.0+ (minSdk 24), Java 17, and a Firebase project configured for the app.
Samples on this page show placeholders. Sign in to the dashboard in this browser and they fill in with your own organization, app and mobile key.
Install
dependencies {
implementation("dev.carillon:carillon:0.2.0")
}Add your Firebase project's google-services.json to the app module and apply the Google services plugin.
Use a service account from that same project in Carillon.
plugins {
id("com.google.gms.google-services")
}Configure
import dev.carillon.sdk.CarillonCarillon.configure(context, key = "carillon_mk_live_your_mobile_key", debug = true)// Call from a coroutine with the current Activity.Carillon.requestPermission(activity) // ALLOWED | DENIEDrequestPermission takes an Activity because Android's request API does. Below API 33 nothing is
asked and nothing is shown, and the answer comes on every version from
NotificationManager.areNotificationsEnabled(), which is wider than the runtime permission and the
only thing that also sees notifications switched off in Settings.
The permission is declared by the library
POST_NOTIFICATIONS is in the SDK's own manifest and merges into your app, so you do not declare it
yourself. An app can only be granted a permission its own manifest declares.
Forward token rotation and messages
Declare the service the SDK ships:
<service android:name="dev.carillon.sdk.CarillonMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>Or, if you already have a FirebaseMessagingService, forward two calls from it. Firebase dispatches
to one service per application, so declaring both leaves one of them never running.
override fun onNewToken(token: String) = Carillon.didRotate(token)
override fun onMessageReceived(message: RemoteMessage) = Carillon.didReceive(message)Forward the launching intent
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Carillon.didOpen(intent)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
Carillon.didOpen(intent)
}Give the launcher activity android:launchMode="singleTop" so onNewIntent fires rather than a
second instance being created.
Identity, tags, and open callbacks
import dev.carillon.sdk.tagOf
Carillon.identify("user-42")
Carillon.clearIdentity()
Carillon.setTags(mapOf("plan" to tagOf("pro"), "seats" to tagOf(12)))
Carillon.optOut()
Carillon.optIn()
Carillon.onOpened = { notification ->
// notification.deliveryId, notification.data, notification.openedAtMs
}
val info = Carillon.debugInfo()Environment
Always production. FCM has no sandbox; the field exists for iOS.
Foreground notifications
Configure Carillon in your Application, before Firebase callbacks arrive.
CarillonMessagingService forwards received messages. If you own the service, call
Carillon.didReceive(message) from onMessageReceived.
Carillon.onReceived = { notification ->
// Read notification.data and return SUPPRESS for your own in-app UI.
NotificationPresentation.SHOW
}
Carillon.clearNotifications()The SDK displays foreground notification messages unless the handler returns SUPPRESS.
It uses an existing android.notification.channel_id, or creates carillon_default
(“Notifications”). Provide a carillon_notification_icon drawable for the small icon;
the app icon is the fallback. Android 8+ channel settings control sound.
Android 13+ requires notification permission before posting.
Images download through WorkManager with a 10-second budget and a 10 MiB cap. Failures keep
the text. thread_id groups foreground notifications. Background notification messages are
displayed by FCM itself; Carillon's foreground hook does not suppress those.
Clearing cancels pending display work and removes the app's notifications. It does not opt
out the device. Continue forwarding launcher onCreate and onNewIntent to didOpen:
the notification's tap intent carries the original data and delivery stamp.
Device ID
Carillon.deviceId is null before registration succeeds. Carillon.onDeviceIdChanged fires
on first registration and on actual ID changes. The SDK sends its installation proof to preserve
the ID across token rotation. See device identity.
Stored state
SharedPreferences under dev.carillon.sdk: the last registered state hash, the server device id,
installation proof and queued events. Android backup may restore this state; the device ID
is not an authentication credential.