You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android WebView调用相机权限适配异常求助(Android 6升级后)

Hey there, let's dig into this issue and figure out what's going wrong, plus how to fix it!

Why this is happening on Android 6+

Android 6.0 (API 23) introduced runtime permission requests for "dangerous" permissions like camera and storage—something older Android versions handled automatically at install time. When you swapped the native <input> click behavior for a Java callback, you took on the responsibility of managing these permissions properly, and it sounds like that flow has a gap right now.

Common missteps that cause this issue:

  • You're not fully completing the permission request flow (e.g., asking for permissions but not waiting for the user's response before trying to launch the camera/file picker)
  • You're requesting the wrong permissions, or forgetting to declare them in your manifest
  • After the user grants permissions, you're not re-triggering the original <input> click that launches the system's picker/camera
  • Your WebView's WebChromeClient isn't properly handling the file chooser callback (required for Android 5+ WebView file selection)

Step-by-step fixes

1. Declare required permissions in your AndroidManifest.xml

First, make sure you've listed the permissions your app needs:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- For Android 10+, add this if needed -->
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />

2. Fix the permission request flow in your Java code

Instead of replacing the <input> entirely, use your Java callback to handle permissions first, then trigger the original <input> click once permissions are granted. Here's a concrete example:

// Define a request code for permission checks
private static final int REQUEST_IMAGE_PERMISSIONS = 1001;
private WebView mWebView;

// This is the method your HTML click event calls via @JavascriptInterface
@JavascriptInterface
public void triggerImagePicker() {
    // Check if we already have the required permissions
    boolean hasCameraPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
    boolean hasStoragePerm = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;

    if (hasCameraPerm && hasStoragePerm) {
        // Permissions are good—trigger the hidden input's click
        mWebView.loadUrl("javascript:document.getElementById('InputImgFileDialog').click()");
    } else {
        // Request missing permissions
        String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE};
        ActivityCompat.requestPermissions(this, permissions, REQUEST_IMAGE_PERMISSIONS);
    }
}

// Handle the permission request result
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_IMAGE_PERMISSIONS) {
        boolean allPermissionsGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allPermissionsGranted = false;
                break;
            }
        }

        if (allPermissionsGranted) {
            // User said yes—launch the picker
            mWebView.loadUrl("javascript:document.getElementById('InputImgFileDialog').click()");
        } else {
            // User denied permissions—show a helpful message
            Toast.makeText(this, "We need camera and storage permissions to select photos", Toast.LENGTH_SHORT).show();
        }
    }
}

3. Ensure your WebChromeClient handles file selection

Android 5+ WebViews require you to implement onShowFileChooser in your WebChromeClient to properly handle file picker triggers. Add this to your WebView setup:

mWebView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        // If you're relying on the native <input> behavior, you can use the default implementation
        // Or customize it here if you need more control over the picker
        return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
    }
});

4. Test edge cases

  • Make sure you handle the scenario where the user denies permissions and checks "Don't ask again"—you'll need to redirect them to app settings to enable permissions manually.
  • Verify that the <input> tag's capture="camera" attribute still works as expected once permissions are granted (it should launch the camera directly if the device supports it).

Quick recap

The core issue is that Android 6+ requires explicit runtime permission checks, which the native <input> handled automatically in older versions. By adding the permission request flow in your Java callback and re-triggering the original <input> click after approval, you'll restore the expected behavior while complying with Android's security rules.

内容的提问来源于stack exchange,提问作者Steve Brooker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:28:43