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:
- Your app installs the Sendrealm Android SDK.
- Firebase Cloud Messaging gives the app a device token.
- 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:
- Create or select your Sendrealm app in the dashboard.
- Configure Android Firebase credentials in Sendrealm.
- Install the Android SDK in your app.
- Initialize the SDK once during app startup.
- Request notification permission after your app explains the value.
- Link the device with
login after user sign-in.
- 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.
| File | Where it goes | Why it is needed |
|---|
google-services.json | Your Android app, usually app/google-services.json | Gives the app its Firebase Android app configuration. |
| Firebase service account private key JSON | Sendrealm dashboard | Lets 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:
- Open the Firebase console.
- Select the Firebase project for your Android app.
- 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.
- In the Firebase project overview, click the Android icon or Add app.
- Enter the exact Android package name from your app, usually the
applicationId in your app-level Gradle file.
- Click Register app.
- Click Download google-services.json.
- Move the file into your Android app module root:
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.
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 version | What happens |
|---|
| Android 13 / API 33 and newer | The user must grant the runtime POST_NOTIFICATIONS permission. |
| Android 12 / API 32 and older | There is no runtime notification prompt. Notifications can still be disabled in system settings. |
A good product flow is:
- Initialize Sendrealm.
- Show an in-app explanation.
- Call
Sendrealm.requestPermission(activity).
- Check
Sendrealm.hasNotificationPermission(context).
- If disabled, guide the user to Android notification settings.
Notification Opens And Deep Links
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:
Logging out clears the local identity and refreshes registration so future push behavior is not tied to the previous user.
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
| Symptom | What to check |
|---|
token is null | The emulator or device must have Google Play services and internet access. |
| Notifications arrive but do not display | Check notification permission, Android channel settings, and custom icon resources. |
| Notifications are delayed | Check Doze, App Standby, battery optimization, message priority, and whether the message is user-visible. |
| Some notifications seem missing | Check disabled channels, stale tokens, too many pending messages, offline devices, and FCM delivery diagnostics. |
| Notification sound does not change | Android may be keeping the original channel behavior. Use a new channel ID. |
| Deep link does not open | Verify the launch URL and Android intent filters. |
Tags fail with ContactNotLinked | Call login(userId, email) before setting user tags. |
Related Pages