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

Android如何调用系统相机APP拍照且仅在拍照成功时创建存储文件

解决方案

核心实现思路

  • 替换废弃的startActivityForResult,使用Jetpack官方推荐的Activity Result API处理拍照回调
  • 针对提前创建空文件的问题,采用「临时文件预创建 + 取消拍照自动删除」的兼容方案:跳转相机前预创建临时文件,在回调中判断如果用户取消拍摄则直接删除该文件,仅拍照成功时保留文件,既避免了多余空文件的产生,也兼容了绝大多数系统/第三方相机APP的全尺寸照片输出逻辑

完整修改代码

首先确保你的项目已经引入了最新的Activity KTX依赖(高版本appcompat默认已包含,无需额外引入)。

1. 声明成员变量与拍照回调

// 存储照片文件路径
private String currentPhotoPath;
// 注册拍照结果回调
private ActivityResultLauncher<Uri> takePictureLauncher = registerForActivityResult(
    new ActivityResultContracts.TakePicture(),
    isSuccess -> {
        if (isSuccess) {
            // 拍照成功,可直接使用currentPhotoPath处理后续逻辑(如展示、上传照片等)
        } else {
            // 用户取消拍摄,删除预创建的空临时文件
            if (currentPhotoPath != null) {
                File tempFile = new File(currentPhotoPath);
                if (tempFile.exists()) {
                    tempFile.delete();
                }
                currentPhotoPath = null;
            }
        }
    }
);

2. 保留创建图片文件的工具方法

private File createImageFile() throws IOException {
    // 生成带时间戳的唯一文件名
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
        imageFileName,  /* 文件名前缀 */
        ".jpg",         /* 文件名后缀 */
        storageDir      /* 应用私有存储目录,无需申请存储权限 */
    );
    currentPhotoPath = image.getAbsolutePath();
    return image;
}

3. 修改触发拍照的逻辑

private void dispatchTakePictureIntent() {
    // 检查设备是否存在可处理拍照请求的APP
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(getPackageManager()) == null) {
        // 无可用相机,可自行添加Toast提示逻辑
        return;
    }
    File photoFile = null;
    try {
        photoFile = createImageFile();
    } catch (IOException ex) {
        // 创建文件失败,可自行添加错误提示逻辑
        ex.printStackTrace();
        return;
    }
    if (photoFile != null) {
        Uri photoURI = FileProvider.getUriForFile(this,
                "com.example.android.fileprovider", // 替换为你项目中FileProvider的authorities值
                photoFile);
        // 启动拍照流程
        takePictureLauncher.launch(photoURI);
    }
}

注意事项

  • 请确保你在AndroidManifest.xml中正确配置了FileProvider,配置的authorities参数需要和代码中传入的值完全一致
  • 如果你的业务仅需要使用缩略图,不需要全尺寸照片,可以使用ActivityResultContracts.TakePicturePreview协议,直接获取返回的Bitmap后再创建文件写入,完全不需要预创建临时文件,但该方案存在传输过大Bitmap触发TransactionTooLargeException的风险,不适合需要高清照片的场景

内容的提问来源于stack exchange,提问作者Vishnu AV

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:09:03