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

Android应用拍摄8-10张照片后崩溃问题求助

问题分析

从报错日志和代码来看,崩溃的直接原因是MediaStore.Images.Media.insertImage()方法返回了null,导致后续Uri.parse(path)抛出NullPointerException。而多次拍照后触发该问题,是因为这个方法已被官方废弃,且依赖系统MediaStore的插入逻辑,当图库中照片数量达到一定阈值时,会因存储配额、重复条目限制或系统兼容性问题返回空值。

同时当前拍照逻辑存在两个缺陷:

  • 启动相机时将EXTRA_OUTPUT设为null,导致相机仅返回低分辨率缩略图,而非原图
  • 依赖废弃的insertImage方法将Bitmap插入MediaStore,可靠性极低
解决方案

改用FileProvider指定相机拍照的保存路径,直接获取原图Uri,彻底规避MediaStore插入的不可靠操作:

1. 配置FileProvider

在AndroidManifest.xml中添加FileProvider声明:

<application>
    ...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
    ...
</application>

在res/xml目录下创建file_paths.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="camera_images" path="Pictures" />
</paths>

2. 修改相机启动逻辑

替换原启动代码,生成临时文件并通过FileProvider获取可访问的Uri:

File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File imageFile = null;
try {
    // 生成唯一的临时图片文件
    imageFile = File.createTempFile(
        "VISIT_",
        ".jpg",
        storageDir
    );
} catch (IOException e) {
    e.printStackTrace();
}

if (imageFile != null) {
    // 获取FileProvider授权的Uri
    imageUri = FileProvider.getUriForFile(
        this,
        getPackageName() + ".fileprovider",
        imageFile
    );

    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    // 授予相机写入该Uri的权限
    takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}

3. 修改Activity结果回调

直接使用预先生成的imageUri,无需再处理返回的缩略图:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        if (imageUri != null) {
            String checkInOutText = checkInOut.getText().toString();
            if ("Check In".equals(checkInOutText)) {
                checkInHolder.setVisibility(View.VISIBLE);
                checkInHolder.setImageURI(imageUri);
            } else if (checkInHolder.getVisibility() == View.VISIBLE && "Check Out".equals(checkInOutText)) {
                checkOutHolder.setVisibility(View.VISIBLE);
                checkOutHolder.setImageURI(imageUri);
            }
            // 上传数据库时,可直接通过该Uri获取文件流
        }
    }
}

4. 清理废弃代码

删除原有的getImageUri方法,因为不再需要将Bitmap插入MediaStore。

权限说明

  • Android 10及以上:无需申请WRITE_EXTERNAL_STORAGE权限,使用的是应用私有外部存储,系统自动授权
  • Android 9及以下:需在Manifest中声明WRITE_EXTERNAL_STORAGE权限,并在运行时请求该权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:32:21