Appearance
Integrating LIQA into Android app
Below is the guide for integrating LIQA into an Android app using Kotlin language.
WebView with LIQA integrated
Here is a ready-to-use implementation of WebView with integrated LIQA functionality.
Production recommendation
For the simplicity of the guide, WebView loads the HTML page from a string containing the page‘s HTML content.
In a real-world application, you may consider loading the page from a CDN managed by your organization. Check the Hosting the HTML Page section for more details.
kotlin
package ai.haut.liqa
import android.net.Uri
import android.webkit.*
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import org.json.JSONObject
const val HTML = """ PUT THE HTML PAGE CONTENT HERE """
fun LiqaWebView(context: ComponentActivity, onLiqaEvent: (name: String, payload: JSONObject?) -> Unit): WebView {
return WebView(context).apply {
webViewClient = WebViewClient()
webChromeClient = object : WebChromeClient() {
// Grant camera permissions to WebView
override fun onPermissionRequest(request: PermissionRequest) {
request.grant(request.resources)
}
// Handle Upload device photo
override fun onShowFileChooser(
webView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
onFilePicked = filePathCallback
filePicker.launch(fileChooserParams?.createIntent())
return true
}
private var onFilePicked: ValueCallback<Array<Uri>>? = null
private val filePicker = context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val data = result.data?.data
if (data != null)
onFilePicked?.onReceiveValue(arrayOf(data))
}
}
settings.apply {
javaScriptEnabled = true
mediaPlaybackRequiresUserGesture = false
}
// Communication interface between WebView‘s JavaScript and the Native App
addJavascriptInterface(object {
@JavascriptInterface
fun postMessage(message: String) {
val json = JSONObject(message)
val name = json.getString("name")
val payload = if (json.has("payload")) json.getJSONObject("payload") else null
onLiqaEvent(name, payload)
}
}, "NativeApp")
// `https://` is required to get WebView camera working
loadDataWithBaseURL("https://YOUR.DOMAIN.COM", HTML, "text/html", "UTF-8", null)
}
}
package ai.haut.liqa
import android.net.Uri
import android.webkit.*
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import org.json.JSONObject
const val HTML = """ PUT THE HTML PAGE CONTENT HERE """
fun LiqaWebView(context: ComponentActivity, onLiqaEvent: (name: String, payload: JSONObject?) -> Unit): WebView {
return WebView(context).apply {
webViewClient = WebViewClient()
webChromeClient = object : WebChromeClient() {
// Grant camera permissions to WebView
override fun onPermissionRequest(request: PermissionRequest) {
request.grant(request.resources)
}
// Handle Upload device photo
override fun onShowFileChooser(
webView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
onFilePicked = filePathCallback
filePicker.launch(fileChooserParams?.createIntent())
return true
}
private var onFilePicked: ValueCallback<Array<Uri>>? = null
private val filePicker = context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val data = result.data?.data
if (data != null)
onFilePicked?.onReceiveValue(arrayOf(data))
}
}
settings.apply {
javaScriptEnabled = true
mediaPlaybackRequiresUserGesture = false
}
// Communication interface between WebView‘s JavaScript and the Native App
addJavascriptInterface(object {
@JavascriptInterface
fun postMessage(message: String) {
val json = JSONObject(message)
val name = json.getString("name")
val payload = if (json.has("payload")) json.getJSONObject("payload") else null
onLiqaEvent(name, payload)
}
}, "NativeApp")
// `https://` is required to get WebView camera working
loadDataWithBaseURL("https://YOUR.DOMAIN.COM", HTML, "text/html", "UTF-8", null)
}
}
Before integrating the snippet into your app, please, ensure that:
- Content of the HTML Page is inlined into the
HTML
string. WebChromeClient.settings.javaScriptEnabled
is set totrue
.- WebView loads the page over HTTPS.
Application integration example
Here is an app‘s entry point, showcasing a sample integration of LiqaWebView
:
kotlin
package ai.haut.liqa
import android.Manifest
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import org.json.JSONObject
import android.widget.Toast
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val webView = LiqaWebView(this) { name, payload ->
handleLiqaEvent(name, payload)
}
// Request camera permission before loading WebView
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
setContentView(webView)
}.launch(Manifest.permission.CAMERA)
}
// The App‘s business logic for handling LIQA events
private fun handleLiqaEvent(name: String, payload: JSONObject?) {
var text = "LIQA: $name"
payload?.let {
var extars = "$payload"
// Do not overwhelm the log
if (extars.length >= 1024) extars = extars.substring(0, 1024) + "..."
text += "\n$extars"
}
log(text)
}
private fun log(text: String) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
}
}
package ai.haut.liqa
import android.Manifest
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import org.json.JSONObject
import android.widget.Toast
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val webView = LiqaWebView(this) { name, payload ->
handleLiqaEvent(name, payload)
}
// Request camera permission before loading WebView
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
setContentView(webView)
}.launch(Manifest.permission.CAMERA)
}
// The App‘s business logic for handling LIQA events
private fun handleLiqaEvent(name: String, payload: JSONObject?) {
var text = "LIQA: $name"
payload?.let {
var extars = "$payload"
// Do not overwhelm the log
if (extars.length >= 1024) extars = extars.substring(0, 1024) + "..."
text += "\n$extars"
}
log(text)
}
private fun log(text: String) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
}
}
Feel free to adapt the example for your‘s application needs.
Application permissions configuration
Additionally, there is an example of the minimal Android manifest file necessary for LiqaWebView
to function correctly:
xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<application android:label="LIQA WebView integration">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<application android:label="LIQA WebView integration">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Before running your app with LiqaWebView
integrated, please, ensure that:
INTERNET
andCAMERA
user permissions are included in theAndroidManifest.xml
.
Need Assistance?
If you have any questions regarding the integration or need further assistance, please contact Haut.AI Support Team with this request via the Support Desk.