如何解决android.net.Uri转java.net.URI后创建File报scheme非file错误
错误原因
Android 10(API 29)引入了分区存储机制,公共Download目录下的文件返回的android.net.Uri默认是content://开头的scheme,你原有代码要求java.net.URI必须是file://开头的scheme,两者不匹配就会抛出该异常。
修复方案
方案1:临时兼容方案(仅API 29生效,API 30及以上已废弃)
仅适合需要快速兼容旧代码的场景:
- 在
AndroidManifest.xml的<application>节点添加属性android:requestLegacyExternalStorage="true",即可临时关闭分区存储,此时拿到的Download目录文件Uri为file://开头,原有代码可正常运行。注意该属性在targetSDK升级到30后自动失效,不建议长期使用。
方案2:官方推荐通用方案(全版本兼容)
不要尝试将content://类型的Uri转换为File对象,直接通过ContentResolver操作Uri对应的文件流即可,示例代码如下:
// 已获取到目标mp4文件的android.net.Uri对象 INPUT_FILE InputStream inputStream = getContentResolver().openInputStream(INPUT_FILE); // 若确实需要本地File对象,可将流拷贝到应用私有目录 File targetFile = new File(getExternalFilesDir(Environment.DIRECTORY_MOVIES), "test.mp4"); FileOutputStream outputStream = new FileOutputStream(targetFile); // 流拷贝逻辑 byte[] buffer = new byte[4096]; int len; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } // 关闭流 outputStream.close(); inputStream.close(); // 后续直接操作targetFile即可
如果你的业务场景仅需要读取文件内容(比如给播放器设置数据源),不需要生成本地File对象,直接使用InputStream或者直接传入content://类型的Uri即可,不需要额外做流拷贝。
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

