Android上传assets文件至Google Drive遇ENOENT异常的排查与解决
问题原因与解决方案
这个坑我之前踩过!你遇到的FileNotFoundException核心原因是:Android项目assets目录下的文件是打包在APK内部的,并非设备文件系统中的真实文件,你直接用java.io.File去访问file:///android_asset/config.json这个路径完全行不通——这个URI只是Android用来访问内部资源的协议,对应不到真实的文件系统路径。
解决思路
要上传assets里的文件,你得先通过Android的AssetManager读取文件的输入流,再把流转换成Google Drive API能识别的内容格式(要么写入临时文件,要么直接用流上传)。
方案一:写入临时文件后上传(兼容性好)
这种方式是把assets里的文件先复制到设备的临时目录,再用这个临时文件来上传,代码修改如下:
try { // 1. 获取AssetManager并打开config.json的输入流 AssetManager assetManager = getAssets(); InputStream inputStream = assetManager.open("config.json"); // 2. 创建临时文件 File tempFile = File.createTempFile("config", ".json", getCacheDir()); FileOutputStream outputStream = new FileOutputStream(tempFile); // 3. 将assets文件流写入临时文件 byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } inputStream.close(); outputStream.close(); // 4. 用临时文件上传到Google Drive File fileMetadata = new File(); fileMetadata.setName("config.json"); fileMetadata.setParents(Collections.singletonList("appDataFolder")); FileContent mediaContent = new FileContent("application/json", tempFile); File file = mService.files().create(fileMetadata, mediaContent) .setFields("id") .execute(); Log.d("File ID: ", file.getId()); // 5. 上传完成后删除临时文件(可选,避免占用空间) tempFile.delete(); } catch (IOException e) { Log.d("Upload Error: ", e.getMessage()); e.printStackTrace(); }
方案二:直接用InputStreamContent上传(更高效,无需临时文件)
Google Drive API其实支持直接传入输入流,用InputStreamContent代替FileContent,这样可以省去创建临时文件的步骤:
try { // 1. 获取AssetManager并打开文件流 AssetManager assetManager = getAssets(); InputStream inputStream = assetManager.open("config.json"); // 2. 构建InputStreamContent InputStreamContent mediaContent = new InputStreamContent("application/json", inputStream); // 设置文件长度(可选,但建议设置,避免API处理异常) mediaContent.setLength(assetManager.openFd("config.json").getLength()); // 3. 上传到Google Drive File fileMetadata = new File(); fileMetadata.setName("config.json"); fileMetadata.setParents(Collections.singletonList("appDataFolder")); File file = mService.files().create(fileMetadata, mediaContent) .setFields("id") .execute(); Log.d("File ID: ", file.getId()); inputStream.close(); } catch (IOException e) { Log.d("Upload Error: ", e.getMessage()); e.printStackTrace(); }
注意事项
- 如果你用的是Fragment,获取
AssetManager需要用requireContext().getAssets(),而不是直接调用getAssets() - 方案二中的
setLength步骤很重要,因为有些情况下输入流无法自动获取长度,会导致上传失败 - 不用额外申请外部存储权限,因为临时文件存在App的缓存目录里,属于App私有空间
内容的提问来源于stack exchange,提问作者Hitesh Matnani
相关产品推荐
相关产品推荐

