Skip to main content

What you’ll build

In this quickstart you will:
  • Install the Desmo Android SDK via JitPack.
  • Initialize the SDK with your publishable key.
  • Start and stop a delivery session from your Android app.
This page assumes you already have a Desmo account and at least one publishable key that starts with pk_....
If you don’t have a key yet, contact your Desmo representative to have one issued for your project.

Requirements

  • Android 7.0 (API 24) or later
  • Android Gradle Plugin compatible with Kotlin 1.9+
  • Your app is written in Kotlin (the SDK is a Kotlin library)

App permissions

To let Desmo record sessions correctly, your app should request location permissions so sessions can be tied to where the delivery happened. Add these to your AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
On Android 6.0+ you must also request these at runtime. Later on this page we’ll show how to ask for the permissions using the helpers exposed by the SDK.

1. Install the SDK (JitPack)

The Android SDK is distributed via JitPack from the GitHub repo kubocreate/desmo-android-sdk.

1.1 Add the JitPack repository

In your app project (not the SDK repo), open the root settings.gradle.kts and make sure the dependencyResolutionManagement block includes JitPack:
// settings.gradle.kts (Kotlin DSL)
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven(url = "https://jitpack.io")
    }
}
If you use Groovy and have settings.gradle:
// settings.gradle (Groovy)
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}
If your project still uses a top-level build.gradle with an allprojects { repositories { ... } } block instead of dependencyResolutionManagement, add the jitpack.io maven entry there:
// Top-level build.gradle (older projects)
allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}

1.2 Add the dependency

In your app module build.gradle (usually app/build.gradle):
  1. Remove any old module dependency, for example:
    implementation project(':desmo-android-sdk')
    
  2. Add the JitPack dependency:
    dependencies {
        implementation 'com.github.kubocreate:desmo-android-sdk:v0.1.3'
    }
    
If you use Kotlin DSL for your app module, the equivalent is:
dependencies {
    implementation("com.github.kubocreate:desmo-android-sdk:v0.1.3")
}
Here v0.1.2 is the Git tag for the SDK release on GitHub. When a new version is tagged, update this value to match. If you previously copied any Desmo code directly into your project, or used old Maven Central coordinates or local module references, remove those and keep only the JitPack dependency to avoid duplicate classes.

2. Initialize the SDK

Call Desmo.setup once at app startup, usually in your custom Application class.
import android.app.Application
import io.getdesmo.tracesdk.Desmo
import io.getdesmo.tracesdk.config.DesmoEnvironment

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

        Desmo.setup(
            context = this,
            apiKey = "pk_sandbox_XXXXXXXXXXXXXXXX", // your Desmo publishable key
            environment = DesmoEnvironment.SANDBOX  // use LIVE in production
        )
    }
}
Then register your Application class in AndroidManifest.xml:
<application
    android:name=".MyApp"
    ...>
    <!-- activities etc -->
</application>
  • apiKey: your publishable Desmo API key (starts with pk_).
  • environment:
    • DesmoEnvironment.SANDBOX – Desmo sandbox environment.
    • DesmoEnvironment.LIVE – Desmo production environment.
If Desmo.setup fails (for example, if the key does not start with pk_), the SDK will log an error and Desmo.client will remain null.

Without a Context (no telemetry)

There is also a setup(apiKey, environment) overload that does not take a Context. This is useful in non-Android environments, but it disables on-device telemetry. For typical courier apps you should prefer the setup(context, apiKey, environment) version so telemetry is enabled.

3. Request permissions at runtime

The SDK exposes helpers so you know which permissions are required and whether they are granted:
  • Desmo.getRequiredPermissions() : Array<String>
  • Desmo.hasRequiredPermissions(context) : Boolean
  • Desmo.getMissingPermissions(context) : List<String>
Example with an Activity:
import android.Manifest
import android.content.pm.PackageManager
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import io.getdesmo.tracesdk.Desmo

class DeliveryActivity : AppCompatActivity() {

    private val requestPermissionsLauncher =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { _ ->
            // You can re-check Desmo.hasRequiredPermissions(this) here if needed
        }

    private fun ensureDesmoPermissions() {
        if (!Desmo.hasRequiredPermissions(this)) {
            val missing = Desmo.getMissingPermissions(this).toTypedArray()
            requestPermissionsLauncher.launch(missing)
        }
    }
}
Call ensureDesmoPermissions() before you start a session so location is available.

4. Start a delivery session

Call this when you begin recording a delivery (for example, when the driver starts a drop-off). Because the Android SDK uses Kotlin coroutines, these calls are suspend functions. You should call them from a coroutine scope (e.g. lifecycleScope).
import androidx.lifecycle.lifecycleScope
import io.getdesmo.tracesdk.Desmo
import kotlinx.coroutines.launch

fun startDeliverySession() {
    val client = Desmo.client
    if (client == null) {
        println("Desmo SDK is not configured")
        return
    }

    lifecycleScope.launch {
        try {
            val session = client.startSessionWithDeviceInfo(
                context = this@DeliveryActivity,
                deliveryId = "DELIVERY_123",
                address = "123 Main Street, City"
            )
            println("Started session: ${session.sessionId}")
        } catch (t: Throwable) {
            println("Failed to start session: $t")
        }
    }
}
Behind the scenes, the SDK:
  • Calls Desmo’s backend to create a session.
  • Starts collecting telemetry on-device (when initialized with a Context).
  • Begins batching telemetry to Desmo while the session is recording.

5. Stop a delivery session

Call this when the delivery is complete:
fun stopDeliverySession() {
    val client = Desmo.client
    if (client == null) {
        println("Desmo SDK is not configured")
        return
    }

    lifecycleScope.launch {
        try {
            val session = client.stopSession()
            println("Stopped session: ${session.sessionId}")
        } catch (t: Throwable) {
            println("Failed to stop session: $t")
        }
    }
}
When you stop the session, the SDK:
  • Flushes any remaining telemetry.
  • Notifies the backend that the session is complete.
  • Lets Desmo’s workers start processing PoD intelligence for that session.

Next steps

From here: