Android

The Roam Android SDK provides continuous location tracking with minimal setup. It works in both foreground and background, optimizing for accuracy and battery efficiency across a wide range of devices.

Prerequisites

Before you begin:

  • Access to the Roam Dashboard

  • A project created with your Android app’s package name

  • Your SDK Key (PUBLISHABLE_KEY) from the dashboard

  • Android Studio 2.0+

  • Target SDK version 21 (Lollipop) or higher

Step 1: Install the SDK

The first step in integrating the Roam SDK is to add the necessary dependencies to your Android project. This involves updating your Gradle files so that your app can locate and include the Roam SDK from our custom Maven repository.

1.1 Update Gradle Settings

In your settings.gradle.kts, make sure you’ve enabled mavenCentral() in the dependencyResolutionManagement block. This ensures that dependencies can be pulled from the Maven Central repository.

settings.gradle.kts
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

Additionally, in your root-level build.gradle.kts, verify that the buildscript block also includes Maven Central:

build.gradle.kts
buildscript {
    repositories {
        mavenCentral()
    }
}

1.2 Add Roam SDK Dependency

Now, open your app-level app/build.gradle.kts file and add the Roam SDK repository and dependency.

app/build.gradle.kts
repositories {
    maven {
        url = uri("https://com-roam-android.s3.amazonaws.com/")
    }
}

Then, add the Roam SDK dependency:

dependencies {
    implementation("com.roam.sdk:roam-android:0.1.40")
    implementation("com.roam.sdk:roam-batch-android:0.1.40")
}

Once these changes are added, sync your Gradle project to download and apply the SDK.

✅ What You Should See After a Successful Setup

Once you sync Gradle:

  • The Gradle sync completes without errors

  • You should see com.roam.sdk classes available in your code editor

  • Auto-complete should work for SDK classes like Roam, RoamReceiver, RoamLocation, etc.

🧪 Test Tip: Try typing Roam. in any Kotlin file — if auto-suggestions appear, the SDK was installed correctly.

Step 2: Initialize the SDK

Once the SDK has been added to your project, the next step is to initialize it. Initialization tells the Roam SDK which project it belongs to and prepares it to start tracking location.

You’ll do this in your application’s Application class — the entry point of your app’s lifecycle.

2.1 Add Application Class

First, open your AndroidManifest.xml and add the following attribute to the <application> tag to specify your custom Application class:

<application
    android:name=".Application"
    ... >
</application>

This tells Android to use your custom Application.kt class when the app starts.

Now, create a new Kotlin file named Application.kt and add the following code:

import android.app.Application
import com.roam.sdk.Roam
import com.roam.roam_batch_connector.RoamBatch

class Application : Application() {
    override fun onCreate() {
        super.onCreate()
        Roam.initialize(this, "YOUR_PUBLISHABLE_KEY")
        RoamBatch.initialize(this)
    }
}

This initializes the SDK with your project context, allowing it to function correctly throughout the app.

✅ What You Should See After a Successful Setup

After running the app with this setup:

  • The app should launch without crashing or throwing initialization errors.

  • There should be no warnings or exceptions related to Roam in Logcat during startup.

  • You can now begin using Roam’s SDK features like starting location tracking.

🧪 Test Tip: Add a quick log inside onCreate() to verify that the class is being called correctly.

Log.d("RoamInit", "Roam SDK initialized")

If you see this message in Logcat, you’re good to go.

Step 3: Handle Permissions

To ensure Roam can track location accurately and reliably, your app must request the necessary foreground and background location permissions, and verify that location services are enabled on the device.

This step guides you through requesting those permissions from the user during runtime.

🔐 Why Permissions Matter

Modern versions of Android require explicit permission from users to access their location. Without these permissions, the SDK will not be able to track location — especially when the app is running in the background.

In your main activity (typically MainActivity.kt), add the following method:

