> For the complete documentation index, see [llms.txt](https://docs.multiset.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.multiset.ai/native-sdk/android-native/sample-activities/mainactivity.md).

# MainActivity

The demo entry point activity: SDK initialization, authentication callbacks and navigation into the AR activities.

## Overview

The `MainActivity` serves as the entry point for the MultiSet SDK demo application. It demonstrates SDK initialization, authentication handling, and navigation to the AR localization activity.

## Description

This activity is responsible for:

1. Initializing the MultiSet SDK with credentials
2. Handling the authentication flow
3. Managing camera and ARCore permissions
4. Launching the unified `MultiSetLocalizationActivity` for single-frame or multi-frame localization
5. Launching `ObjectTrackingActivity` for AR object detection and tracking

The landing page uses a card-based layout:

* **Settings Gear**: top-right icon that opens the [Settings dialog](/native-sdk/android-native/api-reference/localizationconfig.md#runtime-settings-dialog) to edit localization & object-tracking configuration at runtime
* **Auth Button**: full-width, shows authentication state
* **Localization Card**: displays map code, a mode toggle (Single Frame / Multi Frame), and a Start Localization button
* **Object Tracking Card**: displays configured object codes and a Start Object Tracking button

***

## Authentication Flow

### 1. SDK Initialization

The SDK is initialized using credentials from `BuildConfig`:

```kotlin
val config = MultiSetSDKConfig.Builder(clientId, clientSecret)
    .mapCode(mapCode)           // or .mapSetCode(mapSetCode)
    .enableMeshVisualization(true)
    .backgroundLocalization(true)
    .build()

MultiSetSDK.initialize(this, config, this)
```

In the sample app this is wrapped by `MultiSetSDKInit.initialize(context, callback)`, which reads the `BuildConfig` fields produced from `multiset.properties`, applies the optional `MULTISET_BASE_URL` override, and returns `false` (rather than throwing) when credentials or every map and object code are missing, so the UI can show a setup message.

### 2. Configuration Builder Options

| Method                               | Description                                            |
| ------------------------------------ | ------------------------------------------------------ |
| `mapCode(String)`                    | Set a single map code for localization                 |
| `mapSetCode(String)`                 | Set a mapSet code for localizing against multiple maps |
| `objectCodes(List<String>)`          | Set the object codes to track (maximum 10)             |
| `localizationMode(LocalizationMode)` | `SINGLE_FRAME` or `MULTI_FRAME`                        |
| `enableMeshVisualization(Boolean)`   | Enable/disable 3D mesh overlay visualization           |
| `backgroundLocalization(Boolean)`    | Enable/disable background localization                 |
| `poseConsistencyCheck(Boolean)`      | Enable/disable false-positive rejection                |
| `poseConsistencyThreshold(Float)`    | Tolerance in metres, 3 to 30                           |
| `baseUrl(String)`                    | Point the SDK at a staging or on-premise API host      |

The builder exposes the full configuration surface, including confidence settings, localization hints, GPS options, frame counts and image quality. See [LocalizationConfig](/native-sdk/android-native/api-reference/localizationconfig.md) for the meaning of each value.

### 3. Authentication Callbacks

The activity implements `MultiSetSDKCallback` to receive authentication events:

```kotlin
override fun onSDKReady() {
    // SDK is initialized, authentication in progress
}

override fun onAuthenticationSuccess() {
    // Authentication successful, ready for localization
    // Enable localization buttons
}

override fun onAuthenticationFailure(error: String) {
    // Authentication failed
    // Show error message and enable retry
}
```

***

## APIs Used for Authentication

### MultiSetSDK

| Method                                                        | Description                                         |
| ------------------------------------------------------------- | --------------------------------------------------- |
| `MultiSetSDK.initialize(context, config, callback)`           | Initializes the SDK with configuration and callback |
| `MultiSetSDK.isAuthenticated()`                               | Whether a valid token is currently held             |
| `MultiSetSDK.getVersion()`                                    | The SDK version string                              |
| `MultiSetSDK.localizationSession(frameSource, mode)`          | Creates a localization session                      |
| `MultiSetSDK.objectTrackingSession(frameSource, objectCodes)` | Creates an object tracking session                  |
| `MultiSetSDK.resetPoseConsistencyReference()`                 | Re-bootstraps the false-positive reference anchor   |
| `MultiSetSDK.release()`                                       | Releases SDK resources                              |

{% hint style="info" %}
`MultiSetSDK.getLastLocalizationResult()` was removed in 1.16.0. Results are delivered through the session callbacks instead. See [FrameSource and Sessions](/native-sdk/android-native/api-reference/framesource.md).
{% endhint %}

### MultiSetSDKConfig.Builder

| Method                             | Parameters       | Description                                      |
| ---------------------------------- | ---------------- | ------------------------------------------------ |
| `Builder(clientId, clientSecret)`  | `String, String` | Creates a configuration builder with credentials |
| `mapCode(code)`                    | `String`         | Sets the map code for single-map localization    |
| `mapSetCode(code)`                 | `String`         | Sets the mapSet code for multi-map localization  |
| `enableMeshVisualization(enabled)` | `Boolean`        | Enables mesh visualization after localization    |
| `backgroundLocalization(enabled)`  | `Boolean`        | Enables background localization                  |
| `build()`                          | -                | Builds the configuration object                  |

***

## Structure

`MainActivity` is the landing screen. It initializes the SDK, reflects authentication state in the UI, and launches the two AR activities.

### setupUI()

Initializes the UI components and sets up button click listeners:

* Mode toggle group (Single Frame / Multi Frame selection)
* Start Localization button
* Start Object Tracking button
* Settings gear (opens `SettingsDialogFragment` to edit `LocalizationConfig` / `ObjectTrackingConfig` at runtime)

> Persisted configuration is restored before any AR activity reads it: `MainActivity.onCreate()` calls `ConfigStore.load(this)`, which applies the values saved from the Settings dialog. Credentials and map / object codes are always sourced from `multiset.properties` and are never persisted.

### displayMapCode() and displayObjectCodes()

Render the configured map (or mapSet) code and the object code list on the landing cards, so it is obvious which environment and objects the build is pointed at.

### showConfigurationAlert()

Shown when `MultiSetSDKInit.initialize()` returns `false`, meaning credentials or all map and object codes are missing from `multiset.properties`.

### Launching the AR activities

```kotlin
// Localization
val intent = Intent(this, MultiSetLocalizationActivity::class.java)
intent.putExtra(EXTRA_LOCALIZATION_MODE, selectedMode.name)
startActivity(intent)

// Object Tracking
val intent = Intent(this, ObjectTrackingActivity::class.java)
intent.putExtra(EXTRA_OBJECT_CODES, codes.toTypedArray())
startActivity(intent)
```

Camera permission and ARCore availability are requirements of the AR activities, which use ARCore through Sceneform. They are not requirements of the SDK itself.

***

## Callbacks (MultiSetSDKCallback Interface)

### onSDKReady()

Called when the SDK has been initialized and is beginning authentication.

```kotlin
override fun onSDKReady() {
    runOnUiThread {
        binding.authButton.text = getString(R.string.authenticating)
    }
}
```

### onAuthenticationSuccess()

Called when authentication with the MultiSet backend is successful. Enables the Localization and Object Tracking buttons and updates the auth button to show a green "Authenticated" state.

```kotlin
override fun onAuthenticationSuccess() {
    runOnUiThread {
        binding.authButton.text = getString(R.string.authenticated)
        binding.authButton.isEnabled = false
        binding.authButton.backgroundTintList = ColorStateList.valueOf(
            ContextCompat.getColor(this, R.color.success)
        )
        binding.localizationButton.isEnabled = true
        binding.objectTrackingButton.isEnabled = true
    }
}
```

### onAuthenticationFailure(error: String)

Called when authentication fails.

| Parameter | Type     | Description                                 |
| --------- | -------- | ------------------------------------------- |
| `error`   | `String` | Error message describing the failure reason |

```kotlin
override fun onAuthenticationFailure(error: String) {
    runOnUiThread {
        binding.statusText.text = "Authentication Failed"
        binding.authButton.isEnabled = true
        showToast("Authentication failed: $error")
    }
}
```

### onLocalizationSuccess(result: LocalizationResult)

Called when localization succeeds. The result can be logged or used by the host application.

| Parameter | Type                 | Description                                                                                     |
| --------- | -------------------- | ----------------------------------------------------------------------------------------------- |
| `result`  | `LocalizationResult` | Contains map code, map codes list, position, rotation, confidence, and optional geo-coordinates |

```kotlin
override fun onLocalizationSuccess(result: LocalizationResult) {
    Log.d(TAG, "Localization success - mapCode: ${result.mapCode}, " +
            "mapCodes: ${result.mapCodes}, " +
            "position: [${result.position.joinToString()}], " +
            "rotation: [${result.rotation.joinToString()}], " +
            "confidence: ${result.confidence}")
}
```

### onLocalizationFailure(error: String)

Called when localization fails. In `MainActivity`, this is handled by the AR activity.

| Parameter | Type     | Description                                 |
| --------- | -------- | ------------------------------------------- |
| `error`   | `String` | Error message describing the failure reason |

### onLocalizationFalsePositive(info: FalsePositiveInfo)

Called when a localization response was discarded because it contradicted the device's own AR trajectory. The request succeeded; the answer was wrong. The scene is left untouched.

| Parameter | Type                | Description                                                                   |
| --------- | ------------------- | ----------------------------------------------------------------------------- |
| `info`    | `FalsePositiveInfo` | Jump distance, threshold, consecutive count, map codes, confidence and reason |

```kotlin
override fun onLocalizationFalsePositive(info: FalsePositiveInfo) {
    Log.w(TAG, "Discarded false positive: ${info.summary}")
}
```

This callback has a default no-op implementation, so it is optional to override.

### onTrackingStateChanged(state: TrackingState)

Called when AR tracking state changes. Handled internally by the AR activities.

| Parameter | Type            | Description                                        |
| --------- | --------------- | -------------------------------------------------- |
| `state`   | `TrackingState` | Current tracking state (TRACKING, PAUSED, STOPPED) |

### onObjectTrackingSuccess(result: ObjectTrackingResult)

Called when an object is successfully tracked. Forwarded from `ObjectTrackingActivity` via `MultiSetSDK.getCallback()`.

| Parameter | Type                   | Description                                     |
| --------- | ---------------------- | ----------------------------------------------- |
| `result`  | `ObjectTrackingResult` | Contains object code, pose data, and confidence |

```kotlin
override fun onObjectTrackingSuccess(result: ObjectTrackingResult) {
    Log.d(TAG, "Object tracking success - objectCode: ${result.objectCode}, " +
            "position: [${result.position.joinToString()}], " +
            "confidence: ${result.confidence}")
}
```

### onObjectTrackingFailure(error: String)

Called when object tracking fails.

| Parameter | Type     | Description                                 |
| --------- | -------- | ------------------------------------------- |
| `error`   | `String` | Error message describing the failure reason |

```kotlin
override fun onObjectTrackingFailure(error: String) {
    Log.d(TAG, "Object tracking failure: $error")
}
```

***

## LocalizationResult

| Property         | Type              | Description                                      |
| ---------------- | ----------------- | ------------------------------------------------ |
| `mapCode`        | `String`          | The code of the map where localization succeeded |
| `mapCodes`       | `List<String>`    | All map codes returned by the localization API   |
| `position`       | `FloatArray`      | XYZ position coordinates                         |
| `rotation`       | `FloatArray`      | XYZW quaternion rotation                         |
| `confidence`     | `Float?`          | Confidence score of the localization (0.0 - 1.0) |
| `geoCoordinates` | `GeoCoordinates?` | Optional geographic coordinates                  |

***

## TrackingState

| Value      | Description                       |
| ---------- | --------------------------------- |
| `TRACKING` | AR tracking is working normally   |
| `PAUSED`   | AR tracking is temporarily paused |
| `STOPPED`  | AR tracking has stopped           |

***

## Usage Example

```kotlin
class MainActivity : AppCompatActivity(), MultiSetSDKCallback {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Initialize SDK
        val config = MultiSetSDKConfig.Builder(
            BuildConfig.MULTISET_CLIENT_ID,
            BuildConfig.MULTISET_CLIENT_SECRET
        )
        .mapCode(BuildConfig.MULTISET_MAP_CODE)
        .enableMeshVisualization(true)
        .backgroundLocalization(true)
        .build()

        MultiSetSDK.initialize(this, config, this)
    }

    override fun onAuthenticationSuccess() {
        // Enable localization and object tracking buttons in the UI
    }

    // Launch localization
    fun launchLocalization(mode: LocalizationMode) {
        val intent = Intent(this, MultiSetLocalizationActivity::class.java)
        intent.putExtra(MultiSetLocalizationActivity.EXTRA_LOCALIZATION_MODE, mode.name)
        startActivity(intent)
    }

    // Launch object tracking
    fun launchObjectTracking() {
        val objectCodes = BuildConfig.MULTISET_OBJECT_CODES
            .split(",").map { it.trim() }.filter { it.isNotEmpty() }.toTypedArray()

        ObjectTrackingConfig.objectCodes = objectCodes
        ObjectTrackingConfig.validate()

        val intent = Intent(this, ObjectTrackingActivity::class.java)
        intent.putExtra(ObjectTrackingActivity.EXTRA_OBJECT_CODES, objectCodes)
        startActivity(intent)
    }

    override fun onLocalizationSuccess(result: LocalizationResult) {
        Log.d("MainActivity", "Localized at mapCode: ${result.mapCode}")
    }

    override fun onObjectTrackingSuccess(result: ObjectTrackingResult) {
        Log.d("MainActivity", "Tracked object: ${result.objectCode}")
    }

    override fun onObjectTrackingFailure(error: String) {
        Log.e("MainActivity", "Tracking failed: $error")
    }

    override fun onAuthenticationFailure(error: String) {
        Toast.makeText(this, "Auth failed: $error", Toast.LENGTH_SHORT).show()
    }

    // ... other callback implementations
}
```

***

## Related

* [MultiSetLocalizationActivity](/native-sdk/android-native/sample-activities/multisetlocalizationactivity.md)
* [ObjectTrackingActivity](/native-sdk/android-native/sample-activities/objecttrackingactivity.md)
* [LocalizationConfig](/native-sdk/android-native/api-reference/localizationconfig.md)
* [ObjectTrackingConfig](/native-sdk/android-native/api-reference/objecttrackingconfig.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.multiset.ai/native-sdk/android-native/sample-activities/mainactivity.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
