Skip to main content
The Sendrealm Android SDK connects your Android app to Sendrealm mobile push. It registers each device, sends the Firebase Cloud Messaging token to Sendrealm, displays incoming notifications, opens deep links, and tracks events such as delivery, open, click, opt-in, opt-out, and custom app events. This page is written for native Android apps using Kotlin or Java. If your app is built with React Native, start with React Native Bare SDK or React Native Expo SDK.

How Android Push Works

Android push delivery has three systems involved:
  1. Your app installs the Sendrealm Android SDK.
  2. Firebase Cloud Messaging gives the app a device token.
  3. Sendrealm stores that token and uses Firebase Cloud Messaging to deliver notifications later.
The SDK handles the device-side work. The Sendrealm dashboard handles provider credentials and campaign configuration. Your app should initialize the SDK, request notification permission at the right time, and link the device to the current user when the user signs in.
The device token is not a user ID. A token identifies one app install on one device. Use login to connect that install to the signed-in user or contact.

Setup Order

Follow this order for the least confusing setup:
  1. Create or select your Sendrealm app in the dashboard.
  2. Configure Android Firebase credentials in Sendrealm.
  3. Install the Android SDK in your app.
  4. Initialize the SDK once during app startup.
  5. Request notification permission after your app explains the value.
  6. Link the device with login after user sign-in.
  7. Send a test notification from Sendrealm.
If a test push fails, diagnostics are much easier to read after the SDK has been initialized and the app has asked for permission.

Requirements

  • Android API 27 or newer
  • Kotlin or Java Android app
  • Google Play services on the test device or emulator
  • A Sendrealm app ID from the dashboard
  • Firebase Cloud Messaging configured for the same Android package name
  • google-services.json added to your Android app
  • Firebase service account JSON uploaded to the Sendrealm dashboard
Android delivery currently uses Firebase Cloud Messaging. The test device or emulator must have Google Play services. Devices without Google services, including many Huawei-only devices, are not supported yet.

Firebase Files You Need

Android setup uses two Firebase JSON files. They are different files and they go in different places.
FileWhere it goesWhy it is needed
google-services.jsonYour Android app, usually app/google-services.jsonGives the app its Firebase Android app configuration.
Firebase service account private key JSONSendrealm dashboardLets Sendrealm send push from its servers through FCM.
Do not upload google-services.json as the Sendrealm provider credential. Sendrealm needs the service account private key JSON for server-side sending. See Mobile Push Credentials for the full Firebase and APNs walkthrough.

Generate google-services.json

Create or download google-services.json from Firebase:
  1. Open the Firebase console.
  2. Select the Firebase project for your Android app.
  3. If you only have a Google Cloud project, choose Add Firebase to Google Cloud project in the Firebase console, select the existing Google Cloud project, and complete the Firebase setup.
  4. In the Firebase project overview, click the Android icon or Add app.
  5. Enter the exact Android package name from your app, usually the applicationId in your app-level Gradle file.
  6. Click Register app.
  7. Click Download google-services.json.
  8. Move the file into your Android app module root:
app/google-services.json
The package name is case-sensitive. If Firebase is registered with com.example.app but your app builds as com.example.App, token registration and delivery can fail in confusing ways. Make sure the file name is exactly google-services.json. Browsers sometimes save repeated downloads as google-services (1).json; rename it before adding it to the app.

Configure The Google Services Gradle Plugin

The Firebase Android config file is read by the Google Services Gradle plugin. In a native Android app, confirm your Gradle setup includes it. In the root Gradle plugins block:
plugins {
    id("com.google.gms.google-services") version "4.5.0" apply false
}
In the app module Gradle plugins block:
plugins {
    id("com.android.application")
    id("com.google.gms.google-services")
}
If your project already applies the Google Services plugin because it uses Firebase, you do not need to add it again.

Install

