You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 11及更早版本图片选择功能失效适配求助

Android 旧版本(API24及以下)选择照片文件找不到问题的解决方案

问题根源

你当前的实现依赖MediaStore.Images.Media.DATA列获取文件路径,但该方式存在以下兼容性问题:

  • 从Android 10(API29)开始,系统限制了DATA字段的访问权限,部分场景下无法获取有效路径。
  • 对于非媒体库来源的Uri(如第三方文件管理器、云存储文件),DATA字段本身不存在,直接返回空路径,导致File(getPathFromUri(uri))指向不存在的文件,抛出ENOENT错误。
  • Android13(API33)的兼容逻辑可能暂时能拿到路径,但旧版本(如API24)的Uri解析逻辑不支持这种方式,因此失效。

解决方案:直接通过Uri复制文件

完全放弃获取本地路径的思路,直接利用ContentResolver打开Uri对应的输入流,将文件内容复制到目标位置。这种方式兼容所有Android版本,且无需依赖不可靠的媒体库路径。

步骤1:修改文件复制函数

替换原有的copyTo函数,改为接收Uri和目标文件:

private fun copyUriToFile(uri: Uri, destination: File) {
    applicationContext.contentResolver.openInputStream(uri)?.use { input ->
        destination.outputStream().use { output ->
            input.copyTo(output)
        }
    } ?: throw IllegalArgumentException("无法打开Uri对应的输入流")
}

步骤2:修改选择照片后的处理逻辑

移除getPathFromUri函数,在pickMedia2中直接使用Uri复制文件,同时将文件操作移至IO线程(避免阻塞主线程):

private val pickMedia2 = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
    if (uri != null) {
        val scope = CoroutineScope(Dispatchers.IO)
        scope.launch {
            val randomString = generateRandomString()
            Log.d("testing", randomString)

            val extension = "png"
            val localFileName = "${randomString}Image2.${extension}"
            val localDir = File(this@EditProfile.getExternalFilesDir(null), "images")
            if (!localDir.exists()) {
                localDir.mkdirs()
            }
            val newFile = File(localDir, localFileName)
            
            runCatching {
                copyUriToFile(uri, newFile)
                val newFilePath = newFile.absolutePath
                databaseHelper.replacePhotoReference(newFilePath, 2)
                uploadFile(uri, "2")
            }.onFailure {
                Log.e("testing", "文件复制失败", it)
            }
        }

        Glide.with(this)
            .load(uri)
            .transform(MultiTransformation(CenterCrop(), RoundedCorners(60)))
            .into(userPhoto2)
        rotatePlusButton(2, false, fast = false)
        photoTwoSet = true
    }
}

额外说明

  • 该方式无需申请额外的存储权限:getExternalFilesDir属于应用私有目录,系统允许直接访问;通过ContentResolver访问Uri是系统授权的结果,符合Android权限规范。
  • 避免了依赖媒体库路径的各种兼容性问题,无论Uri来自媒体库还是第三方应用,都能正常复制文件。

内容的提问来源于stack exchange,提问作者TheG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:44:54