ReachBellDocs

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:

  1. Create a Firebase project at console.firebase.google.com and add your Android app (use your app's applicationId as the package name).

  2. Download the generated google-services.json and drop it into your app module at app/google-services.json. It must be supplied per app.

  3. 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
    }
  4. 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:

codeMeaning
not_initializedinit() was never called.
no_subscriptionidentify() / tag() called before a successful register().
fcm_token_unavailableFirebase couldn't return an FCM token (missing google-services.json, no Play Services, etc.).
network_errorTransport failure before a response (I/O, DNS, timeout).
server_errorNon-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)
    }
}