Add the SDK dependency to your app module:
dependencies {
    implementation("com.sendrealm:sendrealm-android:<version>")
}
For local SDK development from this repository, include the sendrealm-android Gradle module and depend on the project:
dependencies {
    implementation(project(":sendrealm-android"))
}
The SDK manifest contributes the Android pieces it needs:
  • android.permission.INTERNET
  • android.permission.POST_NOTIFICATIONS
  • A Firebase messaging service
  • A notification action receiver
You still decide when to ask the user for notification permission.

Initialize

Initialize once from your launcher activity or application startup flow. Initialization should happen before you call methods such as login, addTags, trackEvent, optIn, or optOut.
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import com.sendrealm.sdk.Sendrealm
import com.sendrealm.sdk.SendrealmConfig

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val config = SendrealmConfig()
            .setAutoRequestPermission(false)

        Sendrealm.initialize(
            context = this,
            appId = "YOUR_SENDREALM_APP_ID",
            config = config
        ) { token ->
            if (token != null) {
                Log.d("Push", "Registered FCM token: $token")
            } else {
                Log.w("Push", "Sendrealm initialized, but token registration failed")
            }
        }
    }
}
During initialization, the SDK:
  • Stores your Sendrealm app ID.
  • Creates or restores the local Sendrealm device ID.
  • Calls the Sendrealm SDK API initialization endpoint.
  • Receives Firebase provider configuration from Sendrealm.
  • Initializes Firebase when the host app has not already done so.
  • Gets the Firebase Cloud Messaging token.
  • Registers the token with Sendrealm.
  • Starts lifecycle tracking for foreground and background behavior.

Configuration Options

Use SendrealmConfig to customize initialization:
  • setExternalUserId("user-123"): links the device to a user during initialization.
  • setUserEmail("user@example.com"): links the device to an email during initialization.
  • setPlatform("android"): platform value sent to Sendrealm. Android apps should use android.
  • setAutoRequestPermission(false): controls whether initialization immediately requests notification permission.
Most apps should set autoRequestPermission to false. Asking immediately on first launch often performs worse because users do not yet understand what they will receive.

Notification Permission

Ask for permission after your app explains why notifications are useful:
Sendrealm.requestPermission(this)
Check permission state:
val allowed = Sendrealm.hasNotificationPermission(this)
Android behavior depends on OS version:
Android versionWhat happens
Android 13 / API 33 and newerThe user must grant the runtime POST_NOTIFICATIONS permission.
Android 12 / API 32 and olderThere is no runtime notification prompt. Notifications can still be disabled in system settings.
A good product flow is:
  1. Initialize Sendrealm.
  2. Show an in-app explanation.
  3. Call Sendrealm.requestPermission(activity).
  4. Check Sendrealm.hasNotificationPermission(context).
  5. If disabled, guide the user to Android notification settings.
When a notification opens the app, forward the intent to Sendrealm:
override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    Sendrealm.handleNotificationOpen(intent)
}
Sendrealm tracks open when a user taps a notification. If the payload includes a launch URL, Sendrealm also tracks click and tries to open the URL. Launch URLs can be:
  • App deep links, such as myapp://orders/123
  • Android App Links, such as https://example.com/orders/123
  • External URLs, such as https://example.com
If a deep link does not open, check the notification payload and your Android intent filters. If an external URL does not open, make sure a browser or matching app exists on the device.

Identity

Call login after the user signs in:
Sendrealm.login("user-123", "user@example.com")
This links the current device to the user in Sendrealm. It is safe to call after initialization and again when the signed-in user changes. Call logout when the user signs out:
Sendrealm.logout()
Logging out clears the local identity and refreshes registration so future push behavior is not tied to the previous user.

Tags

Tags are client-sourced values from the app. Use them for app-observed preferences, local state, and behavior.
Sendrealm.addTags(
    mapOf(
        "plan" to "pro",
        "onboardingComplete" to true
    )
)
Examples of good SDK tags:
  • plan = "pro"
  • theme = "dark"
  • onboardingComplete = true
  • lastViewedCategory = "shoes"
