Android 11/12读取最近文件与Google Drive文件触发FileNotFound异常
解决Android 11/12中Google Drive及最近文件Uri转Base64的FileNotFound异常
你的代码问题出在试图将所有Uri解析为本地文件路径,但Google Drive的Uri是云端内容的虚拟标识,没有对应的本地File;部分"最近文件"的Uri指向媒体库记录,也不是直接的文件路径,直接用File类读取必然抛出FileNotFound异常。
正确解决方案:通过ContentResolver读取Uri输入流
不管Uri指向本地存储、媒体库还是Google Drive,都可以利用Android的ContentResolver直接打开对应的输入流,读取字节后再转Base64,无需解析本地路径。
修改后的完整代码如下:
public class PdfToBase64 { // 直接从Uri转换为Base64字符串 public static String convertUriToBase64(Context context, Uri uri) throws IOException { InputStream inputStream = context.getContentResolver().openInputStream(uri); if (inputStream == null) { throw new IOException("无法打开Uri对应的输入流"); } // 读取输入流的所有字节 byte[] bytes = new byte[inputStream.available()]; inputStream.read(bytes); inputStream.close(); // 转换为Base64 return Base64.getEncoder().encodeToString(bytes); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (data == null || data.getData() == null) { return; } Uri pdfUri = data.getData(); try { String pdfBase64 = PdfToBase64.convertUriToBase64(this, pdfUri); // 这里处理转换后的Base64字符串 } catch (IOException e) { Log.e("TFGTESTINGPanE", "转换失败: " + e.getMessage()); } } }
关键说明
- ContentResolver.openInputStream(uri):这是Android统一读取内容的标准方式,不管Uri来自外部存储、媒体库还是第三方应用(如Google Drive),只要应用拥有该Uri的访问权限,就能获取到输入流。
- 权限适配:Android 11+中,访问外部存储需要
READ_EXTERNAL_STORAGE权限;对于Google Drive的文件,用户通过文件选择器授权后,应用自动获得对应Uri的临时访问权限,无需额外申请。 - 废弃原路径解析逻辑:原来的
getActualPath方法仅适用于外部存储的文档Uri,无法兼容云端或媒体库的内容,直接删除即可。
测试验证
- 外部存储Uri:
content://com.android.externalstorage.documents/document/primary%3ADownload%2FJava%20.pdf→ 正常转换 - Google Drive Uri:
content://com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3Dencoded%3DGKVQVPeUy8YACTP3yosCu14qFMpPUAUvpmE_n27UcH0XrcgXcBFfjHrOnO2h→ 正常转换 - 最近文件Uri:
content://com.android.providers.media.documents/document/document%3A1000004084→ 正常转换
内容的提问来源于stack exchange,提问作者vignesh
相关产品推荐
相关产品推荐

