5

Android 10,11 调用系统相机错误:Failed to find configured root that contains dat...

 2 years ago
source link: http://i.lckiss.com/?p=7427
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Android 10,11 调用系统相机错误:Failed to find configured root that contains data.

2021-08-19

做H5界面拍照功能遇到的错误:

java.lang.IllegalArgumentException: Failed to find configured root that contains your_file

网上的说法都很旧,大多数是说 FileProvider 配置错误而这里并不是,查看逻辑后发现,之前未适配 Android 10,11 ,所以使用的是 FileProvider.getUriForFile 获取到的URI,然后传递给系统相机即可,但目前新版本并不允许这样做,正确的做法如下:

先根据不同的 Android 版本生成不同的URI:

    val uploadUri:Uri

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val values = ContentValues()
        values.put(MediaStore.Images.Media.DISPLAY_NAME, "pic.jpg")
        values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM)
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
        uploadUri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
    } else {
        val authority: String = context.getPackageName().toString() + ".fileprovider"
        val file = File(context.getCacheDir().toString() + "/pic.jpg")
        uploadUri = FileProvider.getUriForFile(context, authority, file)
    }

然后使用该 URI 作为相机拍照后输出的路径:

    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    intent.putExtra("return-data", true)
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uploadUri)
    intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
    startActivityForResult(intent, REQUEST_CODE_UPLOAD_IMAGE)

最后在拍照回调里先判断 intent.getData() 是否为空(大概率是为空),为空时直接用 uploadUri 即可。

可以发现整体逻辑变了:

Android 7.0 以下 :自行指定一个私有目录或者其他目录URI,然后传递给系统相机,系统相机获取到权限就可以随意写。

Android 10 及以上:需要先显示在系统中定义一个 URI,先报备再传递给系统相机进行操作,而且目录必须为公用目录(DCIM,Pictures)。

对于 Android 7.0以上的版本只要用 FileProvider 授权就行,Android 7.0以下的版本,随便怎么玩,但在Android 10以上,是不被允许的,同时对于相机的调用,输出目录只能用 DCIM, 以及 Pictures 目录,不信可以将上面的 Environment.DIRECTORY_DCIM 改成其他目录,看看报错就知道了(因为系统应用也没权限写我们应用的私有目录,其他目录我们又没有权限去读取)。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK