Mobile Widget SDKs

# Android

Use the native Android SDK with an existing View hierarchy or Jetpack Compose application.

[Core package](https://central.sonatype.com/artifact/ai.returning/returningai-widget/0.1.0) [Compose package](https://central.sonatype.com/artifact/ai.returning/returningai-widget-compose/0.1.0)

## Requirements

- Android minSdk 24, compile/target SDK 36, and JVM 17.
- An Android System WebView that supports `WEB_MESSAGE_LISTENER`.
- An HTTPS client origin allowlisted for the target widget.
- A trusted backend that returns freshly minted embed tokens.

## Install from Maven Central

Add the core artifact for Views. Add the Compose artifact when the host uses Jetpack Compose.

`build.gradle.kts`

```kotlin
repositories {
    google()
    mavenCentral()
}

dependencies {
    implementation("ai.returning:returningai-widget:0.1.0")
    implementation("ai.returning:returningai-widget-compose:0.1.0")
}
```

The AAR does not add internet permission to the host application. Add it to the app manifest.

`AndroidManifest.xml`

```xml
<uses-permission android:name="android.permission.INTERNET" />
```

> The secure bridge fails closed
>
> The SDK uses AndroidX WebKit's message listener. It does not fall back to `addJavascriptInterface`. Update the device System WebView when the required capability is unavailable.

## Jetpack Compose

Configure the supplied custom widget and let the token provider call your backend. The provider must not contain Returning.AI access credentials.

`RewardsScreen.kt`

```kotlin
val configuration = ReturningAIWidgetConfiguration.customBundle(
    widgetId = "YOUR_SUPPLIED_WIDGET_ID",
    bundleUrl = URI.create("YOUR_SUPPLIED_BUNDLE_URL"),
    clientOrigin = URI.create("https://mobile-client.example"),
    runtimeUrl = URI.create(
        "https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js",
    ),
)

ReturningAIWidget(
    configuration = configuration,
    embedTokenProvider = {
        backend.fetchReturningAIEmbedToken()
    },
    onExternalNavigation = { uri ->
        appRouter.openExternal(uri)
    },
)
```

## Android View

The core artifact exposes `ReturningAIWidgetView`. Dispose the view when its host screen is destroyed.

`RewardsFragment.kt`

```kotlin
val widgetView = ReturningAIWidgetView(
    context = context,
    configuration = configuration,
    embedTokenProvider = {
        backend.fetchReturningAIEmbedToken()
    },
)

container.addView(widgetView)

// When the host screen is destroyed:
widgetView.dispose()
```

## Session lifecycle

- Use `ReturningAIWidgetController.invalidate()` for session invalidation.
- Do not confuse controller invalidation with Android `View.invalidate()`.
- Open delegated HTTPS navigation through the host application.
- On account change, dispose and remove the old View. In Compose, replace the keyed subtree so disposal runs before mounting the new user.

Return to the [Mobile Widget SDK overview](https://docs.returning.ai/mobile-widget-sdk.md).
