Native Android (Kotlin)
Integrate FaceGuard into native Android apps using WebView.
Setup
Add camera permission to AndroidManifest.xml:
AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
Implementation
FaceGuardActivity.kt
class FaceGuardActivity : AppCompatActivity() {
private lateinit var webView: WebView
fun startVerification(token: String) {
webView = findViewById(R.id.webview)
webView.settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
mediaPlaybackRequiresUserGesture = false
}
// Camera permission
webView.webChromeClient = object : WebChromeClient() {
override fun onPermissionRequest(request: PermissionRequest) {
if (request.resources.contains(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(request.resources)
}
}
}
// Listen for postMessage
webView.addJavascriptInterface(object {
@JavascriptInterface
fun onMessage(json: String) {
val data = JSONObject(json)
if (data.optString("action") == "close") {
val reason = data.optString("reason")
val confidence = data.optDouble("confidence", 0.0)
runOnUiThread {
when (reason) {
"approved", "bypass_active" -> handleApproved(confidence)
"rejected" -> handleRejected(confidence)
"canceled" -> handleCanceled()
"error", "no_base_photo" ->
handleError(data.optString("error", reason))
}
}
}
}
}, "SurtBridge")
// Inject bridge script
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
view.evaluateJavascript("""
window.addEventListener('message', function(e) {
if (e.data && (e.data.type === 'surt:ready' || e.data.action === 'close')) {
SurtBridge.onMessage(JSON.stringify(e.data));
}
});
""", null)
}
}
webView.loadUrl("https://faceguard.surt.com/intro?token=$token")
}
fun handleApproved(confidence: Double) { /* Grant access */ }
fun handleRejected(confidence: Double) { /* Deny access */ }
fun handleCanceled() { /* User closed */ }
fun handleError(message: String) { /* Show error */ }
}
How the Bridge Works
Android WebView doesn't natively receive postMessage events. The @JavascriptInterface method and injected bridge script forward events from the FaceGuard iframe to native Kotlin code.
Camera Permission
Both the manifest permission (CAMERA) and the onPermissionRequest handler are required. The manifest declares the permission, and the handler grants it to the WebView at runtime.