> ## Documentation Index
> Fetch the complete documentation index at: https://docs.molin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Android integration

> Integrate the Molin AI chatbot into your Android app using WebView.

The recommended way to integrate Molin AI in your Android app is by rendering our widget inside a `WebView` component.

See the full working example on GitHub: [molin-ai/molin-ai-android-example](https://github.com/molin-ai/molin-ai-android-example).

## Basic setup

Create an HTML file that loads the widget and displays the chat component fullscreen. Place it at `app/src/main/assets/widget.html`:

```html theme={null}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      html,
      body {
        height: 100%;
        width: 100%;
        overflow: hidden;
        background: #fdfdfd;
      }
      molin-shop-ai-chat {
        display: block;
        width: 100%;
        height: 100%;
      }
    </style>
    <script src="https://widget.molin.ai/shop-ai.js"></script>
  </head>
  <body>
    <molin-shop-ai-chat show-close widget="YOUR_WIDGET_ID"></molin-shop-ai-chat>
  </body>
</html>
```

Replace `YOUR_WIDGET_ID` with your actual widget ID from the Molin dashboard.

The `show-close` attribute is optional. It renders a close button (✕) in the chat header, which is useful when the widget is displayed fullscreen in a webview. You can omit it if your app has its own navigation to dismiss the chat.

## Loading the WebView

Create a layout with a fullscreen `WebView` (`res/layout/activity_main.xml`):

```xml theme={null}
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

Then load the HTML file in your activity:

```kotlin theme={null}
import android.annotation.SuppressLint
import android.os.Bundle
import android.webkit.WebView
import android.webkit.WebViewClient
import android.webkit.WebSettings
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        supportActionBar?.hide()
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val webView: WebView = findViewById(R.id.webView)

        webView.settings.javaScriptEnabled = true
        webView.settings.domStorageEnabled = true
        webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
        @SuppressLint("AllowUniversalAccessFromFileURLs")
        webView.settings.allowUniversalAccessFromFileURLs = true

        webView.webViewClient = WebViewClient()
        webView.loadUrl("file:///android_asset/widget.html")
    }
}
```

## Handling the close button

When the user taps the close button, the `<molin-shop-ai-chat>` element fires a `molin-shop-ai-chat:close-click` event. Navigate to a custom `molin://` URL to tell the native side to go back:

```html theme={null}
<script>
  document.addEventListener('molin-shop-ai-chat:close-click', function () {
    window.location.href = 'molin://close';
  });
</script>
```

On the Kotlin side, intercept the `molin://` scheme in a `WebViewClient`:

```kotlin theme={null}
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView?,
        request: WebResourceRequest?
    ): Boolean {
        val url = request?.url ?: return false
        if (url.scheme == "molin") {
            if (url.host == "close") {
                finish()
            }
            return true
        }
        return false
    }
}
```
