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

调用相机拍照保存至外部存储时应用崩溃问题排查

解决调用相机Intent拍照存外部存储时权限获取后崩溃的问题

看起来你遇到的问题是在获取相机和存储权限后,调用相机Intent时应用崩溃了。结合你给出的代码片段,我来梳理几个最可能的原因和对应的解决方案:

1. 相机Intent未正确配置输出文件路径

很多时候崩溃的核心原因是没有给相机Intent指定有效的图片存储路径,导致相机App无法完成图片写入操作,进而抛出异常。你需要确保在invokeCamera()方法中创建合法的存储文件,并将其Uri传递给相机Intent。

示例代码如下:

// 定义请求码,用于后续回调处理
private static final int REQUEST_IMAGE_CAPTURE = 1;
private String mCurrentPhotoPath;

private void invokeCamera() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // 先检查设备上是否有相机App可以处理这个Intent,避免找不到相机导致崩溃
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            // 处理文件创建失败的异常,比如提示用户存储异常
            ex.printStackTrace();
            Toast.makeText(this, "创建图片文件失败", Toast.LENGTH_SHORT).show();
        }
        // 只有文件创建成功时,才启动相机
        if (photoFile != null) {
            // Android 7.0及以上必须用FileProvider获取Uri,不能直接用file://
            Uri photoURI = FileProvider.getUriForFile(this,
                    "com.your.package.name.fileprovider", // 这里替换成你的包名+fileprovider
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    } else {
        Toast.makeText(this, "未找到可用的相机应用", Toast.LENGTH_SHORT).show();
    }
}

// 生成唯一的图片存储文件
private File createImageFile() throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    // 使用App专属的外部存储目录,不需要额外的存储权限(Android 10+)
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    // 确保存储目录存在
    if (!storageDir.exists()) {
        storageDir.mkdirs();
    }
    return File.createTempFile(imageFileName, ".jpg", storageDir);
}

2. 未配置FileProvider(Android 7.0+ 必做)

从Android 7.0开始,系统禁止直接传递file://格式的Uri给其他App,否则会抛出FileUriExposedException导致崩溃。你需要在项目中配置FileProvider:

第一步:在AndroidManifest.xml中添加Provider配置

<application>
    ...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.your.package.name.fileprovider" <!-- 替换成你的包名+fileprovider -->
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
    ...
</application>

第二步:创建file_paths.xml文件

在res/xml目录下创建file_paths.xml(如果没有xml目录则新建),内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 对应getExternalFilesDir(Environment.DIRECTORY_PICTURES)的路径 -->
    <external-files-path name="my_images" path="Pictures" />
</paths>

3. 权限请求的回调处理不完整

你的代码中权限请求部分没有写完,需要确保在权限请求结果回调中,确认所有权限都被授予后再调用invokeCamera():

private static final int REQUEST_CAMERA_STORAGE_PERMISSIONS = 2;

public void dispatchTakePictureIntent(View view) {
    if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED 
        && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
        invokeCamera();
    } else {
        String[] permissionRequest = {
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
        requestPermissions(permissionRequest, REQUEST_CAMERA_STORAGE_PERMISSIONS);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CAMERA_STORAGE_PERMISSIONS) {
        boolean allPermissionsGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allPermissionsGranted = false;
                break;
            }
        }
        if (allPermissionsGranted) {
            invokeCamera();
        } else {
            Toast.makeText(this, "需要相机和存储权限才能完成拍照", Toast.LENGTH_SHORT).show();
        }
    }
}

4. 适配Android 10+的存储权限

Android 10及以上引入了分区存储,如果你使用getExternalFilesDir()这类App专属目录,不需要申请WRITE_EXTERNAL_STORAGE权限,这可以简化权限逻辑,避免不必要的权限申请问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:32:26