【问题标题】:How to access the camera from within a Webview?如何从 Webview 中访问相机?
【发布时间】:2026-01-16 02:00:01
【问题描述】:

在我的 android 应用程序中,我试图在 WebView 上加载一个网页(必须访问相机)。在我的笔记本电脑上,当我加载网页时,我可以访问相机。

显示html 页面上的所有其他内容。

这是我在Manifest.xml 中输入的权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.webkit.PermissionRequest" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />

我将 SDK 设置如下:

<uses-sdk
    android:minSdkVersion="18"
    android:targetSdkVersion="21" />

这是我的 webview 设置:

private void setMyWebviewSettings(WebSettings MyWebviewSettings) {
    MyWebviewSettings.setAllowFileAccessFromFileURLs(true);
    MyWebviewSettings.setAllowUniversalAccessFromFileURLs(true);
    MyWebviewSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    MyWebviewSettings.setJavaScriptEnabled(true);
    MyWebviewSettings.setDomStorageEnabled(true);
    MyWebviewSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    MyWebviewSettings.setBuiltInZoomControls(true);
    MyWebviewSettings.setAllowFileAccess(true);
    MyWebviewSettings.setSupportZoom(true);
}

如果我可以直接从我的应用程序访问相机(使用正常活动),为什么我不能从WebView 中打开它?!

【问题讨论】:

标签: android webview android-permissions


【解决方案1】:

我也在尝试同样的事情。下面的代码对我有用。

首先在清单文件中,我们必须使用使用权限标签添加相机硬件权限 true。

然后需要接受相机权限才能在您的活动中使用以下行。

webview.setWebChromeClient(new WebChromeClient() {

   @Override
   public void onPermissionRequest(final PermissionRequest request) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
         request.grant(request.getResources());
      }
   }

 });

