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.
This commit is contained in:
Daniel 2026-04-11 03:37:45 +02:00
parent f03ca5cb94
commit 7a957e856e

View file

@ -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;
}
}
}