private fun checkPermissions() {
    if (!Roam.checkLocationPermission()) {
        Roam.requestLocationPermission(this)
    } else if (!Roam.checkBackgroundLocationPermission()) {
        Roam.requestBackgroundLocationPermission(this)
    } else if (!Roam.checkLocationServices()) {
        Roam.requestLocationServices(this)
    }
}

This method checks:

  • If foreground location permission is granted

  • If background location permission is granted

  • If location services (GPS/Wi-Fi) are enabled

If any of them are missing, it prompts the user accordingly.

You also need to handle user responses when they interact with the permission dialogs.

Add these two override methods in the same activity:

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    // Handle permission results here
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    // Handle location service dialog result here
}

Inside these callbacks, you can optionally retry tracking or show a message to the user if permissions were denied.

✅ What You Should See After a Successful Setup

When implemented correctly:

  • The app should prompt the user for location permissions when first launched.

  • If permissions are granted, no errors should be thrown, and the app can proceed to tracking.

  • If permissions are denied, the SDK will gracefully halt tracking until they are granted.

🧪 Test Tip: Try launching the app with a fresh install on a real device or emulator with Android 10+ to observe how the system prompts appear.

Step 4: Start and Stop Location Tracking

Once the SDK is initialized and permissions are granted, you’re ready to start tracking location. This step covers how to begin and end location tracking using Roam’s built-in methods.

Start Tracking

To start tracking, call the Roam.startTracking() method. This will begin collecting location updates in the background — using a default configuration optimized for both accuracy and battery usage.

Add the following code wherever you want to begin tracking (e.g., inside your MainActivity, or after user login):

Roam.startTracking(RoamTrackingMode.BALANCED, object : TrackingCallback {
    override fun onSuccess(message: String?) {
        // Tracking started successfully
        Log.d("RoamTracking", "Tracking started: $message")
    }

    override fun onError(error: RoamError?) {
        // Handle tracking error
        Log.e("RoamTracking", "Error starting tracking: ${error?.message}")
    }
})

Stop Tracking

To stop tracking at any point, simply call Roam.stopTracking():

Roam.stopTracking(object : TrackingCallback {
    override fun onSuccess(message: String?) {
        // Tracking stopped successfully
        Log.d("RoamTracking", "Tracking stopped: $message")
    }

    override fun onError(error: RoamError?) {
        // Handle stopping error
        Log.e("RoamTracking", "Error stopping tracking: ${error?.message}")
    }
})

This is useful for scenarios such as:

  • When the user logs out

  • You only need on-demand tracking

  • For specific app states or events

✅ What You Should See After a Successful Setup
  • When tracking starts: You should see logs confirming that tracking has begun ("Tracking started").

  • When tracking stops: You’ll see a corresponding "Tracking stopped" message.

  • If there’s an issue (e.g., permissions not granted or SDK not initialized), onError() will be triggered.

🧪 Test Tip: Run the app, start tracking, and move around with the device. Then stop tracking and verify that no additional location updates are received.

Step 5: Receive Location Updates

Once tracking has started, the Roam SDK will begin generating location updates in real time. To receive these updates in your app, you’ll implement a RoamReceiver.

This receiver listens for broadcasted location events and allows you to process, log, or forward location data however your app needs.

5.1 Create a LocationReceiver

Start by creating a new Kotlin file named LocationReceiver.kt, and add the following implementation:

import android.content.Context
import android.util.Log
import com.roam.sdk.service.RoamReceiver
import com.roam.sdk.models.RoamLocation
import com.roam.sdk.models.RoamError

class LocationReceiver : RoamReceiver() {

    override fun onLocationUpdated(context: Context?, locations: MutableList<RoamLocation>?) {
        locations?.firstOrNull()?.let {
            Log.d("LocationReceiver", "Location: ${it.location}")
            // You can also store, sync, or display the location here
        }
    }

