Android SDK (Kotlin)
com.reachbell:reachbell-android is the native-Android client SDK for ReachBell — the mobile counterpart to the browser SDK. It fetches the device's FCM registration token and registers it so your dashboard or the Node server SDK can target the device. It does not send pushes or render notification UI — FCM delivers them and Android renders them.
Preview: This SDK is newly released and was written against FCM and the documented APIs. Build it with Gradle and test on a device before shipping to production.
Install
The SDK is published as a Gradle library (Kotlin, minSdk 21, coroutines). Add it to your app module:
// app/build.gradle.kts
dependencies {
implementation("com.reachbell:reachbell-android:0.1.0")
}firebase-messaging comes transitively from this SDK, so you do not need to add it yourself. ReachBell delivers Android push through your own Firebase project, so a Firebase/FCM project is a prerequisite — see Setup.
Setup
ReachBell sends to the FCM tokens this SDK registers using credentials from your Firebase project. If your app doesn't already use FCM:
-
Create a Firebase project at console.firebase.google.com and add your Android app (use your app's
applicationIdas the package name). -
Download the generated
google-services.jsonand drop it into your app module atapp/google-services.json. It must be supplied per app. -
Apply the Google Services Gradle plugin in your app module, and add the classpath/plugin to your project-level build per the Firebase docs:
// app/build.gradle.kts plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("com.google.gms.google-services") // <-- add this } -
In the ReachBell dashboard, add your FCM credentials (the service-account JSON for the HTTP v1 API) so ReachBell can send to the tokens this SDK registers.
The INTERNET and POST_NOTIFICATIONS permissions are declared in the library manifest and merged into your app automatically. The SDK declares POST_NOTIFICATIONS, but you must request it at runtime on Android 13+ (API 33) before notifications are shown:
val requestPermission = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted ->
if (granted) {
lifecycleScope.launch {
runCatching { ReachBell.register(externalId = currentUserId) }
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermission.launch(Manifest.permission.POST_NOTIFICATIONS)
} else {
// Pre-13: no runtime prompt needed.
lifecycleScope.launch { runCatching { ReachBell.register(externalId = currentUserId) } }
}FCM can rotate the device token at any time. Forward it so ReachBell stays current by creating (or extending) a FirebaseMessagingService and wiring onNewToken:
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.reachbell.ReachBell
class MyMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
ReachBell.onNewToken(token) // fire-and-forget re-registration
}
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
// Handle data-message payloads here and post your own Notification
// if you send data messages. Notification messages are rendered by
// the system automatically when the app is backgrounded.
}
}Register the service in your manifest:
<service
android:name=".MyMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>onNewToken can fire in a fresh process (before any Activity runs). ReachBell.onNewToken() is a safe no-op if init() hasn't run yet, and the new token is picked up on the next register().
Initialize
Initialize the SDK once, early — Application.onCreate() is the recommended place, which ensures it's ready for most callbacks (including onNewToken):
import android.app.Application
import com.reachbell.ReachBell
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
ReachBell.init(this, "rb_live_yourkey")
// Optional custom base URL:
// ReachBell.init(this, "rb_live_yourkey", "https://api.reachbell.com")
}
}apiUrl defaults to https://api.reachbell.com. Make sure your Application is registered in your manifest:
<application android:name=".MyApp" ...>Register for push
All network methods are suspend functions — call them from a coroutine. register() fetches the FCM token and calls POST /subscribers { token, tokenType:"fcm", platform:"android", externalId? }, then persists and returns the subscriber token. Call it once the user has granted the notification permission:
import androidx.lifecycle.lifecycleScope
import com.reachbell.ReachBell
import com.reachbell.ReachBellException
import kotlinx.coroutines.launch
lifecycleScope.launch {
try {
ReachBell.register() // FCM token + POST /subscribers
// or register and link in one call:
// ReachBell.register(externalId = "user_42")
} catch (e: ReachBellException) {
Log.w("ReachBell", "push setup failed: ${e.code}", e)
}
}ReachBell.getSubscriberToken() returns the stored subscriber token, or null before a successful register(). ReachBell.reset() forgets the stored token (e.g. on logout); it does not unsubscribe from FCM.
Identify
Link the device to your own user id with identify(), which calls POST /subscribers/identify { token, externalId }:
lifecycleScope.launch {
ReachBell.identify("user_42") // POST /subscribers/identify
}This is the id the Node server SDK uses to target the device by externalId. Call identify() only after a successful register().
Tag
Attach segmentation tags with tag(), which calls POST /subscribers/tag { token, tags }:
lifecycleScope.launch {
ReachBell.tag(listOf("pro", "weekly_digest")) // POST /subscribers/tag
}Like identify(), tag() requires a successful register() first.
Errors
Network methods throw ReachBellException with a stable, machine-readable code (ReachBellException.Code.*) and, for server errors, a statusCode:
code | Meaning |
|---|---|
not_initialized | init() was never called. |
no_subscription | identify() / tag() called before a successful register(). |
fcm_token_unavailable | Firebase couldn't return an FCM token (missing google-services.json, no Play Services, etc.). |
network_error | Transport failure before a response (I/O, DNS, timeout). |
server_error | Non-2xx response; see statusCode. |
try {
ReachBell.register()
} catch (e: ReachBellException) {
when (e.code) {
ReachBellException.Code.FCM_TOKEN_UNAVAILABLE -> /* check Firebase setup */ Unit
ReachBellException.Code.NETWORK_ERROR -> /* retry later */ Unit
else -> Log.w("ReachBell", e)
}
}