Do not use SDK tags for authoritative account, billing, compliance, security, or verified profile data. Update those properties from your backend instead.
Tags require the device to be linked to a contact. If tag calls fail with ContactNotLinked, call login(userId, email) first.

Custom Events

Use custom events when your app needs to send behavior to Sendrealm for segmentation, analytics, or automation triggers.
Sendrealm.trackEvent(
    "checkout_started",
    mapOf(
        "product_id" to "sku_123",
        "price" to 29
    )
)
Use stable lowercase names such as app_opened, checkout_started, or order_viewed. Keep event properties JSON-compatible and avoid sending sensitive data that your team does not want stored in marketing systems.

Notification Channels

Android 8 and newer require notification channels. A channel controls important display behavior such as sound, importance, vibration, and whether notifications appear prominently. The important Android rule is that channel behavior sticks. Once a device creates a channel, Android may keep the original sound and importance even if your dashboard later changes the channel configuration. If you need a materially different sound or importance level, create a new channel ID. The SDK syncs dashboard-created Android channels:
  • During initialization
  • After token registration or refresh
  • Periodically when the app resumes
Use clear channel IDs, for example:
  • orders
  • promotions
  • account_alerts
  • chat_messages

Delivery Timing And OS Behavior

Android notification delivery is best effort and can depend on the device, Android version, app state, battery mode, user settings, notification channel settings, and Firebase Cloud Messaging priority. Normal-priority FCM messages are delivered immediately when the device is awake, but Android may delay them while the device is in Doze mode to conserve battery. High-priority messages are intended for urgent, user-visible notifications and can wake a sleeping device for limited processing. High priority is not a magic guarantee, though. It should be reserved for messages that actually display a notification or require immediate user attention. You may see delayed or missing notifications when:
  • The device is in Doze or App Standby.
  • The app is restricted by battery optimization or OEM background limits.
  • The user disabled notifications for the app or channel.
  • Android channel importance is too low.
  • The device is offline or has poor network connectivity.
  • Too many messages are pending for the device.
  • A high-priority message does not result in a visible notification and FCM lowers future priority behavior.
  • The app spends too long processing the message before displaying it.
For time-sensitive notifications, use high priority and make the notification user-visible. For general background sync or non-urgent updates, use normal priority and expect delivery to happen later when Android allows it.

Testing Checklist

Before sending production traffic, confirm:
  • The app initializes without SDK errors.
  • Diagnostics show a Sendrealm device ID.
  • Diagnostics show a registration token is present.
  • Notification permission is granted on Android 13 or newer.
  • The Android package name in Firebase matches your app applicationId.
  • The Firebase service account JSON is uploaded in Sendrealm.
  • A test notification arrives while the app is foregrounded.
  • A test notification arrives while the app is backgrounded.
  • Time-sensitive notifications use an appropriate priority.
  • Non-urgent notifications still make sense if they arrive later.
  • Tapping the notification opens the expected screen or URL.

Diagnostics

Use diagnostics when push delivery is not working:
val diagnostics = Sendrealm.getDiagnostics(this)
Log.d("Sendrealm", diagnostics.toString())
Look for:
  • deviceId: should be present after initialization.
  • registrationTokenPresent: should be true after FCM token registration.
  • permissionStatus: should be authorized when notifications are allowed.
  • subscribed: should be true unless the user opted out.
  • lastSdkError: should be empty or explain the latest failure.

Troubleshooting

SymptomWhat to check
token is nullThe emulator or device must have Google Play services and internet access.
Notifications arrive but do not displayCheck notification permission, Android channel settings, and custom icon resources.
Notifications are delayedCheck Doze, App Standby, battery optimization, message priority, and whether the message is user-visible.
Some notifications seem missingCheck disabled channels, stale tokens, too many pending messages, offline devices, and FCM delivery diagnostics.
Notification sound does not changeAndroid may be keeping the original channel behavior. Use a new channel ID.
Deep link does not openVerify the launch URL and Android intent filters.
Tags fail with ContactNotLinkedCall login(userId, email) before setting user tags.