From 7a957e856e2b280b875cb061a6c8fa029a0b59f2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 11 Apr 2026 03:37:45 +0200 Subject: [PATCH] Fix WebView mic: grant both Android runtime + WebView permissions The WebView has its own permission layer separate from Android runtime permissions. Both must be granted. Now when the web page requests mic access, the WebChromeClient checks if Android permission exists, grants the WebView request if yes, or requests Android permission first then grants the pending WebView request in the callback. --- .../java/com/pedshub/scribe/MainActivity.java | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/mobile/android/app/src/main/java/com/pedshub/scribe/MainActivity.java b/mobile/android/app/src/main/java/com/pedshub/scribe/MainActivity.java index aa5b1d7..234ee2a 100644 --- a/mobile/android/app/src/main/java/com/pedshub/scribe/MainActivity.java +++ b/mobile/android/app/src/main/java/com/pedshub/scribe/MainActivity.java @@ -4,7 +4,10 @@ import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import android.webkit.PermissionRequest; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -13,22 +16,63 @@ import com.getcapacitor.BridgeActivity; public class MainActivity extends BridgeActivity { private static final int MIC_PERMISSION_CODE = 1001; + private PermissionRequest pendingPermissionRequest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Request microphone permission at app start (not just when WebView asks) + // Request mic permission upfront if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.RECORD_AUDIO }, MIC_PERMISSION_CODE); } + + // Override WebView to handle permission requests from the web page + WebView webView = this.bridge.getWebView(); + final MainActivity activity = this; + + webView.setWebChromeClient(new WebChromeClient() { + @Override + public void onPermissionRequest(final PermissionRequest request) { + // Check if we already have the Android permission + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) + == PackageManager.PERMISSION_GRANTED) { + // Grant the WebView permission + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + request.grant(request.getResources()); + } + }); + } else { + // Save the request and ask for Android permission + pendingPermissionRequest = request; + ActivityCompat.requestPermissions(activity, + new String[]{ Manifest.permission.RECORD_AUDIO }, MIC_PERMISSION_CODE); + } + } + }); } @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); - // Capacitor handles the result via its bridge + + if (requestCode == MIC_PERMISSION_CODE && pendingPermissionRequest != null) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + final PermissionRequest req = pendingPermissionRequest; + runOnUiThread(new Runnable() { + @Override + public void run() { + req.grant(req.getResources()); + } + }); + } else { + pendingPermissionRequest.deny(); + } + pendingPermissionRequest = null; + } } }