Android

Android SDK

Requirements

Basic integration

Migrating from older versions? Check the Migration guide

Add HyperTrack SDK to your project

We constantly work on making our SDKs better, so make sure you have the latest version. You can get it in the changelog here.

Add HyperTrack's Maven repository

Depending on the Gradle version used in the Project use one of the following snippets:

This way of managing dependencies was added in Gradle 6.8 and is required by default in Gradle 8.

dependencyResolutionManagement {
    ...
    repositories {
        google()
        mavenCentral()
        jcenter()

        maven {
            name 'hypertrack'
            url 'https://s3-us-west-2.amazonaws.com/m2.hypertrack.com/'
        }
    }
}

dependencyResolutionManagement {
    ...
    repositories {
        google()
        mavenCentral()
        jcenter()

        maven {
            name = 'hypertrack'
            url = 'https://s3-us-west-2.amazonaws.com/m2.hypertrack.com/'
        }
    }
}
Without centralized repositories declaration

Add the repository to your module-level Gradle config (usually app/build.gradle) and project-level one (<project folder>/build.gradle).

repositories {
    maven {
        name 'hypertrack'
        url 'https://s3-us-west-2.amazonaws.com/m2.hypertrack.com/'
    }
}
repositories {
    maven {
        name = 'hypertrack'
        url = 'https://s3-us-west-2.amazonaws.com/m2.hypertrack.com/'
    }
}
allprojects {
    repositories {
        google()
        mavenCentral()
        maven {
            name 'hypertrack'
            url  'https://s3-us-west-2.amazonaws.com/m2.hypertrack.com/'
        }
    }
}
allprojects {
    repositories {
        google()
        mavenCentral()
        maven {
            name = 'hypertrack'
            url = 'https://s3-us-west-2.amazonaws.com/m2.hypertrack.com/'
        }
    }
}

Add HyperTrack SDK dependencies

Add HyperTrack SDK dependencies to the app or module

dependencies {
    ...
    implementation 'com.hypertrack:sdk-android:<version>'
    implementation 'com.hypertrack:location-services-google:<version>'
    implementation 'com.hypertrack:push-service-firebase:<version>'
    ...
}
dependencies {
    ...
    implementation('com.hypertrack:sdk-android:<version>')
    implementation('com.hypertrack:location-services-google:<version>')
    implementation('com.hypertrack:push-service-firebase:<version>')
    ...
}

The latest version: SDK-Android

You can learn more about SDK plugins here.

⚠️

Because of a known issue in Google Play Services Location library, if you use version 19.0.1 or older you need to use the special version of the HyperTrack SDK Location Services plugin. Check this FAQ item for more details.

💻

After adding dependencies make sure you run Sync Project with Gradle Files!

Configure Proguard

Make sure you are using the latest SDK version.

If you use Proguard (have minifyEnabled true in your app build.gradle) add these lines to your proguard-rules.pro:

# config for kotlin-coroutines
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepclassmembernames class kotlinx.** {
    volatile <fields>;
}
-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}

Set up silent push notifications

HyperTrack SDK requires Firebase Cloud Messaging to:

  • Manage on-device tracking
  • Enable HyperTrack cloud APIs usage to control the tracking from your server
  • Waking up the app if it was killed by the device OS

If you do not yet have push notifications enabled, please proceed to Setup Firebase Cloud Messaging.

To provide HyperTrack the access to sending push messages you need to get a JSON key for a Google Cloud Service account with Firebase access that is connected to your app. You need to upload the key to HyperTrack Dashboard Setup Page under Server to Device communication section.

If you don't know how to get the key, check the guide: Getting Google Service account key for Firebase

Set the publishable key

Get your Publishable Key from the Setup page.

Add PublishableKey to AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:name=".AnApplication">
        <meta-data
            android:name="HyperTrackPublishableKey"
            android:value="put-your-key-here" />
    </application>
</manifest>

Grant the permissions to the app

The application has to ask for runtime permissions before the SDK will be able to track.

The permissions that are necessary are:

Start tracking

Now the app is ready to be tracked from the cloud.

You will need the device id to start tracking, check the Identify devices section for instructions on how to get it.

Follow the Start Tracking tutorial to learn how to control device tracking from your backend.

Dashboard

Once your app is running, go to the dashboard where you can see a list of all your devices and their live location with ongoing activity on the map.

Prepare for Google Play submission

Preparing for Google Play review

Recommended additional steps

Identify devices

All devices tracked on HyperTrack are uniquely identified using UUID. You can get this identifier programmatically in your app by calling getDeviceId().

⚠️

The device ID is changed on each app re-install or clearing the app data

   val deviceId = HyperTrack.deviceID
   String deviceId = HyperTrack.getDeviceID();

Another approach to identification is to tag devices with names that will make it easy to distinguish them on HyperTrack Dashboard.

   HyperTrack.name = "Device name"
   HyperTrack.setName("Device name");

You can additionaly tag devices with custom metadata (and filter them in the Dashboard using metadata fields).

Metadata should be representable with a map of JSON data types.

You need to build a special Json.Object data type to send the data to the SDK. This type ensures that the format is JSON-compatible. There are 2 helper methods to build this object from Map or JSON string, but you can build it manually too using the constructor methods.

Kotlin

import com.hypertrack.sdk.android.Json

val metadataJson: Json? = Json.fromString("{ \"key\":\"value\" }")

if(metadataJson != null) {
    HyperTrack.metadata = metadataJson
} else {
    // You will get the null value if provided String is not a valid JSON
}
import com.hypertrack.sdk.android.Json

val metadataJson: Json? = Json.fromMap(mapOf("key" to "value"))

if(metadataJson != null) {
    HyperTrack.metadata = metadataJson
} else {
    // You will get the null value if provided Map is not a valid JSON Map
}

Java

import com.hypertrack.sdk.android.Json

Json.Object metadataJson = Json.Companion.fromString("{ \"key\":\"value\" }")

if(metadataJson != null) {
    HyperTrack.setMetadata(metadataJson)
} else {
    // You will get the null value if provided String is not a valid JSON
}
import com.hypertrack.sdk.android.Json

Map myMetadata = new HashMap<String, Object>()
myMetadata.put("key", "value")

Json.Object metadataJson = Json.Companion.fromMap(myMetadata)

if(metadataJson != null) {
    HyperTrack.setMetadata(metadataJson)
} else {
    // You will get the null value if provided Map is not a valid JSON Map
}

Handle errors

Use the errors query or subscribeToErrors subscription to make sure that when the driver navigates to the screen where tracking is supposed to happen, there are no blockers that can interrupt it.

You can use subscription API to be able to react immediately when errors come up:

// You can use this value to cancel the subscription.
val errorsCancellable: HyperTrack.Cancellable? = null

errorsCancellable = HyperTrack.subscribeToErrors { errors ->
  errors.forEach {
    when(it) {
      is Permissions.Location.Denied -> ...
      is Location.ServicesDisabled -> ...
      ...
    }
  }
}

Or by querying the API only when needed:

HyperTrack.errors.forEach {
  when(it) {
    is Permissions.Location.Denied -> ...
    is Location.ServicesDisabled -> ...
    ...
  }
}

Check the API docs to get the full list of errors.

Migration guide

Version < 7.0.0

The release of HyperTrack Android SDK 7.0.0 is a major update that has a bunch of new improvements. We highly recommend upgrading, but please note that there are a few breaking changes.

The key advantages of the new version are:

User-friendly API:
The revamped static API is the highlight, standing out for its unmatched simplicity, ease of use, and conciseness.

Enhanced Responsiveness & Speed:
Experience quicker time to the first location and minimized system latency.

Superior Tracking Performance:
Delight in the improved quality, granularity, and accuracy of the location event stream.

Optimized Battery Efficiency:
Our refined tracking algorithm reduces unnecessary network calls, preserving battery life.

Decreased Binary Size:
The library's size optimization ensures a more compact overall app footprint.

You can check the detailed Changelog here

The key breaking changes are:

Setting the publishable key

There is no need to initialize the SDK by setting publishable key. The Basic integration instructions decribe the new way of setting it.

Static API

The SDK API was fully redesigned to be more ergonomic and to require less code to use.

All the API methods can be accessible at any time from any place in the app by calling them on the static HyperTrack class.

Check the Changelog for the renamed methods.

New Maven artifact ID

The old dependency in build.gradle should be removed:

implementation "com.hypertrack:hypertrack:${version}"

Follow the Add HyperTrack SDK to your project tutorial to configure the new SDK.

ACTIVITY_RECOGNITION permission is no longer required

While the SDK still can benefit from Motion activity data to get better accuracy, requesting this permission is now optional.

Make sure you implement requests for all permissions: Grant the permissions to the app

SDK Sync

The SDK is now automatically syncs with the servers, so the syncDeviceSettings() method is not needed. You can safely remove it and all the logic related to it.

New Json.Object param type for addGeotag and metadata

In the new version you need to build a special Json.Object object to send the data to the SDK.

Check the Identify devices metadata section for details on how to use it.

New nested HyperTrack.Error

In older versions there were 2 ways to get the SDK errors:

  1. With addTrackingListener()/addAvailabilityListener() onError callback
  2. With Blockers API HyperTrack.getBlockers()

In the new version both of the APIs above are removed and replaced with Errors API (HyperTrack.errors/HyperTrack.subscrbeToErrors())

Check the Handle errors section for the details on how to use that API.

Here is the table of correspondence between the TrackingError/Blocker and according HyperTrack.Error types:

Old ErrorHyperTrack.Error
TrackingError.UNKNOWN_ERROR-- removed --
TrackingError.INVALID_PUBLISHABLE_KEY_ERRORError.InvalidPublishableKey
TrackingError.AUTHORIZATION_ERROR-- removed --
TrackingError.PERMISSION_DENIED_ERRORError.Permissions.Location.Denied
TrackingError.GPS_PROVIDER_DISABLED_ERRORError.Location.ServicesDisabled
TrackingError.UNKNOWN_NETWORK_ERROR-- removed --
TrackingError.DATA_STORE_ERROR-- removed --
Blocker.LOCATION_PERMISSION_DENIEDError.Permissions.Location.Denied
Blocker.LOCATION_SERVICE_DISABLEDError.Location.ServicesDisabled
Blocker.ACTIVITY_PERMISSION_DENIED-- removed --
Blocker.BACKGROUND_LOCATION_DENIEDError.Permissions.Location.Denied
OutageReason.MISSING_LOCATION_PERMISSIONError.Permissions.Location.Denied
OutageReason.MISSING_ACTIVITY_PERMISSION-- removed --
OutageReason.LOCATION_SERVICE_DISABLEDError.Location.ServicesDisabled
OutageReason.NOT_TRACKINGLocationError.NotRunning
OutageReason.START_HAS_NOT_FINISHEDLocationError.Starting
OutageReason.NO_GPS_SIGNALError.Location.SignalLost
OutageReason.RESTART_REQUIRED-- removed --

Version < 6.3.0

From the version 6.3.0 The device ID doesn't persist between installs similar to iOS SDK

Reference

For a full SDK API reference see HyperTrack Android SDK

SDK integration examples

To learn more about SDK integration examples, you may visit these resources:

Support

Join our Slack community for instant responses.

Frequently Asked Questions

Why starting tracking from the server fails?

HyperTrack relies on Firebase Cloud Messaging to deliver the tracking intent to the app, and to wake up the app if it is killed at that moment. This mechanism is generally reliable, but sometimes may fail or delay due to various reasons.

We recommend to check the following frequent issues:

  • Check if you added FCM key properly as described in Set up silent push notifications.
  • Check if you have matching app package and project ID for the key above and for the app.
  • Check if you mistakenly use wrong environment (production vs development) for the app.
  • Check if you have your app signature properly added to the Firebase project (may fail on debug builds).
  • If you want to simulate waking the app up, make sure you don't use Force stop to kill the app (this feature disables push notifications for that app until the next launch). Kill the app with phone reboot, with simulated crash, or by manually stopping the activities and the services instead. Killing the app from Android Studio or adb also counts as Force stopping and blocks the push notifications.
  • Check the push notification delivery with Firebase debug menu: call *#*#426#*#* in the device dialpad and press Events button. Reopen the debug app to update the logs.

Why do I have persistent notification in my app?

