java.lang.RuntimeException: 未能传递结果 ResultInfo{who=null,request=1,result=-1,data=Intent{dat=file:///storage/0EE6-4002/Mete/test.jpg}}

问题描述

我正在通过应用程序从存储中获取图片。通常,来自 onActivityResult 中的数据的 uri 不为 null,并且图片以“content://”开头。但是有些应用程序为我提供了以“file://”开头的同一张图片的uri。 Glide 也不适用于 "file://" uri。所以我想从 FileProvider 获取 uri。当我将此 uri 提供给 FileProvider 时,我收到此错误

2021-01-10 19:01:55.453 30049-30049/com.example.photoselector E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.photoselector,PID: 30049
    java.lang.RuntimeException: Failure delivering result ResultInfo{who=null,request=1,result=-1,data=Intent { dat=file:///storage/0EE6-4002/Mete/IMG_20210108_120951.jpg typ=image/jpeg flg=0x3 }} 
to activity {com.example.photoselector/com.example.photoselector.MainActivity}: java.lang.IllegalArgumentException: Failed to find configured root that contains /file:/storage/0EE6-4002/Mete/IMG_20210108_120951.jpg

同一张图片uri带有“content://”没有问题,当带有来自另一个应用程序的“file://”时,我得到一个错误

我通过此代码创建意图:

private fun initData() {
        button_storage.setonClickListener {
            val intent = Intent()
            intent.type = "image/*"
            intent.action = Intent.ACTION_GET_CONTENT
            startActivityForResult(
                Intent.createChooser(
                    intent,"Select App"
                ),SELECT_PICTURE
            )
        }
    }

从以下地址获取 Uri:

override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
        super.onActivityResult(requestCode,resultCode,data)

        when (resultCode) {
            Activity.RESULT_OK -> {
                isExistCheck.isChecked = false

                setimageWiaUri(data?.data ?: tempFileUri)//tempFileUri for camera option

                when (requestCode) {
                    CAMERA_PICTURE -> {
                        Toast.makeText(this,"CAMERA",Toast.LENGTH_SHORT).show()
                    }
                    SELECT_PICTURE -> {
                        Toast.makeText(this,"STORAGE",Toast.LENGTH_SHORT).show()
                    }

                }
            }
            Activity.RESULT_CANCELED -> {
                Toast.makeText(this,"CANCELED",Toast.LENGTH_SHORT).show()
            }
        }
    }

这是我的代码

private fun setimageWiaUri(uri: Uri) {
        isExistCheck.isChecked = isFileExist(uri)
        var imguri = uri

        if (isFileExist(uri)) {
            if (uri.toString().split(":")[0] == "file") {

               imguri = FileProvider.getUriForFile(
                    this,"com.example.photoselector.fileprovider",File(uri.toString())
                )
            }

            Glide.with(this)
                .load(imguri)
                .into(image)

        } else {
            Toast.makeText(this,"File does not exist...",Toast.LENGTH_SHORT).show()
        }
    }

我的 provider_paths :

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-cache-path
        name="external_cache_files"
        path="."/>
    <external-files-path
        name="external_files"
        path="." />
    <files-path
        name="files"
        path="." />
    <external-media-path
        name="external_media"
        path="." />
    <external-path
        name="externals"
        path="." />
    <cache-path
        name="cache_files"
        path="." />

</paths>

我该如何解决这个问题,或者如何将“file://”uri 转换为“content://”uri?

解决方法

但是有些应用程序给了我以“file://”开头的uri。 Glide 也不适用于 "file://" uri

ACTION_GET_CONTENT 实现的工作是返回一个有用的 Uri。您可以通过在 CATEGORY_OPENABLE 中添加 Intent 来消除一些麻烦的应用程序,表明您希望能够打开由 Uri 标识的内容。

Glide 可以使用 file:// Uri,前提是您的应用有权访问该文件。

如何将“file://”uri 转换为“content://”uri?

那不是你的问题。 content:// 不是表示“Uri 会起作用”的魔法字符串,而 file:// 不是表示“Uri 不起作用”的魔法字符串。>

您没有解释您在使用 Glide 时遇到的具体问题。我的猜测是您没有对该文件的读取权限。如果是这样,FileProvider 不会神奇地授予您读取权限,而 HeyThisClassIsMagic 类不会授予您读取权限。您的应用要么具有读取权限,要么没有。

确保您的应用拥有 READ_EXTERNAL_STORAGE 权限并在运行时请求它。此外,请确保您的应用在清单的 android:requestLegacyExternalStorage="true" 元素中有 <application>。这些步骤将增加您阅读由 Uri 标识的内容的可能性。

如果这没有帮助,那么我建议您提出一个单独的问题,说明您如何将返回的 file:// Uri 与 Glide 结合使用,以及您遇到的具体错误。