Skip to main content

Android

Ensure you have completed the Prerequisites section before continuing.

Installation

note

The SDK currently targets minSdk 26 and compileSdk/targetSdk 34.

  1. Add Maven Central repository to your settings.gradle file:

    settings.gradle
    dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    // ...
    google()
    mavenCentral()
    }
    }
  2. Add dashx-android as a dependency in your module-level build.gradle file:

    app/build.gradle
    dependencies {
    // ...
    implementation 'com.dashx:dashx-android:1.1.5'
    }
  3. Ensure you're using Java 17 or higher (Java 17 is the minimum).

    app/build.gradle
    android {
    compileOptions {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
    }
    }
tip

If you're using Android Studio, you should hit the Sync Now button that pops up after modifying build.gradle.

Configuration

DashX needs to be initialized as early as possible in your application's lifecycle, which is generally in an instance of the Android Application class:

app/src/main/java/.../MyApplication.kt
import android.app.Application
import com.dashx.android.DashX

class MyApplication : Application() {
override fun onCreate() {
super.onCreate()

DashX.configure(
context = this,
publicKey = "...", // required
baseURI = null, // optional (defaults to https://api.dashx.com/graphql)
targetEnvironment = null, // optional
)
}
}

If your product uses multiple environments, a good practice is to:

Optional: activity lifecycle tracking

If you want automatic tracking for app installed/updated/opened and session length, you can enable activity lifecycle tracking:

import com.dashx.android.DashXActivityLifecycleCallbacks

DashXActivityLifecycleCallbacks.enableActivityLifecycleTracking(this)

Optional: automatic screen tracking

To automatically track screen views based on Activity labels:

DashXActivityLifecycleCallbacks.enableScreenTracking(this)

Permissions

By default, the dashx-android SDK automatically requests the following permissions:

<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

If you need to meet certain privacy restrictions (example: if your app targets children), you can easily remove the AD_ID permission declaration in your Android Manifest file:

app/src/main/AndroidManifest.xml
<!-- Ensure that xmlns:tools is declared in your manifest tag -->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="..."
>

<!-- Remove the permission from your final merged manifest -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" />

Publishing

On the Play Store Console, you will need to fill out the Advertising ID form to prevent any warnings during release:

  • Head to the Policy > App Content section in the sidebar.
    App Content
  • Hit Start under the Advertising ID section.
    Advertising ID
  • For the question, "Does your app use advertising ID?", select the answer "Yes".
  • For the question, "Why does your app need to use advertising ID?", select the option "Analytics".

Troubleshooting

As an optional step, you can set the log level for debugging your integration:

import com.dashx.android.DashXLog

// ...

DashXLog.setLogLevel(DashXLog.LogLevel.DEBUG)

By default, the log level is set to ERROR. You can set it to one of: DEBUG (most logs), INFO, ERROR or OFF (no logs).

Crash tracking

To automatically track unhandled exceptions, enable the DashX exception handler:

import com.dashx.android.DashXExceptionHandler

DashXExceptionHandler.enable()

Usage

tip

Most public methods have suspend variants for Kotlin coroutine users (e.g., identifyAsync, trackAsync, fetchRecordAsync, searchRecordsAsync). These throw DashXException on failure instead of using callbacks.

User Management

// Recommended when you have a signed-in user + identity token
DashX.setIdentity(uid = "123", token = "your-identity-token")

// Update only the identity token (useful for token refresh)
DashX.setIdentityToken("new-token")

// Send user attributes
DashX.identify(
hashMapOf(
"uid" to "123",
"email" to "john@example.com",
"first_name" to "John",
"last_name" to "Doe",
),
onSuccess = { /* ... */ },
onError = { error -> /* ... */ }
)

// Clear identity, generate new anonymous ID, and unsubscribe from push
DashX.reset()

Learn more

Analytics

DashX.track("Button Clicked", hashMapOf(
"label" to "Click here",
"placement" to "top"
))

Track screen views:

DashX.screen("HomeActivity", hashMapOf(
"referrer" to "deep_link"
))

Learn more

Messaging

