You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android相机拍照生成0字节文件,获取文件大小失败的解决方法

解决方案

问题根源

  1. 取消拍摄的空文件残留:调用ACTION_IMAGE_CAPTURE并指定EXTRA_OUTPUT时,系统会预先创建你指定的空文件,无论用户最终是否完成拍摄,这个空文件都会留在目录中。
  2. 正常拍摄后文件大小显示为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:05:25