    override fun onError(context: Context?, error: RoamError?) {
        Log.e("LocationReceiver", "Location Error: ${error?.message}")
        // Optional: Handle specific error codes if needed
    }
}
🧠 How This Works?
  • RoamReceiver is a broadcast receiver that listens for updates emitted by the SDK.

  • Whenever new location data is available, the SDK triggers onLocationUpdated().

  • You can process and store the data (e.g., upload to a server or update UI).

5.2 Register Receiver in AndroidManifest.xml

After creating your LocationReceiver, you need to register it in your app’s manifest so that the SDK can deliver location updates to it.

Open your AndroidManifest.xml and add the following inside the <application> block:

<receiver android:name=".LocationReceiver"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
        <action android:name="com.roam.android.RECEIVED"/>
    </intent-filter>
</receiver>

This tells the Android system to allow your app to receive broadcasts from the Roam SDK for location updates.

✅ What You Should See After a Successful Setup

Once registered:

  • You should begin receiving live location updates in your LocationReceiver after calling Roam.startTracking(...).

  • Each update will trigger the onLocationUpdated() method with the latest RoamLocation data.

  • If the receiver is not registered properly, no location updates will be delivered, even if tracking is active.

🧪 Debug Tip: If you don’t see any logs, double-check the receiver registration, permissions, and tracking status.

Step 6: Set Up Foreground Location Service

To ensure your app can reliably receive location updates — especially when running in the background — Android requires that you use a foreground service.

A foreground service keeps your app active and visible to the system, helping prevent it from being killed when the device is idle or under memory pressure.

6.1 Add Service Entry in Manifest

Open your AndroidManifest.xml and add the following inside the <application> block:

AndroidManifest.xml
<service android:name=".LocationService"
    android:enabled="true"
    android:exported="false"
    android:foregroundServiceType="location"
    tools:ignore="ForegroundServicePermission" />

This declares your LocationService as a foreground service responsible for handling location updates.

Also, make sure to declare the required permissions at the top of your manifest:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

6.2 Create LocationService.kt

Now, create a new Kotlin file named LocationService.kt and add the following code:

import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.content.IntentFilter
import android.os.Build

class LocationService : Service() {
    private var mLocationReceiver: LocationReceiver? = null

    override fun onCreate() {
        super.onCreate()
        registerReceiver()
    }

    private fun registerReceiver() {
        mLocationReceiver = LocationReceiver()
        val filter = IntentFilter("com.roam.android.RECEIVED")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            registerReceiver(mLocationReceiver, filter, RECEIVER_EXPORTED)
        } else {
            registerReceiver(mLocationReceiver, filter)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        mLocationReceiver?.let { unregisterReceiver(it) }
    }

    override fun onBind(intent: Intent?): IBinder? = null
}

This service dynamically registers your LocationReceiver and ensures that it stays active while tracking is enabled.

✅ What You Should See After a Successful Setup

Once this service is added and launched:

  • The receiver will continue to receive location updates even when the app is in the background.

  • You should see location logs in Logcat when moving around.

  • If something is misconfigured (e.g., missing permissions or manifest entry), you may see runtime exceptions or no updates at all.

🧪 Test Tip: Start tracking, then press the home button to background the app. Watch Logcat to confirm that LocationReceiver continues to receive updates.

Step 7: Enable and Configure Batch Sync

By default, the Roam SDK transmits each location update in real-time. However, you can enable Batch Mode to buffer and send multiple location events together — optimizing for network efficiency and battery life, especially in low-connectivity scenarios.

7.1 Enable Batch Transmission

In your main activity or wherever you handle tracking logic, enable batch mode using:

RoamBatch.setConfig(true, roamBatchPublish)

Here, roamBatchPublish is your configuration object for what data you want included in each batch.

7.2 Customize What Gets Sent (Optional)

Use the RoamBatchPublish.Builder() to control what data is included in each batch upload:

import com.roam.roam_batch_connector.RoamBatchPublish

val roamBatchPublish = RoamBatchPublish.Builder()
    .userId()
    .locationEvents()
    .batteryStatus()
    .speed()
    .appVersion()
    .deviceModel()
    .carrierName()
    // Add as many as you'd like
    .metadata(customBundle) // optional: include your own metadata
    .build()

