Android documentation

The MOTIONTAG Mobility & Location Analytics SDK enables to collect raw sensor data of the telephone in a battery efficient way. This data is then transmitted to the MOTIONTAG back-end system (ISO 27001 certified). In the backend, the sensor events are processed and a partial journey is constructed. Journeys consist either solely of tracks or tracks plus stays. Tracks describe a movement from a origin to a destination with a certain mode of transport. Stays symbolize a stationary behaviour with a particular purpose for the visit.

The use cases for the SDK are manifold. In the mobility sector it can be used to get detailed mobility data for planning purposes. The collected data enables to compare how the transport network is being used. This way the effectiveness of the current infrastructure and the passenger flow management is measured and the design of new mobility services. By implementing and using the SDK you can make use of these findings to improve timetables and routes, expand transport supply and attract more passengers.

If you integrate the MOTIONTAG SDK inside your own application, you can either download user journeys via a provided dump interface on the internet or we tailor a customized solution to your needs.

1. Download

1.1 Native sample app

A native Android sample app can be found on our GitHub page: This sample app showcases the best practices in integrating the SDK into native Android apps.

1.2 Project build gradle

First you need to add the following to you projects build.gradle file:

allprojects {
    repositories {
        maven { url "" }

This allows you to download the SDK from our public maven repository.

1.3 Application build gradle

The SDK requires compileSdkVersion 28 or higher for on version 2.1.0 or older and compileSdkVersion 29 on version 2.2.0+

Java 8 support is needed, therefore is should be added via compileOptions:

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()

It also requires apps to migrate to androidx, you can check the official migration guide here.

Lastly, you need to include the following dependency in your application build.gradle file to download the SDK:

implementation 'de.motiontag:tracker:<VERSION>'

1.4 Auto Backup for Apps

Auto Backup for Apps is a platform feature that automatically backs up a user's data from apps that target and run on Android 6.0 (API level 23) or later. To limit unexpected behavior from our SDK, you should either disable automated backups entirely or exclude the appropriate SDK files from full backup. To fully disable the Auto Backup feature you must add the following flag to the app's AndroidManifest.xml :

<manifest ... >
        android:allowBackup="false" ... >

In case your app relies on Auto Backup and you don't want fully disable it, some SDK files must be excluded from the process:

<manifest ... >
        android:fullBackupContent="@xml/my_backup_rules" ... >

The my_backup_rules.xml is a xml file that should be created in the app's resources folder and contains the paths that must be excluded from the back up process:

<?xml version="1.0" encoding="utf-8"?>
    <exclude domain="sharedpref" path="motiontag_tracker.xml"/>

The above lines can be appended to an existing file in case your app has already defined one. More information can be found here.

1.5 SDK version

You can find the SDK version in our changelog page.

You should be good to go now ;)

2. MotionTag Tracker Structure

2.1 MotionTag class

The MotionTag class is the main entry point of the SDK. It has the following public methods:

Returns Method Explanation
void with(application: Application, settings: Settings, callback: MotionTag.Callback) Initializes the SDK with the Application context, Settings and the MotionTag.Callback implementation.
void start(token: String) Starts tracking for the specified user JWT token. The provided MotionTag.Callback implementation will be called to inform about SDK state changes or relevant tracking events.
void stop() Stops tracking and removes the foreground notification.
Boolean isTrackingActive() Returns true if the tracking is active and collecting data, false otherwise.
void notification(notification: Notification) Updates the provided tracking Notification. Can be safely called even after the tracking has been started.
void useBatterySavingMode(on: Boolean) This function is deprecated and will be removed in version 6.0.0. Enables the Battery Saving Mode, as known as Slow-Mode. In this mode the Location Services is disabled to preserve battery when the phone is stationary after a certain amount of time. Disabling this mode leads to a higher battery usage, however it improves the location tracking. Can be safely called even after the tracking has been started.
void useWifiOnlyDataTransfer(on: Boolean) Enables the data transmission only when connected to Wifi. Can be safely even called after the tracking has been started.
Boolean hasRequiredLocationSettings() Checks if the device has all the required location settings (e.g.: LocationManager.GPS_PROVIDER).
Boolean hasRequiredPermissions() Checks if the app has been granted all required runtime permissions.
List<String> getRequiredPermissions() Returns an list with the required runtime permissions.
List<String> getDeniedRequiredPermissions() Returns an list with the required runtime permissions that are still denied.
void requestRequiredLocationSettings(activity: Activity, requestCode: Int) Displays a dialog that allows users to enable all the required location settings. The result of the dialog will be returned via onActivityResult(requestCode: Int, resultCode: Int, data: Intent).
Settings getSettings() Retrieves current settings
void clearData() Stops tracking and deletes all stored user data from the SDK

2.2 Settings.Builder class

The Settings class is used to customise the behaviour of the SDK during its initialization.

Returns Method Explanation
Settings.Builder notification(notification: Notification) Sets the Android Notification to be displayed when the device is moving. The FLAGONGOINGEVENT flag will be added to the Notification if not provided. Starting from API version 26, a NotificationChannel must be created first. In order to avoid distracting the user, we recommend setting NotificationCompat.PRIORITY_LOW and NotificationManager.IMPORTANCE_LOW to your Notification and the associated NotificationChannel, respectively.
Settings.Builder useBatterySavingMode(on: Boolean) This function is deprecated and will be removed in version 6.0.0.. Enables the Battery Saving Mode, so less battery is draining if set to true. In this mode the Location Requests are disabled when stationary to preserve battery. Disabling this mode leads to a higher battery usage, however it improves the location tracking. The default is set to true.
Settings.Builder useWifiOnlyDataTransfer(on: Boolean) Enables Wifi only transmission of sensor events. Disabling this can lead to high cost because of the mobile data usage, however it improves analysis speed, so the user has maybe a faster response of processed journeys. The default is set to true.
Settings build() As described in the Builder Pattern a build() method is needed to construct the actual Settings object.

2.3 MotionTag.Callback interface

MotionTag.Callback interface used to inform an application about state changes:

Returns Method Explanation
void onEvent(event: Event) Informs the application about a new incoming event.

Event description:

Event Explanation
AutoStartEvent(reason: Reason) Informs the application that tracking has been automatically started.
AutoStopEvent(reason: Reason) Informs the application that tracking has been automatically stopped.
LocationEvent(location: Location) Hands the latest captured android.location.Location. to the application.
TransmissionEvent.Success(timestamp: Long, trackedFrom: Long, trackedTo: Long) Informs when a package of events has been successfully sent to the server. The timestamp represents the time of the server confirmation response. The trackedFrom and trackedTo represents the time range of the transmitted events.
TransmissionEvent.Error(timestamp: Long, errorCode: Int, errorMessage: String) Informs when a package of events failed to be transmitted to the server. The timestamp represents the time of the failure. The errorCode and errorMessage describes the error that occurred.

2.4 Reason enum

The Reason enum describes the reasons behind the automatic tracking stops and starts.

Selection Explanation
RESTART This is the case when tracking is restarted after a phone restart.
LOCATION_SERVICE This is the case when tracking is restarted after the user turns on the location services.
KILLED This is the case when tracking is restarted after an application kill.
PERMISSION This is the case when tracking is started without the required runtime permissions.

3. Usage

3.1 Initialization

This initialization should be either in your Application file or in a file that is directly affiliated with the Application, so it's started/restarted when the Application file is initialized.

class App : Application(), MotionTag.Callback {

    private val yourNotification: Notification //

    override fun onCreate() {
        val settings = Settings.Builder()
            .notification(yourNotification)  // Your notification that should be shown while tracking is active
            .useWifiOnlyDataTransfer(true)   // default: true
        MotionTag.with(this, settings, this)

    override fun onEvent(event: Event) {
        TODO() //Handle events from the SDK

3.2 Runtime permissions

3.2.1 Android 9 and below

The SDK needs the android.permission.ACCESS_FINE_LOCATION runtime permission.

3.2.2 Android 10

The SDK needs android.permission.ACCESS_FINE_LOCATION permission and since Android 10 both android.permission.ACCESS_BACKGROUND_LOCATION and android.permission.ACTIVITY_RECOGNITION are also needed.

After requesting the location permissions, Android 10 users will get a dialog with 3 different options to choose from. Users must select "Allow all the time" option, otherwise the SDK won't function properly.

3.2.3 Android 11

Starting on Android 11, the android.permission.ACCESS_FINE_LOCATION permission must be granted before requesting android.permission.ACCESS_BACKGROUND_LOCATION. There are 2 different cases to consider when running the SDK on a Android 11 device:

  • If the app targets Android 11 (targetSdkVersion = 30): A system exception will be thrown if android.permission.ACCESS_BACKGROUND_LOCATION is requested before holding android.permission.ACCESS_FINE_LOCATION permission.
  • If the app targets Android 10 or lower (targetSdkVersion <= 29): The app can still request both location permissions at the same time. The resulting permission dialog will contain a link that allows users to select "Allow all the time" in the app permission settings.

More information in the official Android documentation. An example implementation can be found in our sample app.

3.2.4 Runtime permission helper functions

The SDK exposes 3 public methods that helps you verify whether the SDK has been granted or not all required runtime permissions based on the device's Android version:

hasRequiredPermissions(): Bool, getRequiredPermissions(): List<String>, getDeniedRequiredPermissions(): List<String>.

3.2.5 Background location access approval

In 2020, Google introduced a new process that requires app developers to get explicit approval for each app that needs access to user’s location data in the background. App developers integrating the Android MOTIONTAG SDK will need to get this approval since the SDK requires access to background location data in order to function correctly. You can find more information about the approval here.

3.3 Location settings

Location services should be enabled in the device otherwise the SDK will not function properly. In order to display a dialog requesting the users to enable it, one could use the SettingsClient and set LocationRequest.PRIORITY_HIGH_ACCURACY priority in the LocationSettingsRequest.Builder.

The SDK contains 2 methods to help you with the task of verifying and requesting the required location settings: boolean hasRequiredLocationSettings() and requestRequiredLocationSettings(Activity activity, int requestCode).

3.4 SDK user authentication

The SDK must be configured at runtime with a user-specific token.

Tokens can be generated on your backend, or manually with the form below (only accessible when signed in). They are signed JWTs (see Users are identified by distinct UUIDs – the creation and management of the user UUIDs is up to you. MOTIONTAG creates a user entry in its database when data from the SDK for a new user UUID arrives for the first time.

To generate the JWTs on your backend, encode and sign a payload like the example below with the shared secret, which is accessible in the admin dashboard under "Authentication tokens". Include these claims:

  • iss claim: the tenant key that you have received from MOTIONTAG
  • sub claim: the user UUID
  • exp claim: expiry integer timestamp (optional)

Example payload:

  "iss": "my-tenant-key",
  "sub": "aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb"

Generate JWTs from user UUIDs

Only accessible when signed in. You need a custom domain setup by MOTIONTAG (e.g. and an account to sign in. Contact MOTIONTAG Support to request a custom domain setup and an account. If you already have both, visit your custom domain and sign in to see a customized version of this documentation.

3.5 Start/Stop Tracking

As described in the chapter 'SDK user authentication', to start tracking, you need a token for the SDK to access our backend system.

Using the token you can start...

class CustomClass : MotionTag.Callback {

    private val yourToken = "SECRET_JWT"

    fun start() {

... and stop

class CustomClass : MotionTag.Callback {

    fun stop() {

... the tracking after the initialization from wherever you want.

3.6 Automatic Start/Stop

When the tracking is ACTIVE it will be automatically stopped and in some cases automatically restarted e.g.

  • Location Services Off causes an automatic stop (Reason.LOCATION_SERVICE).
  • Location Services On causes an automatic start (Reason.LOCATION_SERVICE).
  • Reboot causes an automatic start (Reason.RESTART).
  • Application Update causes an automatic start (Reason.RESTART).
  • Missing a required permission causes an automatic stop (Reason.PERMISSION).
  • System or user kills the App causes an automatic start. If the App is manually opened by the user after the killing, the tracking will be immediately started again. Otherwise, the tracking will be automatically restarted at most 20 minutes. (Reason.KILLED).
class CustomClass : MotionTag.Callback {

    override fun onEvent(event: Event) {
        when (event) {
            is AutoStartEvent -> onAutoStart(event.reason) // do something after the tracking was restarted, e.g.
            is AutoStopEvent -> onAutoStop(event.reason)   // do something after the tracking was stopped, e.g.
            is TransmissionEvent -> onTransmission(event)  // do something after the application has successfully transmitted data, or an error occurred in the process e.g.
            is LocationEvent -> onLocation(event.location) // do something after the application provides a location, e.g.

    private fun onAutoStart(reason: Reason) {
        when (reason) {
            Reason.RESTART -> TODO()           // do something after the tracking was restarted after rebooting the phone or updating the application.
            Reason.LOCATION_SERVICE -> TODO()  // do something after the tracking was restarted by turning on the location services.
            Reason.KILLED -> TODO()            // do something after the application has been killed and the tracking is restarted.

    private fun onAutoStop(reason: Reason) {
        when (reason) {
            Reason.RESTART -> TODO()            // do something after the tracking was stopped because the phone was shut down
            Reason.LOCATION_SERVICE -> TODO()   // do something after the tracking was stopped by turning off the location services.

    private fun onTransmission(event: TransmissionEvent) {
        when(event) {
            is TransmissionEvent.Success -> TODO()   // Transmission was successful. Maybe display the time, so the user gets informed that data will be analysed soon.
            is TransmissionEvent.Error -> TODO()     // Transmission was not successful. Maybe log the error in order to analyze it afterwards.

    private fun onLocation(location: Location) {
        // Maybe display the location on a map

3.7 Runtime Setting Changes

You can still change all settings during runtime. For example if the user changes the language settings on the phone you probably want to provide a new notification with the appropriate language. Just call one of the following methods from anywhere in your application.

class CustomClass : MotionTag.Callback {

    private val yourNotification: Notification //

    fun customize() {

3.8 Current Settings

You can get current SDK settings with the following call:

class CustomClass : MotionTag.Callback {

    fun getCurrentSettings() : Settings {
        return MotionTag.getSettings()

3.9 Clear stored user data

It is possible to delete user data that is stored locally with the following command...

class CustomClass : MotionTag.Callback {

    // more implementation specifics

    fun clearUserData() {

4. WorkManager

The MOTIONTAG SDK uses the WorkManager library under the hood to schedule its deferrable and asynchronous tasks. Please avoid calling WorkManager.cancelAllWork() at all costs as this will cancel all workers previously scheduled by the SDK.

5. Non-standard background process limitations

Some Android OEMs, like Huawei and OnePlus, decided to implement non-standard background process limitations on 3rd party apps as an attempt to reduce battery consumption. The MOTIONTAG SDK must be running all times in the background, otherwise it won't function properly.

Therefore we recommend developers integrating our SDK to read the website, it describes this problem in detail and it provides some workaround options for both developers and users. There's also this StackOverflow post which describes how developers can forward users to the correct OEM settings.

When battery optimization is turned on for your app, the MOTIONTAG SDK may not be able to track and generate data continuously. If 24/7 tracking on all supported phone models is crucial to your use case, we strongly recommend you to include a prompt for the user, and facilitate the deactivation of battery optimization settings for your app on the affected phones.

6. Gradle

  • Minimum SDK Version: 21
  • Obfuscated with R8

7. License

The SDK is licensed under the MOTIONTAG SDK Test License.

8. Open Source Software Licenses

The SDK relies on Open Source Software components. See their respective Open Source Licenses.