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

Android 13从存储选择文件时获取正确Intent Uri的问题

Android 13 下从Intent获取Uri后文件名丢失问题解决

问题原因

Android 13调整了媒体文件Uri的格式,不再将文件名直接包含在Uri路径中,而是使用文档ID(如content://com.android.providers.media.documents/document/document%3A1000000089),导致依赖Uri的path字段或第三方工具类获取文件名的方式失效。

解决方案

不要通过Uri的path或转换为File对象来获取文件名,直接通过ContentResolver查询媒体文件的显示名称,同时处理文件内容时优先使用ContentResolver.openInputStream()而非真实文件路径:

1. 获取文件名并处理文件内容

修改接收Intent的回调代码,直接从ContentResolver获取文件名和文件流:

private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        result.data?.data?.let { uri ->
            // 查询获取文件名
            val fileName = requireContext().contentResolver.query(
                uri,
                arrayOf(MediaStore.MediaColumns.DISPLAY_NAME),
                null,
                null,
                null
            )?.use { cursor ->
                if (cursor.moveToFirst()) {
                    cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME))
                } else {
                    "unknown_file"
                }
            } ?: "unknown_file"

            // 获取文件输入流,用于构建Multipart
            requireContext().contentResolver.openInputStream(uri)?.use { inputStream ->
                val requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), inputStream.readBytes())
                val multipartBody = MultipartBody.Part.createFormData("file", fileName, requestFile)
                // 执行后续上传逻辑
            }
        }
    }
}

2. 废弃依赖真实文件路径的做法

停止使用PathUtils.getReadablePathFromUri()这类工具类,Android 13及更高版本中,content://类型的Uri可能不对应可直接访问的本地文件路径,强制转换会导致路径无效或文件名丢失。

3. 优化Intent调用(可选)

调整Intent参数,更精准筛选txt和csv文件:

private fun performFileSearch() {
    val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
        addCategory(Intent.CATEGORY_OPENABLE)
        type = "text/*"
        val mimeTypes = arrayOf("text/csv", "text/plain")
        putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
    }
    resultLauncher.launch(intent)
}

关键说明

所有Android版本都推荐使用ContentResolver获取文件名和文件内容,而非依赖Uri的path字段,这是ContentProvider的标准用法,兼容性更强。构建Multipart时,直接使用InputStream转换为RequestBody即可,无需先转换为File对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:32:27