You can pass any custom values to .metadata(...) using an Android Bundle object.

Disabling Batch Sync

To turn off batch syncing, call:

RoamBatch.setConfig(false)

This will stop buffering and resume real-time location updates.

✅ What You Should See After a Successful Setup
  • Location updates will continue, but now they’ll be sent in batches instead of individually.

  • Reduced network calls in background or poor-connectivity conditions.

  • Improved battery usage for long-running location sessions.

  • The data you selected via RoamBatchPublish.Builder() will be visible in the logs after sync.

🧪 Test Tip: Simulate offline behavior by disabling Wi-Fi and mobile data. Then re-enable them after some time to observe batch sync behavior.

Data Included in Batch Location Updates

When Batch Sync is enabled, each location update sent to Roam servers includes a rich set of contextual metadata. This allows for precise analysis of user movement, environment, and device conditions.

Below is the list of data fields available in each batched location update:

#
Field Name
Publish Parameter

1

Tracking Mode

tracking_mode

2

Latitude

latitude

3

Longitude

longitude

4

Speed

speed

5

Altitude

altitude

6

Course

course

7

Horizontal Accuracy

horizontal_accuracy

8

Vertical Accuracy

vertical_accuracy

9

Activity

activity

10

App Context

app_context

11

Recorded At (timestamp)

recorded_at

12

Timezone Offset

tz_offset

13

Battery Status

battery_status

14

Battery Remaining (%)

battery_remaining

15

Battery Saver Enabled

battery_saver

16

Network Status

network_status

17

Network Type (e.g., Wi-Fi)

network_type

18

Network State (connected?)

network_state

19

Location Permission Status

location_permission

20

GPS Status

gps_status

21

Device Model

device_model

22

Device Manufacturer

device_manufacturer

23

Device Name

device_name

24

Kernel Version

kernel_version

25

Local IP Address

ip_address

26

Public IP Address

public_ip_address

27

Wi-Fi SSID

wifi_ssid

28

Locale Country

locale_country

29

Locale Language

locale_language

30

Carrier Name

carrier_name

31

App Name

app_name

32

App Installation Date

app_installation_date

33

App Version

app_version

34

OS Name

system_name

35

Centroid (clustered)

centroid

36

Custom Metadata (Bundle)

metadata

37

SDK Version

sdk_version

38

Location ID

location_id

39

User ID (external)

user_id

40

App ID

app_id

41

Local Geofence Events

local_geofence_events

42

Android SDK Version

android_sdk_version

43

Android Release Version

android_release_version

44

Build Type

build_type

45

Build Version Incremental

build_version_incremental

46

Build ID

build_id

47

Android Advertising ID (AAID)

aaid

48

Package Name

package_name

49

Installed Applications

installed_applications

50

Allow Mocked Locations

allow_mocked

51

OS Version

os_version

52

ID for Vendor (IDFV)

idfv

53

ID for Advertisers (IDFA)

idfa

54

Data Source

source

55

Bundle ID

bundle_id

56

Location Listener

location_listener

57

Authorization Status

location_authorization_status

58

Nearby Events

nearby_events

59

App Details

app_details

60

Geofence Events

geofence_events

61

Trips Events

trips_events

62

Location Events

location_events

63

Event Listener

event_listener

64

Airplane Mode

airplane_mode

65

Discarded Flag

discarded

🎉 You’re All Set!

You’ve successfully completed the full Roam Android SDK integration — from initializing the SDK and handling permissions, to starting location tracking and enabling batch sync.

Your app is now ready to:

  • Continuously track user location with optimized battery usage

  • Receive real-time updates through a reliable foreground service

  • Sync data efficiently to Roam servers in batches (if enabled)

Need help? Check out our FAQs, explore the sample project on GitHub, or contact our support team.

Last updated

Was this helpful?