Android相机拍照生成0字节文件,获取文件大小失败的解决方法
解决方案
问题根源
- 取消拍摄的空文件残留:调用
ACTION_IMAGE_CAPTURE并指定EXTRA_OUTPUT时,系统会预先创建你指定的空文件,无论用户最终是否完成拍摄,这个空文件都会留在目录中。 - 正常拍摄后文件大小显示为0:相机App拍摄完成后是异步写入图片数据到目标文件的,
onActivityResult返回RESULT_OK时,文件可能还在后台写入,此时读取大小自然为0。
具体解决步骤
1. 取消拍摄时删除空文件
在onActivityResult中判断结果码,若用户取消拍摄,直接删除预先创建的空文件:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1) { if (resultCode == RESULT_OK) { // 拍摄完成,等待文件写入结束后再处理 waitForFileWriteFinish(currentPhotoPath); } else { // 用户取消拍摄,清理空文件 removeEmptyPhoto(currentPhotoPath); } } } private void removeEmptyPhoto(String photoPath) { if (photoPath == null) return; File photoFile = new File(photoPath); if (photoFile.exists() && photoFile.length() == 0) { photoFile.delete(); } }
2. 等待拍摄文件写入完成
不要在onActivityResult中立刻读取文件状态,用FileObserver监听文件的写入完成事件,确保相机写完数据后再处理:
private void waitForFileWriteFinish(String photoPath) { if (photoPath == null) return; File photoFile = new File(photoPath); File parentDir = photoFile.getParentFile(); // 监听文件的关闭写入事件,代表数据写入完成 FileObserver fileObserver = new FileObserver(parentDir.getAbsolutePath(), FileObserver.CLOSE_WRITE) { @Override public void onEvent(int event, String path) { if (path != null && path.equals(photoFile.getName())) { runOnUiThread(() -> { long fileSize = photoFile.length(); if (fileSize == 0) { // 极端情况:拍摄后文件仍为空,直接删除 photoFile.delete(); } else { // 文件正常,执行后续业务逻辑 // processCapturedPhoto(photoFile); } }); // 处理完成后停止监听 stopWatching(); } } }; fileObserver.startWatching(); }
3. 额外优化:防止路径丢失
将currentPhotoPath保存到SavedInstanceState中,避免因屏幕旋转等配置变更导致路径丢失:
@Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("currentPhotoPath", currentPhotoPath); } @Override public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); if (savedInstanceState != null) { currentPhotoPath = savedInstanceState.getString("currentPhotoPath"); } }
关键说明
- 不要依赖
onActivityResult返回时的文件状态,相机的写入操作是异步的,必须等待写入完成再做判断。 FileObserver是监听本地文件变化的可靠方案,比固定延迟等待(如Handler.postDelayed)更适配不同性能的设备,不会出现误判。
内容的提问来源于stack exchange,提问作者Patrick Renaud
相关产品推荐
相关产品推荐

