Android文件选择器返回两种URI,如何获取文件名或限制为指定URI类型?
Android文件选择器:获取文件名或限制URI类型
我在使用Android文件选择器时,遇到两种不同格式的URI:
content://com.android.providers.media.documents/document/document%3A51(从某选项选取文件时得到,不含文件名)content://com.android.externalstorage.documents/document/primary%3ADownload%2FKTM%20DUKE%20Range%20E-Brochure%202022.pdf(从另一选项选取文件时得到,包含文件名)
我需要实现以下两个目标之一:要么从两种URI中都能提取出文件名,要么限制用户只能选择生成第二种URI的文件来源。当前打开文件选择器的代码如下:
val intent = Intent(Intent.ACTION_GET_CONTENT) intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) intent.type = "*/*" selectFilesActivityResult.launch(intent)
方案一:从两种URI中提取文件名
不管URI来自媒体库还是外部存储,都可以通过ContentResolver查询或路径解析获取文件名:
实现代码(Kotlin)
fun getFileNameFromUri(context: Context, uri: Uri): String? { var fileName: String? = null val docId = DocumentsContract.getDocumentId(uri) // 处理外部存储类型的URI if (docId.startsWith("primary:")) { fileName = docId.split(":")[1] } else { // 处理媒体库类型的URI,查询媒体库获取文件名 val projection = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME) context.contentResolver.query(uri, projection, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)) } } } return fileName ?: "未知文件" }
注意事项
- Android 13及以上版本,读取媒体文件需要申请
READ_MEDIA_IMAGES/READ_MEDIA_VIDEO/READ_MEDIA_AUDIO权限;读取非媒体文件仍需READ_EXTERNAL_STORAGE,记得动态申请权限 - 代码中使用
use块自动关闭Cursor,避免内存泄漏
方案二:限制选择外部存储类型的URI
如果只想让用户选择外部存储中的文件,可以修改Intent的Action,直接打开外部存储的文档树:
修改后的代码(Kotlin)
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) // 可选:设置默认打开Download文件夹 val downloadDirId = DocumentsContract.getTreeDocumentId(MediaStore.Downloads.EXTERNAL_CONTENT_URI) val initialDownloadUri = DocumentsContract.buildDocumentUriUsingTree( MediaStore.EXTERNAL_CONTENT_URI, downloadDirId ) intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialDownloadUri) selectFilesActivityResult.launch(intent)
说明
- 使用
ACTION_OPEN_DOCUMENT_TREE替代ACTION_GET_CONTENT,用户只能选择外部存储中的文件,获取到的URI都会包含路径和文件名信息 - 可以通过
EXTRA_INITIAL_URI设置默认打开的目录,提升用户体验
内容的提问来源于stack exchange,提问作者AashishKSahu
相关产品推荐
相关产品推荐

