Android SDK
activeThe Android output of the Binoban Native SDK — the exhaustive
configuration and method reference. For installing the dependency, initializing
in your Application, and sending a first event, start with the
Track from Android tutorial.
Requirements: minSdk 21+, compiled against a recent Android SDK (the demo
uses compileSdk 35), Kotlin and Java 11+. Check the
compatibility matrix for the current version.
Configuration options
Set these inside the configuration lambda:
| Option | Default | Purpose |
|---|---|---|
application | — | Your Application instance. Only AndroidDeepLinkPlugin reads it — the rest of the SDK obtains its Android context automatically. |
apiHost | none | API endpoint. Required — no default; a blank host disables the SDK (no-op). |
collectDeviceId | true | Collect a device identifier. |
trackApplicationLifecycleEvents | true | Auto-track app open/close/update. |
trackDeepLinks | true | Gates deep-link tracking within AndroidDeepLinkPlugin, which you must add yourself. On its own this option does nothing. |
flushAt | 20 | Send after this many queued events. |
flushInterval | 30 | …or after this many seconds. |
Track and identify
Properties and traits are JsonObjects — build them with buildJsonObject { put(...) }:
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
// Record an action
binoban.track("purchase", buildJsonObject {
put("item", "shoes")
put("price", "49.99")
})
// Associate the current person with your user ID + traits
binoban.identify("user-123", buildJsonObject {
put("email", "user@example.com")
put("firstName", "John")
})
Other methods
// Send queued events immediately
binoban.flush()
// Clear identity and start a new anonymousId — call on logout
binoban.reset()
Read the current identity
binoban.anonymousId() // String — always present
binoban.userId() // String? — null until identify
binoban.deviceId() // String? — present when collectDeviceId is on
binoban.traits() // JsonObject? — current traits
See Identity strategy for how these fit together across platforms.
Runtime controls
The Android SDK exposes a few controls useful in development and for honoring user preferences:
Binoban.debugLogsEnabled = true // verbose console logging (static)
binoban.enabled = false // pause/resume all tracking
binoban.configuration.flushAt = 10
binoban.configuration.flushInterval = 15
Push notifications
Push runs on Firebase Cloud Messaging. Binoban sends data-only messages, so
your FirebaseMessagingService forwards them to the SDK, which displays and
tracks them. For the step-by-step integration see
App push on Android.
Entry points
| Call | Purpose |
|---|---|
Notification.initialize(config) | Configure icon, colour, and channel. Call from Application.onCreate. Persisted, so a cold FCM process can bootstrap from it. |
Notification.notify(data) | Display an incoming push. Pass RemoteMessage.data. Ignores any payload whose source is not "binoban", or that has no id. |
Notification.refreshToken(token) | Register an FCM token. Works with no live SDK instance — caches and replays on next launch. |
binoban.setDeviceToken(token) | Same registration through a live instance. Stamps context.device.token on every later event. |
NotificationInteractionManager.setHandler(handler) | Install a custom interaction handler. |
NotificationInteractionManager.drainPendingInteractions() | Consume interactions buffered before your handler was installed. Delivery-only — already tracked. |
Both registration paths emit bb_notification_registered carrying the token —
see Push events.
Configuration
NotificationPlatformConfiguration.Android:
| Field | Default | Purpose |
|---|---|---|
notificationIconResId | null | Small icon drawable resource. |
notificationIconColorResId | null | Icon tint colour resource. |
notificationChannelData | see below | The channel to post on. |
NotificationPlatformConfiguration.Android.NotificationChannelData:
| Field | Default | Purpose |
|---|---|---|
id | "DEFAULT_NOTIFICATION_CHANNEL_ID" | Channel id. |
name | "General" | Channel name shown in Android settings. |
description | "" | Channel description. |
soundUri | null | Custom sound URI as a string; null uses the default. |
The channel is created at IMPORTANCE_HIGH. An existing channel with the same id
is reused unchanged and a warning is logged — Android does not permit raising
importance after creation.
Interaction handling
Clicks, dismissals, and deep-link opening are handled by the SDK. To read custom
data or route taps yourself, subclass DefaultNotificationInteractionHandler and
call super so tracking still fires.
NotificationInteraction:
| Field | Type | Meaning |
|---|---|---|
notificationUuid | String | The notification's tracking token. |
type | NotificationInteractionType | DELIVERED, CLICKED, CLOSED, FAILED, OPENED. |
actionId | String? | Tapped button id; null for a body tap. |
uri | String? | Resolved target — the button's own target, or the main one. |
customData | Map<String, String>? | The customData sent with the push. |
reason | String? | Failure reason, on FAILED. |
Behaviour and limits
- Permission. Display requires
POST_NOTIFICATIONSon Android 13+. Without it the SDK dispatches aFAILEDinteraction with reasonnotification permissionand displays nothing. - Action buttons are capped at 3.
- Images are downloaded asynchronously; the notification is posted first and updated when the image arrives.
- Tracking is at-least-once. Each interaction is cached durably before the live call, so an offline device still reports on next open.
Deep-link tracking
Android can record the deep links that launch your app, emitting a
deep_link_opened event. This is opt-in — the plugin is not registered for you:
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
val binoban = Binoban("YOUR_API_KEY", "YOUR_SOURCE_ID") {
application = this@MyApp // required by this plugin
apiHost = "your-api-host"
}
binoban.add(AndroidDeepLinkPlugin())
}
}
application is required here and only here; the rest of the SDK resolves its
Android context on its own. Omit it and plugin setup fails — the cause is reported
to Configuration.errorHandler, the plugin is not registered, and the SDK keeps
working with deep-link tracking off. Set trackDeepLinks = false to stop tracking
while leaving the plugin installed.
This is separate from notification taps: a deep link on a notification is opened and tracked by the SDK's own trampoline, with no plugin needed.
The deep_link_opened event
Emitted once per Activity created from an intent that carries data.
| Property | Always present | Value |
|---|---|---|
url | yes | The full link that launched the Activity. |
referrer | no | The launching app or source, when Android reports one. |
| link query parameters | no | Every query parameter on the link, flattened to top-level properties — so utm_source, utm_campaign and similar arrive without extra work. |
Query parameters with blank values are dropped. Parameters are written before
referrer and url, so a link carrying its own ?url= or ?referrer= cannot
overwrite the values Android actually reported — attribution a link doesn't control
is not spoofable by that link. When Android reports no referrer, a referrer
parameter on the link is used, which is the ordinary campaign-tagging case.
Before 1.1.0 a ?referrer= parameter did overwrite the OS-reported referrer.
Payloads for links carrying that parameter changed in 1.1.0.
Non-hierarchical links (mailto:, for example) have no query parameters to extract;
the event still reports url.
Next steps
- Example Apps — binoban-example-android is a runnable integration of this surface.
- iOS SDK — the matching iOS setup.
- Native SDK overview — shared concepts and the full method surface.
- Identity strategy · Go-live checklist