Android API 34下如何从URI获取文件扩展名
解决Android API 34下无法获取文件扩展名的问题
你的核心问题在于用GetContent()获取的是内容Uri(格式类似content://xxx),而非直接的文件系统路径,直接通过File(it.path)获取文件信息在API34中完全不可靠——因为这类Uri的path字段根本不对应真实文件路径,甚至可能为空,自然拿不到扩展名。
以下是可行的解决方案:
方法1:通过MIME类型校验(推荐)
.db文件的标准MIME类型是application/x-sqlite3或application/vnd.sqlite3,通过ContentResolver获取Uri对应的MIME类型来判断,这比扩展名更可靠:
val launch = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri?.let { val contentResolver = context.contentResolver // 获取MIME类型 val mimeType = contentResolver.getType(it) // 校验MIME类型,同时兼容扩展名判断(应对部分自定义情况) val isDbFile = mimeType in setOf("application/x-sqlite3", "application/vnd.sqlite3") || it.lastPathSegment?.endsWith(".db", ignoreCase = true) == true if (isDbFile) { coroutine.launch(Dispatchers.IO) { profileVM.load(it, context) } } } }
方法2:从Uri路径片段提取扩展名
如果只需要通过扩展名判断,可以直接从Uri的最后一段路径提取:
val launch = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri?.let { val fileName = it.lastPathSegment // 提取扩展名并转为小写,避免大小写问题 val extension = fileName?.substringAfterLast('.', "")?.lowercase() if (extension == "db") { coroutine.launch(Dispatchers.IO) { profileVM.load(it, context) } } } }
关键注意事项
- 不要尝试通过Uri的
path字段构建File对象,API34及更高版本的存储权限限制会直接阻止这种操作,且内容Uri本身不指向真实文件路径。 - 确保你的
profileVM.load()方法内部是通过ContentResolver.openInputStream(uri)来读取文件内容,而非直接访问File对象,这样才能符合Android的权限规范。
内容的提问来源于stack exchange,提问作者Pal
相关产品推荐
相关产品推荐