【讨论】:

    【解决方案2】:

    getUserMedia 通过 WebRTC 这当然是可能的。

    设置您的 WebView 以允许权限并使用 loadUrl() 加载您的 HTML:

        WebView myWebView = (WebView) findViewById(R.id.webview);
    
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.getSettings().setAllowFileAccessFromFileURLs(true);
        myWebView.getSettings().setAllowUniversalAccessFromFileURLs(true);
    
        myWebView.setWebViewClient(new WebViewClient());
        myWebView.setWebChromeClient(new WebChromeClient() {
            // Grant permissions for cam
            @Override
            public void onPermissionRequest(final PermissionRequest request) {
                Log.d(TAG, "onPermissionRequest");
                MainActivity.this.runOnUiThread(new Runnable() {
                    @TargetApi(Build.VERSION_CODES.M)
                    @Override
                    public void run() {
                        Log.d(TAG, request.getOrigin().toString());
                        if(request.getOrigin().toString().equals("file:///")) {
                            Log.d(TAG, "GRANTED");
                            request.grant(request.getResources());
                        } else {
                            Log.d(TAG, "DENIED");
                            request.deny();
                        }
                    }
                });
            }
    
    
        });
    
        myWebView.loadUrl(LOCAL_FILE);
    

    然后通过你的JS文件使用getUserMedia,假设你的HTML文件中有&lt;video&gt;标签:

    var constraints = { video: { width: 800, height: 800 } };
    
    navigator.mediaDevices.getUserMedia(constraints)
    .then(function(mediaStream) {
      var video = document.querySelector('video');
      video.srcObject = mediaStream;
      video.onloadedmetadata = function(e) {
        video.play();
      };
    })
    .catch(function(err) { console.log(err.name + ": " + err.message); }); // always check for errors at the end.
    

    最后,确保您在清单中设置了权限:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    

    【讨论】:

    【解决方案3】:

    这对我有用。我希望它可以帮助某人。

    public class MainActivity extends AppCompatActivity implements 
    EasyPermissions.PermissionCallbacks{
    
    WebView myWebView;
    
    private String TAG = "TEST";
    private PermissionRequest mPermissionRequest;
    
    private static final int REQUEST_CAMERA_PERMISSION = 1;
    private static final String[] PERM_CAMERA =
            {Manifest.permission.CAMERA};
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        myWebView  = new WebView(this);
    
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.getSettings().setAllowFileAccessFromFileURLs(true);
        myWebView.getSettings().setAllowUniversalAccessFromFileURLs(true);
    
        //myWebView.setWebViewClient(new WebViewClient());
        myWebView.setWebChromeClient(new WebChromeClient() {
            // Grant permissions for cam
            @Override
            public void onPermissionRequest(final PermissionRequest request) {
                Log.i(TAG, "onPermissionRequest");
                mPermissionRequest = request;
                final String[] requestedResources = request.getResources();
                for (String r : requestedResources) {
                    if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
                        // In this sample, we only accept video capture request.
                        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this)
                                                            .setTitle("Allow Permission to camera")
                                                            .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
                                                                @Override
                                                                public void onClick(DialogInterface dialog, int which) {
                                                                    dialog.dismiss();
                                                                    mPermissionRequest.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
                                                                    Log.d(TAG,"Granted");
                                                                }
                                                            })
                                                            .setNegativeButton("Deny", new DialogInterface.OnClickListener() {
                                                                @Override
                                                                public void onClick(DialogInterface dialog, int which) {
                                                                    dialog.dismiss();
                                                                    mPermissionRequest.deny();
                                                                    Log.d(TAG,"Denied");
                                                                }
                                                            });
                        AlertDialog alertDialog = alertDialogBuilder.create();
                        alertDialog.show();
    
                        break;
                    }
                }
            }
    
            @Override
            public void onPermissionRequestCanceled(PermissionRequest request) {
                super.onPermissionRequestCanceled(request);
                Toast.makeText(MainActivity.this,"Permission Denied",Toast.LENGTH_SHORT).show();
            }
        });
    
    
        if(hasCameraPermission()){
            myWebView.loadUrl("Your URL");
            setContentView(myWebView );
        }else{
            EasyPermissions.requestPermissions(
                    this,
                    "This app needs access to your camera so you can take pictures.",
                    REQUEST_CAMERA_PERMISSION,
                    PERM_CAMERA);
        }
    
    }
    
    
    
    
    
    private boolean hasCameraPermission() {
        return EasyPermissions.hasPermissions(MainActivity.this, PERM_CAMERA);
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }
    
    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
    
    }
    
    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
    
    }
    }
    

    我正在使用 easypermission 库来获取相机权限,记得在 Android Manifest 中为相机添加使用权限

    【讨论】:

    【解决方案4】:

    根据 meuser07 的回答,这对我有用。除了 Manifest.xml 中的权限外,您还需要在运行时检查/授予权限。

    希望对你有帮助。

                override fun onPermissionRequest(request: PermissionRequest) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (ContextCompat.checkSelfPermission(this@YourActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                                                    RxPermissions(this@YourActivity).request(Manifest.permission.CAMERA).subscribe({
                                if (it) request.grant(request.resources)
                            }, {
                                Timber.e(it, "Error requesting camera")
                            }).addSubscription()
                        } else {
                            request.grant(request.resources)
                        }
                    }
                }
    

    我正在使用RxPermission 授予权限。此外,您需要添加此配置。

    webView.settings.mediaPlaybackRequiresUserGesture = false
    

    【讨论】:

    【解决方案5】:

    如果我没记错的话,您只是想打开您的设备相机并在 web 视图中上传新拍摄的照片而不打开其他应用程序,那么您还需要 WRITE_EXTERNAL_STORAGE 权限以及处理文件请求和使用相机创建新文件的方法和将其写入您的设备存储。

    我希望这会有所帮助,Open Source (Android Smart WebView) 让我们为您进行设置。

    您需要寻找openFileChooser()onShowFileChooser() 方法来了解如何处理来自webview 输入的文件请求并激活您的手机摄像头以在不打开其他应用的情况下捕捉和创建新图像。

    【讨论】: