> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ada.cx/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ada.cx/_mcp/server.

# Getting started

The Ada Android SDK is a Kotlin library that you can use to embed your Ada AI Agent into your native Android application.

It also supports actions and settings that you can use to customize the behavior of your AI Agent. For example, you might want to set the language, or pass metadata. The [Android SDK reference](/messaging/android/sdk-api-reference) covers these options and more.

> **Note**
>
> You'll need an active Ada AI Agent handle and access to the Ada Dashboard to use the SDK. To gain access, please reach out to an Ada Account Manager.

> **Note**
>
> This guide covers the new Ada Android SDK. If you are migrating from the existing SDK (`support.ada.embed.*`), see [Upgrade from the existing Android SDK](#upgrade-from-the-existing-android-sdk) below.

## Compatibility

| Requirement            | Minimum Version       |
| ---------------------- | --------------------- |
| Android                | 6.0 (API level 23)    |
| Android System WebView | 99 or later           |
| App framework          | AndroidX              |
| Kotlin toolchain       | Kotlin 2.2-compatible |
| JDK                    | 17                    |

Android System WebView updates separately from the operating system through the Play Store app **Android System WebView**. Android System WebView versions earlier than 99 are not supported.

The published artifact is compiled with Kotlin `2.2.20` metadata. If your app is pinned to an older Kotlin compiler, upgrade that toolchain before integrating the SDK.

## Install the Android SDK

Install the SDK from Maven Central. Add the dependency to your app-level `build.gradle` file:

**`build.gradle`**

```groovy build.gradle
dependencies {
    implementation "cx.ada:messaging-android:<version>"
}
```

Replace `<version>` with the latest version on [Maven Central](https://central.sonatype.com/artifact/cx.ada/messaging-android).

You only need this one artifact. It contains the embedded view, the full-screen activity, and the dialog. Older install guides that mention multiple Ada Android artifacts do not apply to this SDK.

> **Note**
>
> Make sure your project's `build.gradle` file includes `mavenCentral()` in the repositories block:
>
> ```groovy build.gradle
> repositories {
>     mavenCentral()
> }
> ```

After adding the dependency, synchronize your project.

## Launch Ada

The SDK provides three integration surfaces. All three ship in the same artifact.

| Surface                | Use when                                                  |
| ---------------------- | --------------------------------------------------------- |
| `AdaMessagingView`     | You want to place the conversation inside your own layout |
| `AdaMessagingActivity` | You want a full-screen conversation with minimal setup    |
| `AdaMessagingDialog`   | You want the conversation in a dialog-style presentation  |

### XML

The simplest way to start is via XML. Replace `my-handle` with the handle for your AI Agent.

**`XML`**

```xml XML
<cx.ada.messaging.widget.AdaMessagingView
    android:id="@+id/ada_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:ada_handle="my-handle"
    app:ada_language="en" />
```

The `ada_handle` attribute is required to display the view. If you specify it as an attribute, the conversation loads when the view attaches to its parent. If you don't specify it, initialize the view later with `initialize(settings: AdaMessagingView.Settings)`:

**`Kotlin`**

```kotlin Kotlin
val adaView = findViewById<AdaMessagingView>(R.id.ada_view)

val settings = AdaMessagingView.Settings.Builder("my-handle")
    .build()
adaView.initialize(settings)
```

### Programmatically

To create the view in code, pass a context to the constructor, then initialize it with a settings object:

**`Kotlin`**

```kotlin Kotlin
import cx.ada.messaging.widget.AdaMessagingView

val adaView = AdaMessagingView(context)

val settings = AdaMessagingView.Settings.Builder("my-handle")
    .language("en")
    .metaFields(
        AdaMessagingView.MetaFields.Builder()
            .setField("plan", "pro")
            .setField("signedIn", true),
    )
    .build()
adaView.initialize(settings)
```

Finally, add the view to your container to display it.

> **Note**
>
> Most apps only need `handle`. Leave `cluster` unset unless Ada tells you your AI Agent is hosted on a non-default cluster.

### Activity

Use `AdaMessagingActivity` to open the conversation in a separate, full-screen window. Create an `Intent`, put the settings in it with the key `AdaMessagingActivity.EXTRA_SETTINGS`, then start the activity:

**`Kotlin`**

```kotlin Kotlin
import android.content.Intent
import cx.ada.messaging.ui.AdaMessagingActivity
import cx.ada.messaging.widget.AdaMessagingView

val settings = AdaMessagingView.Settings.Builder("my-handle")
    .build()

startActivity(
    Intent(context, AdaMessagingActivity::class.java)
        .putExtra(AdaMessagingActivity.EXTRA_SETTINGS, settings),
)
```

You can subclass `AdaMessagingActivity` like a regular Android activity. Call `getAdaView()` from your subclass to access the underlying `AdaMessagingView`.

### Dialog

Use `AdaMessagingDialog` to display the conversation on top of the current window. Pass the settings through the fragment arguments with the key `AdaMessagingDialog.ARGUMENT_SETTINGS`:

**`Kotlin`**

```kotlin Kotlin
import cx.ada.messaging.ui.AdaMessagingDialog

val dialog = AdaMessagingDialog()
dialog.arguments = Bundle().apply {
    putParcelable(AdaMessagingDialog.ARGUMENT_SETTINGS, settings)
}
dialog.show(supportFragmentManager, AdaMessagingDialog.TAG)
```

## Choose a runtime

The SDK can load two web runtimes inside its WebView:

* **Legacy** preserves the behavior of Ada's existing Chat SDK. This is the default, and it remains fully supported.
* **Messaging** is Ada's next-generation runtime. Features such as [headless mode](/messaging/android/sdk-api-reference#headless-mode), [identityToken](/messaging/android/sdk-api-reference#identitytoken), and [sendMessage](/messaging/android/sdk-api-reference#sendmessage) require it.

Opt into the Messaging runtime explicitly:

**`Kotlin`**

```kotlin Kotlin
import cx.ada.messaging.AdaWebSdk

val settings = AdaMessagingView.Settings.Builder("my-handle")
    .webSdk(AdaWebSdk.Messaging)
    .build()
```

If you do nothing, the SDK stays on the Legacy runtime. That keeps a package upgrade free of end-user-visible conversation changes.

## Runtime commands

Once the view is initialized, you can interact with it at runtime:

**`Kotlin`**

```kotlin Kotlin
adaView.setLanguage("fr")

adaView.setMetaFields(
    AdaMessagingView.MetaFields.Builder()
        .setField("plan", "pro"),
)

adaView.setSensitiveMetaFields(
    AdaMessagingView.MetaFields.Builder()
        .setField("authToken", "secure-session-token"),
)

adaView.setDeviceToken("fcm-device-token")

adaView.addEventCallback { event ->
    Log.d("Ada", "event=${event.eventName}")
}

adaView.reset()
adaView.deleteHistory()
```

See the [Android SDK reference](/messaging/android/sdk-api-reference#actions) for the full list of actions.

## File uploads

`AdaMessagingActivity` and `AdaMessagingDialog` handle file selection for you. They open the system chooser. When the chat asks for images, the chooser also offers the camera.

If you embed `AdaMessagingView` directly, set `filePickerCallback`. The callback carries the page's request (`acceptTypes`, `isCaptureEnabled`, `allowMultiple`) and can build the chooser for you:

**`Kotlin`**

```kotlin Kotlin
private var pendingFileRequest: AdaMessagingView.FilePickerCallback? = null

private val filePicker =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        pendingFileRequest?.onChooserResult(result.resultCode, result.data)
        pendingFileRequest = null
    }

adaView.filePickerCallback = { request ->
    pendingFileRequest = request
    try {
        filePicker.launch(request.createChooserIntent(this))
    } catch (e: ActivityNotFoundException) {
        request.onFileTaken(null)
        pendingFileRequest = null
    }
    true
}

override fun onDestroy() {
    super.onDestroy()
    pendingFileRequest?.onFileTaken(null)
    pendingFileRequest = null
}
```

Return `true` to tell the SDK that your app handles the picker. Resolve each request once. The chat ignores later file picks while a request is open, so resolve it when the launch fails and when your Activity is destroyed.

To use your own picker, call `onFilesTaken(uris)` or `onFileTaken(uri)` with the result. To cancel, call `onFileTaken(null)` or `onFilesTaken(emptyList())`.

### Camera permission

You do not need a camera permission. The camera app takes the photo. If your app declares `android.permission.CAMERA` for another feature, Android lets the camera open only after the end user grants that permission. Until then, the chooser does not show the camera.

## Upgrade from the existing Android SDK

If you are migrating from the existing Ada Android SDK, the lowest-risk path is:

1. Replace the old Ada Android dependencies with the single `cx.ada:messaging-android` artifact.
2. Rename imports and XML tags from the old `support.ada.embed.*` namespace to `cx.ada.messaging.*`.
3. Keep the runtime on the default Legacy path first.
4. Move to the Messaging runtime later, as a separate, deliberate step.

This gives you a package upgrade with no end-user-visible conversation change on day one.

### Side-by-side mapping

| Existing                                                                         | Messaging SDK                              |
| -------------------------------------------------------------------------------- | ------------------------------------------ |
| `android-sdk`, `android-sdk-appcompat`, `android-sdk-appcompat-legacy` artifacts | One artifact: `cx.ada:messaging-android`   |
| `support.ada.embed.widget.AdaEmbedView`                                          | `cx.ada.messaging.widget.AdaMessagingView` |
| `support.ada.embed.ui.AdaEmbedActivity`                                          | `cx.ada.messaging.ui.AdaMessagingActivity` |
| `support.ada.embed.ui.AdaEmbedDialog`                                            | `cx.ada.messaging.ui.AdaMessagingDialog`   |

### Before / after: imports

**`Kotlin`**

```kotlin Kotlin
// Before
import support.ada.embed.widget.AdaEmbedView

// After
import cx.ada.messaging.widget.AdaMessagingView
```

### Before / after: XML tag

**`XML`**

```xml XML
<!-- Before -->
<support.ada.embed.widget.AdaEmbedView ... />

<!-- After -->
<cx.ada.messaging.widget.AdaMessagingView ... />
```

### Compatibility notes

* The old `support.ada.embed.*` classes do not compile against the new artifact. Import renames are required.
* `greeting` is the preferred setter and XML attribute name. The older plural forms `greetings` and `app:ada_greetings` are still accepted as compatibility aliases.
* Zero-argument `reset()` calls compile cleanly on both the view and the dialog.
* `Settings.Builder.sensitiveMetaFields(...)` is supported at initialization time, and `setSensitiveMetaFields(...)` remains available for runtime updates.
* Deprecated `Map<String, String>` overloads still exist for migration compatibility. Use `MetaFields.Builder` for all new code.

## Release checklist

Before shipping your integration or migration to production:

* Verify your real production handle launches successfully
* Test the exact surface you ship (embedded view, activity, or dialog)
* Confirm your logging or analytics layer still receives SDK events
* Test device token storage in the end user's sensitive metadata. See [Push notifications](/docs/channels/messaging/push-notifications) for webhook delivery.
* Test `reset()` and `deleteHistory()` if your app exposes those actions
* Test uploads and downloads if your AI Agent uses them
* Test app background and foreground transitions, and process recreation
* Verify your consumer build uses a Kotlin 2.2-compatible Android toolchain