Kotlin SDK
Install and configure the Android SDK, connect Firebase Messaging, and handle taps.
For text, number, boolean and date attributes, SDK methods and audience operators, see Tags.
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.
Emulator setup
Use an Android Virtual Device image with Google APIs or Google Play and working
Google Play services. A plain AOSP image cannot obtain an FCM token. Match the
Firebase Android app's package name and use its google-services.json.
A signed-in Google account is not listed as a prerequisite for modern FCM token
registration; do not treat signing in as the fix for every missing token.
Check Carillon.debugInfo() for the token and registration result before testing
delivery. See Firebase's Android prerequisites.
Install
Use an explicit release version from Maven Central.
dependencies {
implementation("com.exostack:carillon:0.5.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
Carillon.identify("user-42")
Carillon.clearIdentity()
Carillon.setTag("plan", "pro")
Carillon.setTagNumber("seats", 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.
Related pages
Track opens · Devices · Troubleshooting
Merge tags
setTags merges keys; pass null to remove a key. Use setTag("plan", "pro")
for one key and removeTag("plan") to delete it. Omitted keys remain unchanged.
See tags and backend updates.
Receipt tracking
SDK 0.5.0 reports observed receipts from its receive callback and recovers notifications still present when the app starts or resumes. It does not report an open for these notifications. See receipt tracking for platform limits, offline reporting, and reading the timestamps in a trace.