# Quick Start

## Setup the MOVE SDK

The Android MOVE SDK must be initialized by adding MoveSdk.[init](/move-platform/sdk/api-interface/android/initialization.md#init)() at the first line in your Android Application class (onCreate). This instance can then be used to control MOVE SDK services (check [API Interface](/move-platform/sdk/api-interface.md) for more [details](/move-platform/sdk/api-interface/android/initialization.md)).

After the MOVE SDK has been initialized you also want to add notifications, listeners or activate additional features.

Also, you have to configure the MOVE SDK before you can call .[setup](/move-platform/sdk/api-interface/android/initialization.md#setup)(...).

{% hint style="warning" %}
To successfully initialize and run the MOVE SDK, the user's [MoveAuth ](/move-platform/sdk/models/moveauth.md)must already be fetched with the [MOVE Admin API](/move-platform/backend/move-backend/move-admin-api.md) and the required permissions must be granted ([Permission Handling](/move-platform/sdk/appendix/android/permission-handling.md)).

If the provided [MoveAuth ](/move-platform/sdk/models/moveauth.md)is invalid, the MOVE SDK will not initialize.

If the required permissions are missing, the MOVE SDK State will change to READY. Additionally, MoveServiceFailure and/or MoveServiceWarning will present the missing permission.
{% endhint %}

The initialization of the MOVE SDK is asynchronous and you will be notified regarding state changes with the [MoveStateListener](/move-platform/sdk/models/listeners-callbacks.md). On successful initialization the [MoveSdkState](/move-platform/sdk/models/movesdkstate.md) changes to `READY`.&#x20;

To be able to use the MOVE SDK, several permissions need to be granted. This is described in [Permission Handling](/move-platform/sdk/appendix/android/permission-handling.md).

Now that there is an instance of the MOVE SDK, the detection may be started with [startAutomaticDetection()](/move-platform/sdk/api-interface/android/services.md#start-automatic-detection), which should lead to the state `RUNNING` of the MOVE SDK.

{% hint style="warning" %}
If the MOVE SDK trip detection was started with [startAutomaticDetection()](/move-platform/sdk/api-interface/android/services.md#start-automatic-detection) then it is not possible to manual start a trip with [startTrip(...)](/move-platform/sdk/api-interface/android/services.md#manual-start-trip).
{% endhint %}

{% hint style="warning" %}
The MOVE SDK is collecting data only when in`RUNNING`state.
{% endhint %}

### Code example

```kotlin
package com.example.movesdkandroid

import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.util.Log
import androidx.annotation.MainThread
import androidx.core.app.NotificationCompat
import io.dolphin.move.DrivingService
import io.dolphin.move.MoveAuthResult
import io.dolphin.move.MoveAuthState
import io.dolphin.move.MoveConfig
import io.dolphin.move.MoveConfigurationError
import io.dolphin.move.MoveDetectionService
import io.dolphin.move.MoveNotification
import io.dolphin.move.MoveSdk
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class MoveSDKTest : Application() {

    private val authCallback = object : MoveSdk.MoveAuthCallback {
        override fun onResult(result: MoveAuthResult) {
            // Handle result here. See full example:
            // https://docs.movesdk.com/move-platform/sdk/api-interface/android/initialization#with-authcode
            Log.d("MoveAuthCallback", "onResult: $result")
        }
    }

    override fun onCreate() {
        // MoveSdk.init() must be the first line in onCreate()
        MoveSdk.init(this)
        super.onCreate()
        setupSdk()
    }

    private fun setupSdk() {
        CoroutineScope(Dispatchers.IO).launch {
            // Fetch authCode from your backend.
            // Your backend calls the MOVE Admin API:
            // GET /v20/user/authcode?userId={userId}
            // https://docs.movesdk.com/move-platform/backend/move-backend/move-admin-api
            // Returns: { "authCode": "string" }
            val authCode: String? = "YOUR_AUTH_CODE" // Replace this with your actual backend call

            if (authCode != null) {
                withContext(Dispatchers.Main) {
                    prepareAndConfigSdk(authCode)
                }
            } else {
                Log.e("MoveSDKTest", "Failed to fetch authCode from backend")
            }
        }
    }

    @MainThread
    private fun prepareAndConfigSdk(authCode: String) {

        val channelId = "channel-sdk"
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        val sdkChannel = NotificationChannel(channelId, "Dolphin SDK", NotificationManager.IMPORTANCE_DEFAULT)
        notificationManager.createNotificationChannel(sdkChannel)

        MoveSdk.get()?.recognitionNotification(
            NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.drawable.ic_notification) // Replace with your own drawable resource
                .setContentTitle(getString(R.string.app_name)) // Replace with your own app nameame))
                .setContentText("Active")
                .setShowWhen(false)
                .setSilent(true)
        )

        MoveSdk.get()?.tripNotification(
            NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.drawable.ic_notification) // Replace with your own drawable resource
                .setContentTitle(getString(R.string.app_name)) // Replace with your own app nameame)ame))
                .setContentText("Driving")
                .setShowWhen(true)
                .setSilent(true)
        )

        // To customize notification texts only (without replacing the full notification):
        /*
        MoveSdk.get()?.setNotificationText(
            MoveNotification(
                recognitionTitle = getString(R.string.app_name),
                recognitionText = "Active",
                drivingTitle = getString(R.string.app_name),
                drivingText = "Driving",
            )
        )
        */

        val initListener = object : MoveSdk.InitializeListener {
            override fun onError(error: MoveConfigurationError) {
                Log.d("MoveConfigurationError", "onError: $error")
            }
        }

        val authStateListener = object : MoveSdk.AuthStateUpdateListener {
            override fun onAuthStateUpdate(state: MoveAuthState) {
                when (state) {
                    is MoveAuthState.INVALID -> {
                        // User session invalid -> log out and shut down
                        MoveSdk.get()?.shutdown(force = true)
                    }
                    else -> {}
                }
            }
        }

        MoveSdk.get()?.apply {
            authStateUpdateListener(authStateListener)
            initializationListener(initListener)

            // MORE INFORMATION ABOUT LISTENERS:
            // https://docs.movesdk.com/move-platform/sdk/models/listeners-callbacks

            // sdkStateListener(sdkStateListener)
            // tripStateListener(tripStateListener)

            consoleLogging(true)
        }

        val moveConfig = MoveConfig(
            moveDetectionServices = listOf(
                MoveDetectionService.Driving(
                    drivingServices = listOf(
                        DrivingService.DrivingBehaviour,
                        DrivingService.DistractionFreeDriving,
                        DrivingService.DeviceDiscovery,
                    )
                ),
                MoveDetectionService.Walking(),
                MoveDetectionService.Cycling,
                MoveDetectionService.AutomaticImpactDetection,
                MoveDetectionService.AssistanceCall,
            )
        )

        MoveSdk.get()?.setup(
            authCode = authCode,
            config = moveConfig,
            start = true, // true = startAutomaticDetection() is called automatically after setup
            callback = authCallback
        )
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.movesdk.com/move-platform/sdk/getting-started/android/quick-start.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
