/** * Sample Android WebView setup for Gletra calls (mic/camera). * Copy into your Android app and adjust package name / URL. */ package com.gletra.app.sample import android.Manifest import android.annotation.SuppressLint import android.content.pm.PackageManager import android.os.Build import android.webkit.JavascriptInterface import android.webkit.PermissionRequest import android.webkit.WebChromeClient import android.webkit.WebView import android.webkit.WebViewClient import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat class GletraCallWebViewHelper( private val activity: AppCompatActivity, private val webView: WebView, ) { private var pendingJsCallbackId: String? = null private val permissionLauncher = activity.registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions(), ) { results -> val granted = results.values.all { it } val id = pendingJsCallbackId pendingJsCallbackId = null if (id != null) { val js = "window.gletraNativePermissionCallback('$id', ${granted}, '${if (granted) "" else "Permission denied"}');" webView.evaluateJavascript(js, null) } } @SuppressLint("SetJavaScriptEnabled") fun configure(baseUrl: String) { webView.settings.apply { javaScriptEnabled = true domStorageEnabled = true mediaPlaybackRequiresUserGesture = false allowFileAccess = false } webView.webViewClient = WebViewClient() webView.webChromeClient = object : WebChromeClient() { override fun onPermissionRequest(request: PermissionRequest) { activity.runOnUiThread { request.grant(request.resources) } } } webView.addJavascriptInterface(GletraAndroidBridge(), "GletraAndroid") webView.loadUrl(baseUrl) } inner class GletraAndroidBridge { @JavascriptInterface fun isWebView(): Boolean = true @JavascriptInterface fun onWebViewReady() { // Optional native hook } @JavascriptInterface fun hasCallPermissions(audio: Boolean, video: Boolean): Boolean { val needed = mutableListOf() if (audio) needed += Manifest.permission.RECORD_AUDIO if (video) needed += Manifest.permission.CAMERA return needed.all { ContextCompat.checkSelfPermission(activity, it) == PackageManager.PERMISSION_GRANTED } } @JavascriptInterface fun requestCallPermissions(audio: Boolean, video: Boolean, callbackId: String) { activity.runOnUiThread { pendingJsCallbackId = callbackId val perms = mutableListOf() if (audio) perms += Manifest.permission.RECORD_AUDIO if (video) perms += Manifest.permission.CAMERA if (Build.VERSION.SDK_INT >= 33) { perms += Manifest.permission.POST_NOTIFICATIONS } permissionLauncher.launch(perms.toTypedArray()) } } } } /* AndroidManifest.xml permissions: */