HyperTrack SDK by default runs as a foreground service. This is needed to ensure that the location tracking works reliably even when your app is in background.

A foreground service is a service that the user is actively aware of and isn't a candidate for the system to kill when it is low on memory.

Android require foreground service to have a persistent notification in the status bar.

Can I customize the foreground service notification?

Yes, check the HyperTrackForegroundNotificationTitle and HyperTrackForegroundNotificationText parameters in SDK configuration doc.

You can also check the code example in Quickstart Android

Why do I have dependencies conflicts?

Dependency conflicts may arise when the HyperTrack SDK is used together with different libraries. In most cases Gradle automatically resolves all the issues. In some situations, a configuration modification has to be applied to your project.

Detailed information

More information with detailed explanations and instructions can be found here: Gradle documentation

Cheat sheet

  • In case of unresolvable dependency conflicts, please use ./gradlew :your_project_name:dependencies command to see the dependency graph.

  • Usually there are bumped versions in dependency graph (marked like com.some.dependency:2.0.0 -> com.some.dependency:2.5.0) - Gradle automatically selects the newest version of the transitive dependencies required by other dependencies.

  • If conflicts are visible and cause compilation errors, you can manually exclude the transitive dependencies or downgrade them using: this documentation

  • Common problem here may be depending on different versions of com.android.support library components. You need to migrate to Android X to resolve the issue.

How do I handle system battery saver killing my app?

Check the Whitelisting doc to learn how to handle the battery saver killing your app.

How does tracking work in Doze mode?

Doze mode requires device to be stationary, so before OS starts imposing power management restrictions, exact device location is obtained. When device starts moving, Android leaves Doze mode and works regularly, so no special handling of Doze mode required with respect to location tracking.

Why doesn't setting device metadata and name work in SDK?

Devices API take precedence over SDK methods in setting device name and metadata. If you used it, theSDK methods will not modify device metadata and name.

What runtime permissions are required for the SDK to work?

Chech the Grant permissions section

Why in the dashboard I can see SDK killed by ... outage reason?

SDK killed also can be a result of some kind of battery saving settings. Check How do I handle system battery saver killing my app?

You may benefit from checking this also.

Can I test the tracking without actual movement?

Yes, please check the Test the workflow with mock locations doc.

How to fix Google Api Error: Invalid request - You must let us know whether your app uses any Foreground Service permissions. when uploading the app to Google Play with API?

This error can appear if you have targetSDK 34+. HyperTrack SDK have to use Foreground service, and starting Android 14 it requires declaring the Foreground service permission. If your app has this permission, you can't upload the update with API and need to do a manual release to fill in the Foreground service permissions form. Check our Guide if you have any issues with submitting the form.

How to fix 'AndroidRuntime: java.lang.IncompatibleClassChangeError: Found interface com.google.android.gms.location.FusedLocationProviderClient, but class was expected'?

If the target application / module (or any of the sub-dependencies) uses older Google Play Services Location dependency, a conflict in class definitions between them and HyperTrack SDK Google Play Services dependency can cause build or runtime failures.

The breaking change was added in version 21.0.0), and if your app depend on version 19.0.1 or older, and some other dependency (e.g. HyperTrack SDK) depend on newer version 21.0.0 or newer, you may encounter this issue.

💻

One of the Exceptions that happens with incompatible versions of Google Location Services is:

AndroidRuntime: java.lang.IncompatibleClassChangeError: Found interface com.google.android.gms.location.FusedLocationProviderClient, but class was expected

You can check which dependency version you are using with Gradle dependency graph command:

./gradlew app:dependencies | grep 'com.google.android.gms:play-services-location'
gradlew app:dependencies

Check for lines containing com.google.android.gms:play-services-location. If any of them have version 19.0.1 or older, you should update the dependency to the newer version and check the grapg again..

If updating the dependency is not possible there is a special Location services plugin in HyperTrack SDK to overcome this issue. Use it instead of implementation 'com.hypertrack:location-services-google:<version>:

dependencies {
    ...
    implementation 'com.hypertrack:location-services-google-19-0-1:<version>'
    ...
}
dependencies {
    ...
    implementation('com.hypertrack:location-services-google-19-0-1:<version>')
    ...
}