App push on Android
activeThis how-to wires the Binoban Native SDK into your Android app's Firebase Cloud Messaging setup, so Engage pushes are displayed and their delivery, taps, and dismissals reported.
Work through App push first — it covers the prerequisites, the
shape of the integration, and the source marker the examples below branch on.
1. Declare and request permission
Android 13+ requires runtime permission before anything can be displayed. Without
it the SDK reports a failed interaction instead of showing a notification.
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
// reflect the outcome in your UI
}
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
On Android 12 and below the permission is granted implicitly.
2. Initialize in Application.onCreate
Initialize from Application, not an Activity — a push can arrive while your app
is backgrounded or killed, and the SDK must be able to display it without any UI
having started.
import android.app.Application
import io.binoban.sdk.core.Notification
import io.binoban.sdk.core.platform.notifier.notification.configuration.NotificationPlatformConfiguration
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
Notification.initialize(
NotificationPlatformConfiguration.Android(
notificationIconResId = R.drawable.ic_notification,
notificationChannelData = NotificationPlatformConfiguration.Android.NotificationChannelData(
id = "binoban_engage",
name = "Updates",
description = "Order and account updates"
)
)
)
}
}
The SDK creates this channel at IMPORTANCE_HIGH, which heads-up notifications
require. If a channel with that id already exists, Android does not allow
raising its importance — the SDK reuses it as-is and logs a warning. If your
existing channel sits below IMPORTANCE_HIGH, use a fresh channel id here.
3. Forward FCM callbacks
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import io.binoban.sdk.core.Notification
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
if (message.data["source"] == "binoban") {
Notification.notify(message.data)
} else {
// your own push handling
}
}
override fun onNewToken(token: String) {
super.onNewToken(token)
Notification.refreshToken(token)
}
}
Register it in your manifest if you have not already:
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
The source check
is not there to protect the SDK — Notification.notify already drops non-Binoban
payloads on its own, so calling it unconditionally is safe. The branch exists so
that your else arm does not also fire for a Binoban push. If your service
handles nothing but Binoban messages, call notify bare.
Notification.refreshToken works even when no SDK instance is live — the common
case for a token delivered to a backgrounded app. It caches the registration and
replays it on next launch.
Register the token you already have
onNewToken only fires when FCM generates a token — on a fresh install, or on
rotation. An app that already uses FCM has a token in hand, and that callback will
not fire again for existing installs. Fetch it once at startup so those devices
register too:
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
Notification.refreshToken(task.result)
}
}
refreshToken is safe to call repeatedly — registering the same token twice is
harmless.
4. Taps and dismissals
Clicks, dismissals, and deep-link opening are handled for you. The SDK tracks the interaction and opens the notification's target — or the tapped action button's target — with no extra wiring.
To read the customData sent with a push, or to route the tap through your own
navigation instead, register a handler. Subclass the default one and call super
so the SDK's own tracking still fires:
import io.binoban.sdk.core.platform.notifier.notification.DefaultNotificationInteractionHandler
import io.binoban.sdk.core.platform.notifier.notification.NotificationInteraction
import io.binoban.sdk.core.platform.notifier.notification.NotificationInteractionManager
class MyNotificationHandler : DefaultNotificationInteractionHandler() {
override fun onNotificationInteraction(interaction: NotificationInteraction) {
super.onNotificationInteraction(interaction) // keep SDK tracking
val deepLink = interaction.uri // tapped body or button target
val data = interaction.customData // your push customData, or null
// route as your app sees fit
}
}
// once, at startup:
NotificationInteractionManager.setHandler(MyNotificationHandler())
interaction.uri resolves to the tapped button's target when a button was
pressed, or the notification's main target for a body tap.
Verify it worked
- Your next flushed batch carries a
bb_notification_registeredevent with the token. - Send a test campaign from the panel. The notification appears, and
bb_notification_deliveredfollows; tapping it producesbb_notification_clicked.
See Push events for the full list.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Nothing is displayed | POST_NOTIFICATIONS not granted — the SDK reports a failed interaction with reason notification permission. Or a pre-existing channel with that id sits below IMPORTANCE_HIGH. |
| Messages arrive but nothing shows | Notification.notify is not being called, or it runs before initialize. |
| Existing installs never register | Only onNewToken is wired. It does not fire for a device that already had a token — fetch it once at startup as well. |
| Your own pushes get displayed twice | Your handler's else arm is also running for Binoban messages. Branch on source. |
Next steps
- App push on iOS · App push in React Native
- Android SDK reference — the full method surface.
- Push events — what gets emitted, and the payload keys.
- Web push — the browser equivalent.