Android Integration
Add AlgorithmX to your Android app step by step: install the SDK, start it, identify customers, send events, connect Firebase push notifications, and open the right screen from campaigns.
This guide adds the AlgorithmX SDK to your Android app in 8 steps. You keep your app's login, Firebase setup, and navigation. You only add a few lines in places your app already has.
In the examples, names such as appNavigator are your own code, not part of the SDK. Every SDK call goes through AlgorithmX:
import algorithmx.engage.core.AlgorithmX
Before you start
Check that you have these:
- An Android app with minSdk 24 or higher, compileSdk 34 or higher, and Java 17.
- Firebase Cloud Messaging already set up in your app. If you do not have it yet, follow Firebase's Android guide first.
- The API base URL from AlgorithmX, for example
https://api.example.com. - The list of customer ID, events, deep links, and custom actions you agreed on with AlgorithmX. See the overview.
Send these to your AlgorithmX contact, so AlgorithmX can send notifications to your app:
| What | Example | Where to find it |
|---|---|---|
| Application ID | com.example.shop | applicationId in app/build.gradle. |
| Firebase project | shop-prod-1234 | Firebase console, Project settings. |
| Permission to send messages | A service account key that can send Firebase messages | Google Cloud console of your Firebase project. Send it through a secure channel. Never put it in the app. |
The steps
| Step | What you do | Where |
|---|---|---|
| 1 | Install the SDK | app/build.gradle |
| 2 | Start the SDK | Your Application class |
| 3 | Tell AlgorithmX who the customer is | Login, app start, logout |
| 4 | Send events | Where actions happen, such as checkout |
| 5 | Connect push notifications | Your FirebaseMessagingService |
| 6 | Open the right screen | Your navigation code |
| 7 | Check in-app campaigns | No code |
| 8 | Test | A real phone |
Step 1: Install the SDK
Add the SDK to the dependencies block of your app module:
// app/build.gradle.kts
dependencies {
implementation("cloud.algorithmx:android-sdk:1.0.0")
}
If your project uses Groovy instead:
// app/build.gradle
dependencies {
implementation 'cloud.algorithmx:android-sdk:1.0.0'
}
The SDK comes from Maven Central. New Android projects already include it. If yours does not, add mavenCentral() in settings.gradle:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
Check: Gradle sync finishes without errors.
Good to know:
- The SDK brings everything it needs (OkHttp, Gson, coroutines, AndroidX). It does not include Firebase; your app keeps its own.
- Release builds with R8/ProGuard need no extra rules.
- To update later, change the version number. See the changelog.
Step 2: Start the SDK
Add these lines to onCreate of your Application class. Keep your existing code.
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Keep your existing startup code.
AlgorithmX.initialize(this, "https://api.example.com")
AlgorithmX.setLoggingEnabled(BuildConfig.DEBUG)
AlgorithmX.setSmallIcon(R.drawable.ic_stat_notification) // Your notification icon.
// Your handlers from step 6:
AlgorithmX.setDeepLinkHandler(deepLinkHandler)
AlgorithmX.setNotificationClickListener(notificationClickListener)
AlgorithmX.setActionButtonHandler(actionButtonHandler)
}
}
Why in Application and not in an Activity? Firebase can wake your app in the background to deliver a message. No screen opens then, but Application.onCreate still runs. SDK calls made before initialize are ignored.
- Notification icon: without
setSmallIcon, AlgorithmX notifications show a plain Android icon. - Handlers: the SDK keeps them while the app runs. Let them call your navigation code; do not keep an Activity inside them.
Check: run a debug build. Logcat shows lines with the tag AlgorithmX.
Step 3: Tell AlgorithmX who the customer is
Until you do this, the SDK uses an anonymous ID for the phone.
At login, and when your app starts with a customer already logged in, call identifyUser with your customer ID:
AlgorithmX.identifyUser(
"customer_123",
mapOf("first_name" to "Amina", "language" to "ar", "loyalty_tier" to "gold")
)
Do both places. The second one covers customers who are already logged in when they update to your first app version with AlgorithmX.
At logout, clear waiting campaigns first, so the next person does not see them:
AlgorithmX.clearWebViewQueue()
AlgorithmX.resetIdentity()
When one account replaces another without a logout:
AlgorithmX.clearWebViewQueue()
AlgorithmX.identifyUser("customer_456", mapOf("language" to "en"))
Good to know:
- The SDK remembers the customer after the app restarts. It also links what the customer did before logging in.
resetIdentity()does not close a campaign that is already on screen or remove notifications already shown.- This does not replace your own login. It only tells AlgorithmX who is using the app.
Check: after login, the customer appears in AlgorithmX with the ID you sent.
Step 4: Send events
Send an event right after an action succeeds, for example after an order is confirmed. Put it next to your existing analytics calls.
AlgorithmX.trackEvent("product_view", mapOf("product_id" to "SKU-123"))
AlgorithmX.trackEvent("add_to_cart", mapOf("product_id" to "SKU-123", "quantity" to 2))
AlgorithmX.trackEvent("purchase", mapOf(
"order_id" to "ORDER-1001",
"total" to 149.90,
"currency" to "SAR",
"items" to listOf(mapOf("product_id" to "SKU-123", "quantity" to 2))
))
Rules for events:
- Values: use text, numbers, true/false, and lists or maps of these.
- Names: use simple names with letters and underscores, such as
add_to_cart. - Offline: an event sent without internet is lost. It is not sent again later. Keep your own backend as the record of orders and payments.
- Past data: only new events are sent. To bring in older data, ask your AlgorithmX contact about a data import.
Check: the event appears for the customer in AlgorithmX.
Step 5: Connect push notifications
You keep your Firebase project and your messaging service. You add three things to them.
5a. Send the push token on every app start
In Application.onCreate, after step 2:
import com.google.firebase.messaging.FirebaseMessaging
FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
AlgorithmX.registerDeviceToken(token)
// Keep your own token registration here too.
}
Why every start? Customers who update your app already have a token. AlgorithmX has not seen it yet, and Firebase does not send a new one just because you added the SDK. If your code skips sending an unchanged token, do not skip this call.
5b. Pass AlgorithmX messages to the SDK
In your existing FirebaseMessagingService, add the AlgorithmX check at the top of onMessageReceived, and send new tokens in onNewToken. Do not create a second service.
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
if (AlgorithmX.isAlgorithmXPush(message.data)) {
AlgorithmX.handleFcmMessage(
applicationContext,
message.data,
message.notification?.title,
message.notification?.body
)
return // Stop here. The SDK shows this notification.
}
// Your existing code for other messages stays here.
}
override fun onNewToken(token: String) {
super.onNewToken(token)
AlgorithmX.registerDeviceToken(token)
// Keep your own token registration here too.
}
Important: the check must come before your own notification code, and it must return. The SDK builds AlgorithmX notifications itself, with image and buttons. If your code handles them too, customers see the notification twice.
Good to know:
- The SDK uses the notification channel
algorithmx_notificationsand your app's notification permission. Keep your own permission prompt; the SDK never asks for permission. - AlgorithmX notification IDs start at 10000. If your app uses IDs in that range, tell your AlgorithmX contact.
5c. Forward new intents (recommended)
The SDK handles taps on its own notifications by itself. As a safety net, add one line to onNewIntent of your main Activity:
override fun onNewIntent(intent: android.content.Intent) {
super.onNewIntent(intent)
setIntent(intent)
AlgorithmX.handleNewIntent(this, intent)
// Keep your existing code here.
}
Check: ask your campaign team to send a test notification. It appears once, with its image and buttons.
Step 6: Open the right screen when a customer taps
A campaign can do one of four things when the customer taps it. Two of them need your code:
| The campaign says | What happens | Your code |
|---|---|---|
| Open a screen (deep link) | The SDK gives the link to your handler. | Step 6a |
| Custom action | The SDK gives the action name and its details to your handler. | Step 6b |
| Open a web page | The SDK opens it in the browser. | None |
| Open an in-app campaign | The SDK shows it over your app. | None |
6a. Deep links
Pass the link to the router your app already uses:
import algorithmx.engage.interfaces.DeepLinkHandler
val deepLinkHandler = object : DeepLinkHandler {
override fun onDeepLinkReceived(uri: android.net.Uri): Boolean {
return appNavigator.openDeepLink(uri)
}
}
- Return
trueif your app accepts the link,falseif not. - The SDK never opens the link by itself. If you set no handler, nothing happens.
- This can run before any screen is open, for example when a tap starts the app. Start screens with
FLAG_ACTIVITY_NEW_TASK, or let your router wait until the app is ready. - You do not need new links or screens. Give your campaign team the links your app already supports, for example
myapp://open/product?id=SKU-123.
6b. Custom actions
Map each action name you agreed on to a screen:
import algorithmx.engage.interfaces.NotificationClickListener
val notificationClickListener = object : NotificationClickListener {
// Return false so the SDK runs the campaign's action.
override fun onNotificationClick(data: Map<String, Any>): Boolean = false
override fun onCustomAction(action: String?, data: Map<String, Any>): Boolean {
val details = data["parsedActionData"] as? Map<*, *> ?: return false
return when (action) {
"view_product" -> {
val productId = (details["product_id"] as? String)
?.takeIf { it.isNotBlank() } ?: return false
appNavigator.openProduct(productId)
}
"view_cart" -> appNavigator.openCart()
else -> false
}
}
}
onNotificationClickruns first on every tap. Returnfalse, so the SDK goes on to run the campaign's action.- The action's details are in
parsedActionData. A number arrives as a number, soas? Stringdoes not work for it. Agree on the types with your campaign team. - An action name your app does not know does nothing. Only offer actions that your released app supports.
6c. Notification buttons
A notification can have up to three buttons. Match on the button's action text, not on its title, because the title can be translated:
import algorithmx.engage.interfaces.ActionButtonHandler
val actionButtonHandler = object : ActionButtonHandler {
override fun onActionButtonClicked(
buttonId: String,
actionText: String,
title: String,
notificationData: Map<String, Any>
): Boolean = when (actionText) {
"view_cart" -> appNavigator.openCart()
"dismiss" -> true // Handled: do nothing more.
else -> false
}
}
Every button opens the app. Return true when you handled the button. If you return false, the SDK runs the notification's main action instead.
Register all three handlers in step 2. Keep your normal login and permission checks before sensitive screens: a campaign only suggests where to go.
Check: send a test notification for each link, action, and button your app supports. The right screen opens once.
Step 7: Check in-app campaigns
In-app campaigns need no code. After steps 2 to 5:
- AlgorithmX sends a hidden message to the phone, and your messaging service passes it to the SDK.
- The SDK saves the campaign. No notification appears.
- The next time the customer opens the app, the SDK shows the campaign over the current screen. It shows at most one per visit. The customer closes it with its close button or Back.
Check these in your app:
- Logout: clear waiting campaigns, as in step 3.
- Your own pop-ups at start: a campaign can appear when the app opens, on top of a dialog your app shows at the same time. Try them together.
- Notification permission is not needed. In-app campaigns arrive even when notifications are turned off.
- Force stop: if the customer force-stops the app in Android settings, messages arrive only after the app is opened again.
To see impressions, clicks, and closes while testing, set AlgorithmX.setCampaignInteractionListener(...).
Step 8: Test before you release
Use a real phone and a test customer. Test a debug build and your release build.
- Update while logged in: install your current store version, log in, then update to the new build. The customer is recognized without logging in again.
- Login, restart, logout, second account: events use the right customer each time. No campaign from the first account appears for the second.
- Your existing notifications still work exactly as before.
- AlgorithmX notification with the app open, in the background, and closed: it appears once, and a tap opens the right screen once.
- Each deep link, custom action, and button opens the right screen.
- In-app campaign: it appears the next time the app opens and closes with its close button or Back.
- Notifications turned off: in-app campaigns still arrive.
- Release build: notifications, taps, and campaign buttons still work.
- Events appear for the customer in AlgorithmX.
While testing, Logcat shows each SDK request under the AlgorithmX tag.
Quick reference
| Call on AlgorithmX | What it does |
|---|---|
initialize(application, apiBaseUrl) | Starts the SDK. Call it in Application.onCreate. |
setLoggingEnabled(enabled) | Shows SDK requests in Logcat. Off by default. |
setSmallIcon(resId) | Sets the icon of AlgorithmX notifications. |
identifyUser(userId, attributes) | Sets the customer. Call at login and app start. |
resetIdentity() | Goes back to an anonymous customer. Call at logout. |
trackEvent(name, properties) | Sends an event. |
registerDeviceToken(token) | Sends the push token. Call on every app start and in onNewToken. |
isAlgorithmXPush(data) | Tells you if a Firebase message is from AlgorithmX. |
handleFcmMessage(context, data, title, body) | Gives an AlgorithmX message to the SDK. |
handleNewIntent(activity, intent) | Gives a new intent to the SDK. |
setDeepLinkHandler, setNotificationClickListener, setActionButtonHandler, setCampaignInteractionListener | Register your handlers. Each has a matching remove call. |
clearWebViewQueue() | Removes waiting in-app campaigns. Call at logout. |
getDeviceFingerprint(), getQueueSize() | Show the current customer ID and waiting campaigns, for testing. |
Something not working?
| Problem | What to check |
|---|---|
Gradle cannot find cloud.algorithmx:android-sdk | mavenCentral() is in the repositories in settings.gradle, and the version number is right. |
| No events in AlgorithmX | initialize runs in Application.onCreate with the right HTTPS URL, and the phone is online. |
| No AlgorithmX notifications | The token is sent on every app start (5a). AlgorithmX has permission to send through your Firebase project. Your service passes AlgorithmX messages to the SDK (5b). Notifications are allowed for the app. |
| Notifications appear twice, or not at all | The AlgorithmX check is at the top of onMessageReceived and returns after passing the message on. |
| Tapping a notification does nothing | Your handlers are registered in Application.onCreate and really open a screen. |
| A custom action does nothing | onNotificationClick returns false, and the action name matches exactly. |
| A button opens the wrong screen | Your button handler returned false, so the main action ran. Check the action text. |
| In-app campaign never appears | Your service passes the message to the SDK, the app was not force-stopped, and you opened the app again after the campaign was sent. |
| A previous account's campaign appears | Call clearWebViewQueue() at logout and when switching accounts. |
Next steps
Create your first campaigns with In-App Push Campaigns and In-App View Campaigns. Go back to the overview for other platforms.
