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

为何FileProvider无法在所有Android设备上正常工作?

解决FileProvider拍照部分设备崩溃的问题

你的代码存在几个关键问题,导致部分设备点击相机确认按钮时崩溃,逐一修复即可:

1. 禁止忽略文件创建/FileProvider初始化异常

内部try块直接ignored所有异常,会掩盖目录不存在、权限不足等问题,相机启动后因无法写入指定文件而崩溃。必须移除空catch,至少添加日志记录或终止流程提示用户。

2. 替换废弃的公共存储目录,改用应用私有外部存储

Android 10(API 29)及以上,Environment.getExternalStoragePublicDirectory已废弃,且公共存储的写入权限限制越来越严,部分相机应用无法写入公共目录的Uri。改用应用私有外部存储目录,既不需要额外权限,也更安全:

File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);

3. 确保文件父目录存在

创建文件前必须检查并创建父目录,否则相机无法写入文件:

if (!storageDir.exists()) {
    storageDir.mkdirs();
}

4. 显式授予Uri临时权限

部分相机应用需要显式的Uri读写权限,给Intent添加权限标记:

cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

5. 避免pictureImagePath空值崩溃

如果文件创建失败,不要继续启动相机,否则后续pictureImagePath为空,在onActivityResult里会触发空指针异常。

6. 移除assert,改用安全的非空判断

assert data != null在开启断言的设备上会直接崩溃,换成普通的非空判断:

if (data != null) {
    Bundle extras = data.getExtras();
    if (extras != null) {
        bitmap = (Bitmap) extras.get("data");
    }
}

修改后的完整代码示例

takePicture方法:

private void takePicture() {
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // 确保相机应用存在
    if (cameraIntent.resolveActivity(getPackageManager()) == null) {
        Toast.makeText(this, getString(R.string.camera_not_recog), Toast.LENGTH_SHORT).show();
        return;
    }

    File photoFile = null;
    try {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        String imageFileName = timeStamp + ".jpg";
        // 改用应用私有外部存储
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!storageDir.exists()) {
            storageDir.mkdirs();
        }
        photoFile = new File(storageDir, imageFileName);
        pictureImagePath = photoFile.getAbsolutePath();
        Uri outputFileUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", photoFile);
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        // 显式授予权限
        cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(this, "无法创建拍照文件", Toast.LENGTH_SHORT).show();
        return;
    }

    // 只有成功创建文件才启动相机
    someActivityResultLauncher.launch(cameraIntent);
}

ActivityResultCallback:

ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == Activity.RESULT_OK) {
                Intent data = result.getData();
                try {
                    if (pictureImagePath != null) {
                        File imgFile = new File(pictureImagePath);
                        if (imgFile.exists()) {
                            bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
                        } else if (data != null) {
                            Bundle extras = data.getExtras();
                            if (extras != null) {
                                bitmap = (Bitmap) extras.get("data");
                            }
                        }
                    } else if (data != null) {
                        Bundle extras = data.getExtras();
                        if (extras != null) {
                            bitmap = (Bitmap) extras.get("data");
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    if (data != null) {
                        Bundle extras = data.getExtras();
                        if (extras != null) {
                            bitmap = (Bitmap) extras.get("data");
                        }
                    }
                } finally {
                    startActivity(new Intent(this, CameraActivity.class));
                }
            }
        });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:47:47