首页 > 解决方案 > 无法从 Android 10 Web 视图访问相机

问题描述

在升级到 Android 10 时,我一直在我的 Hybrid Android Web View App 中使用 onShowFileChooser 代码,因为 Android 5 或 6 停止提供对相机的访问。用户仍然可以访问存储的照片,但不再向用户提供相机选项。

我一直在使用的代码如下所示

      //For Android 5.0+
    public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
        {
        if(mUMA != null)
            {
            mUMA.onReceiveValue (null);
            }
        mUMA = filePathCallback;
        Intent takePictureIntent = new Intent (MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity (MainActivity.this.getPackageManager()) != null)
            {
            File photoFile = null;
            try
                {
                photoFile = createImageFile();
                takePictureIntent.putExtra("PhotoPath", mCM);
                }
            catch(IOException ex)
                {
                Log.e(TAG, "Image file creation failed", ex);
                }
            if (photoFile != null)
                {
                mCM = "file:" + photoFile.getAbsolutePath();
                takePictureIntent.putExtra (MediaStore.EXTRA_OUTPUT, Uri.fromFile (photoFile));
                }
            else
                {
                takePictureIntent = null;
                }
            }
        Intent contentSelectionIntent = new Intent (Intent.ACTION_GET_CONTENT);
        contentSelectionIntent.addCategory (Intent.CATEGORY_OPENABLE);
        contentSelectionIntent.setType ("image/*");
        Intent[] intentArray;
        if (takePictureIntent != null)
            {
            intentArray = new Intent[] {takePictureIntent};
            }
        else
            {
            intentArray = new Intent[0];
            }

        Intent chooserIntent = new Intent (Intent.ACTION_CHOOSER);
        chooserIntent.putExtra (Intent.EXTRA_INTENT, contentSelectionIntent);
        chooserIntent.putExtra (Intent.EXTRA_TITLE, "Image Chooser");
        chooserIntent.putExtra (Intent.EXTRA_INITIAL_INTENTS, intentArray);
        startActivityForResult (chooserIntent, FileChooserActivityCode);
        return true;
        }

与以下代码一起处理结果

protected void onActivityResult (int requestCode, int resultCode, Intent intent)
    {
    super.onActivityResult(requestCode, resultCode, intent);

    if (requestCode == FileChooserActivityCode)
        {
        Uri[] results = null;
        //Check if response is positive
        if (resultCode == Activity.RESULT_OK)
            {
            if (null == mUMA)
                {
                return;
                }
            if (intent == null || intent.getData() == null)
                {
                //Capture Photo if no image available
                if (mCM != null)
                    {
                    results = new Uri[]{Uri.parse(mCM)};
                    }
                }
            else
                {
                String dataString = intent.getDataString();
                if(dataString != null)
                    {
                    results = new Uri[]{Uri.parse(dataString)};
                    }
                }
            }
        mUMA.onReceiveValue(results);
        mUMA = null;
        }
    }

我发现了如何从此链接访问相机并将 takePictureIntent 代码更改为以下内容:

    if(takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {

    File photoFile = null;
    Uri photoUri = null;

    if (isAndroidQ) {
        // Android Q compatibility
        photoUri = createImageUri();
        mCameraUri = photoUri;
        if (photoUri != null) {
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
        }
    } else {
        try {
            photoFile = createImageFile();
            takePictureIntent.putExtra("PhotoPath", mCM);
        } catch (IOException ex) {
            Log.e(LOG_TAG, "Image file creation failed", ex);
        }
        if (photoFile != null) {
            mCM = "file:" + photoFile.getAbsolutePath();
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
        } else {
            takePictureIntent = null;
        }
    }
}

private Uri createImageUri()
        {
        String status = Environment.getExternalStorageState();
        if (status.equals(Environment.MEDIA_MOUNTED))
            {
            return MainActivity.this.getApplicationContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
            }
        else
            {
            return MainActivity.this.getApplicationContext().getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, new ContentValues());
            }
        }

但是现在在 onActivityResult 代码中拍摄照片后,变量 mCM 为空,并且没有任何内容传递给 Web 视图。

请有人能告诉我我错过了什么吗?

标签: androidwebviewandroid-cameraandroid-10.0

解决方案


如果您的目标是 Android 10 - 此版本引入了一种新的、更安全/私密的方式来访问名为 Scoped Storage 的存储。查看这篇文章以获取更多信息如何实施

对于更复杂的解决方案,您应该展示发生的事情createImageUricreateImageFile方法

在这里,我们有很好的文档如何处理新旧方式

您可以选择禁用新的访问方式,但仅适用于 Android 10,从 11 开始需要此支持。在清单中android:requestLegacyExternalStorage="true"添加标签<application>


推荐阅读