Integration for Android
Documentation
This guide explains how to embed our Smart Assistant chatbot in your Android app using a WebView. The integration consists of two parts:
- An HTML page that loads the Smart Assistant web component.
- An Android screen that hosts the
WebViewand bridges native ↔ JavaScript communication (e.g. to close the assistant).
1. Create the HTML page
Add an HTML file that loads our launcher.js script and declares the <smart-assistant> web component. You can place it either as a local asset inside your app (app/src/main/assets/smart_assistant.html) or host it on a remote URL.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Smart Assistant</title>
<script src="https://sa-media.usizy.es/smart-assistant/launcher.js"></script>
</head>
<body>
<smart-assistant language="en" api-key="YOUR_API_KEY" opened hide-minimize></smart-assistant>
<script>
document.addEventListener('DOMContentLoaded', function () {
const sa = document.querySelector('smart-assistant')
// Listen for the event that the component emits when it closes.
sa.addEventListener('close', function () {
if (window.Android) {
window.Android.close() // triggers onBack() on Android
}
})
})
</script>
</body>
</html>
2. Recommended attributes of :
| Attribute | Description |
|---|---|
| language | Interface language (e.g. en, es). |
| api-key | Your API key. Replace YOUR_API_KEY with the key provided by usizy. |
| opened | Opens the assistant automatically when the page loads. |
| hide-minimize | Hides the minimize button (recommended for full-screen WebView usage). |
The close event listener is essential: it calls window.Android.close(), which is the JavaScript bridge that lets the web component close the native Android screen.
3. Create the Android screen (Jetpack Compose)
The following example uses Jetpack Compose. It wraps a native WebView inside an AndroidView, configures the required settings, and exposes a JavaScript bridge (window.Android) so the web component can trigger native navigation.
package com.yourcompany.yourapp.ui.screens
import android.os.Handler
import android.os.Looper
import android.webkit.ConsoleMessage
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
// Bridge exposed to JavaScript as window.Android
private class AndroidBridge(private val onClose: () -> Unit) {
@JavascriptInterface
fun close() {
// JavascriptInterface is called on a background thread → dispatch to main
Handler(Looper.getMainLooper()).post { onClose() }
}
}
// Choose the source for the Smart Assistant page.
// Option A – local asset (default): "file:///android_asset/smart_assistant.html"
// Option B – remote URL: "https://your-host.example.com/smart-assistant"
private const val SMART_ASSISTANT_SOURCE = "file:///android_asset/smart_assistant.html"
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SmartAssistantScreen(onBack: () -> Unit) {
var pageTitle by remember { mutableStateOf("Smart Assistant") }
Scaffold(
topBar = {
TopAppBar(
title = { Text(pageTitle) },
navigationIcon = {
IconButton(onClick = onBack) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary,
),
)
},
) { paddingValues ->
AndroidView(
factory = { context ->
// Enable remote debugging via chrome://inspect
WebView.setWebContentsDebuggingEnabled(true)
WebView(context).apply {
settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
cacheMode = WebSettings.LOAD_DEFAULT
allowFileAccess = true
allowContentAccess = true
mediaPlaybackRequiresUserGesture = false
}
webChromeClient = object : WebChromeClient() {
override fun onReceivedTitle(view: WebView?, title: String?) {
if (!title.isNullOrBlank() && title != "about:blank") {
pageTitle = title
}
}
// Forward JS console logs to Logcat (tag: SmartAssistant)
override fun onConsoleMessage(msg: ConsoleMessage): Boolean {
val level = when (msg.messageLevel()) {
ConsoleMessage.MessageLevel.ERROR -> "ERROR"
ConsoleMessage.MessageLevel.WARNING -> "WARN"
else -> "LOG"
}
android.util.Log.d(
"SmartAssistant",
"[$level] ${msg.message()} — ${msg.sourceId()}:${msg.lineNumber()}"
)
return true
}
}
// Expose window.Android to the page's JavaScript
addJavascriptInterface(AndroidBridge(onBack), "Android")
webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?,
) = false
// Log resource load failures (JS, etc.) to Logcat
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: android.webkit.WebResourceError?,
) {
android.util.Log.e(
"SmartAssistant",
"Resource error [${error?.errorCode}] ${error?.description} — ${request?.url}"
)
}
}
loadUrl(SMART_ASSISTANT_SOURCE)
}
},
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
)
}
}
4. Key configuration explained
WebView settings
These WebSettings are required for the Smart Assistant to work correctly:
| Setting | Why it is needed |
|---|---|
| javaScriptEnabled = true | The web component is built with JavaScript and won’t run without it. |
| domStorageEnabled = true | Enables localStorage/sessionStorage used by the assistant. |
| mixedContentMode = …ALWAYS_ALLOW | Allows loading remote HTTPS resources from a local file:// page. |
| allowFileAccess = true | Required when loading the HTML from a local asset. |
| mediaPlaybackRequiresUserGesture | Set to false to allow audio/video playback inside the assistant. |
JavaScript bridge (window.Android)
The AndroidBridge class exposes a native close() method to JavaScript via addJavascriptInterface(…, “Android”). When the user closes the assistant, the web component emits a close event, the HTML calls window.Android.close(), and the bridge invokes your onBack() callback on the main thread to close the screen. Note: @JavascriptInterface methods run on a background thread, so any UI work (like navigation) must be dispatched to the main thread, as shown with Handler(Looper.getMainLooper()).
5. Use the screen in your navigation
Add the screen to your navigation graph and provide the onBack callback:
composable("smart_assistant") {
SmartAssistantScreen(onBack = { navController.popBackStack() })
}
6. Required permissions
Make sure your app has internet access in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
Sample App
Check our sample app for Android