note

Push notifications require your app to be configured for Firebase Cloud Messaging. On Android 13+, you must request the runtime notification permission (POST_NOTIFICATIONS) before notifications can be shown.

info

The SDK automatically tracks notification delivered, opened, and dismissed events via the built-in DashXFirebaseMessagingService. No manual trackMessage() calls are needed unless you use a custom FirebaseMessagingService.

// Subscribe/unsubscribe Push Notifications (FCM)
DashX.subscribe()
DashX.unsubscribe()

// Manage user preferences (requires DashX.setIdentity(uid, ...))
DashX.fetchStoredPreferences(
onSuccess = { prefs ->
// prefs.preferenceData is a JsonObject
},
onError = { err ->
// ...
}
)

// Save preferences
val preferenceData = kotlinx.serialization.json.buildJsonObject {
put("push", true)
put("email", false)
}

DashX.saveStoredPreferences(
preferenceData = preferenceData,
onSuccess = { _ -> /* ... */ },
onError = { _ -> /* ... */ }
)

Learn more

CMS

DashX.fetchRecord(
urn = "email/welcome",
language = "en_US",
preview = true,
onSuccess = { recordJson ->
println(recordJson)
},
onError = { err ->
println(err)
}
)

fetchRecord accepts following optional arguments

NameTypeExample
previewBooleantrue
languageString"en_US"
fieldsList<JsonObject>
includeList<JsonObject>
excludeList<JsonObject>
import kotlinx.serialization.json.buildJsonObject

DashX.searchRecords(
resource = "email",
language = "en_US",
order = listOf(buildJsonObject { put("created_at", "DESC") }),
limit = 10,
preview = true,
onSuccess = { records ->
println(records)
},
onError = { err ->
println(err)
}
)

searchRecords accepts the following optional arguments:

NameTypeExample
filterJsonObjectbuildJsonObject { put("status", "published") }
orderList<JsonObject>listOf(buildJsonObject { put("created_at", "DESC") })
limitInt10
pageInt1
previewBooleantrue
languageString"en_US"
fieldsList<JsonObject>
includeList<JsonObject>
excludeList<JsonObject>

Assets

DashX.uploadAsset(
file = imageFile,
resource = "users",
attribute = "avatar",
onSuccess = { asset ->
println(asset)
},
onError = { err ->
println(err)
}
)
info

The SDK automatically detects the MIME type and polls for upload completion. You can configure polling behaviour with DashX.pollIntervalMs (default: 3000ms) and DashX.maxPollRetries (default: 10).

Error Handling

All callback-based methods receive a DashXError on failure. The error types are:

ErrorRetryableWhen
NotConfiguredNoDashX.configure() was not called
NotIdentifiedNosetIdentity() required but not called
GraphQLErrorNoServer returned a GraphQL error
NetworkErrorYesTimeout, DNS failure, or connectivity issue
AssetErrorNoAsset upload or MIME detection failure

Use error.isRetryable to decide whether to retry:

DashX.track("Event",
onError = { error ->
if (error.isRetryable) {
// retry later
}
}
)
tip

Suspend variants (e.g., trackAsync) throw DashXException instead, which wraps a DashXError. Access it via exception.error.

Offline Event Queue

Failed track() calls are automatically queued and retried with exponential backoff (2 s base, capped at 5 min, up to 10 retries). The queue holds up to 1,000 events, is persisted across app restarts, and flushes automatically after configure().

To manually flush:

DashX.flushEventQueue()

Advanced

Custom FirebaseMessagingService

If your app already has its own FirebaseMessagingService, remove the SDK's service from the merged manifest and forward tokens manually:

app/src/main/AndroidManifest.xml
<service
android:name="com.dashx.android.DashXFirebaseMessagingService"
tools:node="remove" />

Then in your service, forward new tokens to DashX:

override fun onNewToken(token: String) {
super.onNewToken(token)
DashX.subscribe(token)
}

Shutdown

To cancel all in-flight operations and release resources:

DashX.shutdown()
note

You must call DashX.configure() again after shutdown() before using any other SDK methods.