【问题标题】:Cannot Access Camera from Android 10 Web View无法从 Android 10 Web 视图访问相机
【发布时间】:2020-12-23 03:57:37
【问题描述】:

升级到 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;
        }
    }

我发现了如何从this link 访问相机并将 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 视图。

谁能告诉我我错过了什么?

【问题讨论】:

    标签: android webview android-camera android-10.0


    【解决方案1】:

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

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

    HERE 我们有很好的文档如何处理新旧方式

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

    【讨论】:

    • 您可以选择禁用新的访问方式,但仅适用于 Android 10,从 11 开始需要此支持。为清单中的 标签添加 android:requestLegacyExternalStorage="true"
    • 好吧,确切地说不是……只要应用程序以 10 为目标并且拥有 requestLegacyExternalStorage="true" 一切都可以在 Android 11 及更高版本上运行。另一个问题是 Google Play 强制应用发布/更新仅针对低于当前 2 个版本的版本(好举措!)
    【解决方案2】:

    对于 Android 10,SDK 30

    在清单中为application 标签添加android:requestLegacyExternalStorage="true"

    从 marshmallow 开始,android 需要用户权限才能访问相机和外部存储。没有这些权限,Webview 应用无法发起摄像头上传,所以你必须让用户授予权限,所以这里是如何修复 android Webview 中的摄像头上传。

    在 OnCreate 方法下方添加此代码。

    if(!hasPermissions(this, PERMISSIONS)){
              ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
          }
    

    然后在activity中添加这段代码

    int PERMISSION_ALL = 1;
       String[] PERMISSIONS = {
               
               android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
               android.Manifest.permission.CAMERA
       };
    
       public static boolean hasPermissions(Context context, String... permissions) {
           if (context != null && permissions != null) {
               for (String permission : permissions) {
                   if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                       return false;
                   }
               }
           }
           return true;
       }}
    

    请记住,您还必须在您的 android 清单中声明权限。

    <uses-permission
            android:name="android.permission.WRITE_EXTERNAL_STORAGE"
            tools:ignore="ScopedStorage" />
    <uses-permission android:name="android.permission.CAMERA" />
    

    【讨论】:

      【解决方案3】:

      所有需要添加的是

      else if (mCameraUri != null)
                          {
                          results = new Uri[]{mCameraUri};
                          }
      

      【讨论】:

      • 你能发布解决方案吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多