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
相关产品推荐
相关产品推荐

