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

Android 7相机调用崩溃及图片裁剪报错问题求助

解决Android 7.0相机调用及图片裁剪兼容性问题

我来帮你拆解这两个问题,都是Android版本升级后常见的兼容性坑,咱们一步步来解决:


一、Camera.open()强制关闭的问题

问题原因

Android 6.0(API 23)起引入了动态权限机制,CAMERA属于危险权限,必须在运行时主动申请用户授权;另外高版本系统对相机资源的管控更严格,若相机被其他应用占用、设备无可用相机,直接调用Camera.open()会直接崩溃。而Android 4.4.2不需要动态权限,所以之前能正常运行。

解决办法

  1. 先申请相机权限
    在调用相机前,先检查是否已获取CAMERA权限,没有的话动态申请:

    private static final int REQUEST_CAMERA_PERMISSION = 100;
    
    // 检查并申请相机权限
    private void checkCameraPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA},
                    REQUEST_CAMERA_PERMISSION);
        } else {
            // 权限已获取,打开相机
            openCameraSafely();
        }
    }
    
    // 处理权限申请结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                openCameraSafely();
            } else {
                Toast.makeText(this, "需要相机权限才能使用该功能", Toast.LENGTH_SHORT).show();
            }
        }
    }
    
  2. 安全打开相机实例
    用try-catch包裹相机打开逻辑,避免因相机被占用等情况崩溃,还可以遍历可用相机ID尝试打开:

    private void openCameraSafely() {
        Camera camera = null;
        try {
            // 先尝试打开默认相机(ID=0)
            camera = Camera.open();
            // 后续相机操作...
        } catch (Exception e) {
            // 尝试打开其他相机ID(比如ID=1,前置相机)
            try {
                camera = Camera.open(1);
            } catch (Exception ex) {
                Toast.makeText(this, "无法打开相机,请检查相机是否被占用", Toast.LENGTH_SHORT).show();
                ex.printStackTrace();
            }
        }
    }
    

二、相册选图裁剪时“Editing is not supported”错误

问题原因

Android 7.0(API 24)起,系统禁止应用向其他应用暴露file://格式的Uri,否则会抛出FileUriExposedException;同时部分系统自带的裁剪应用不支持接收file:// Uri,导致弹出“Editing is not supported”错误。而Android 4.4.2没有这个限制,所以之前正常。

解决办法

核心是用FileProvider生成content://格式的Uri来替代file://,具体步骤如下:

  1. 配置FileProvider
    在AndroidManifest.xml的<application>标签内添加FileProvider配置:

    <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>
    

    (如果用的是support库,把androidx.core.content.FileProvider换成android.support.v4.content.FileProvider)

    然后在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="my_images" path="Pictures/" />
        <external-cache-path name="cache_images" path="Pictures/" />
        <!-- 根据你的需求添加其他目录,比如external-path对应SD卡根目录 -->
    </paths>
    
  2. 修改裁剪Intent的Uri处理
    选择图片后,生成裁剪输出文件的Uri时,用FileProvider获取content://格式的Uri,并给裁剪Intent添加读写权限:

    private static final int REQUEST_CROP = 200;
    
    // 假设已从相册获取图片的inputUri
    private void startCrop(Uri inputUri) {
        // 创建裁剪输出文件
        File outputFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "cropped_" + System.currentTimeMillis() + ".jpg");
        Uri outputUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", outputFile);
    
        Intent cropIntent = new Intent("com.android.camera.action.CROP");
        cropIntent.setDataAndType(inputUri, "image/*");
        // 添加读写权限
        cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        // 设置裁剪参数
        cropIntent.putExtra("crop", "true");
        cropIntent.putExtra("aspectX", 1);
        cropIntent.putExtra("aspectY", 1);
        cropIntent.putExtra("outputX", 300);
        cropIntent.putExtra("outputY", 300);
        cropIntent.putExtra("return-data", false); // 建议设置为false,避免大图崩溃
        cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
        cropIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    
        // 检查是否有能处理裁剪的应用
        if (cropIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(cropIntent, REQUEST_CROP);
        } else {
            Toast.makeText(this, "没有找到支持裁剪的应用", Toast.LENGTH_SHORT).show();
        }
    }
    
  3. 注意事项

    • 避免设置部分系统裁剪应用不支持的参数,比如有些系统不支持outputFormat为PNG,建议用JPEG;
    • 不要设置return-data=true,尤其是裁剪大图时,容易导致内存溢出,用EXTRA_OUTPUT指定输出文件更可靠;
    • 如果是从相册选择的图片Uri本身就是content://格式(比如MediaStore返回的),直接使用即可,不需要转换。

内容的提问来源于stack exchange,提问作者Ehsan.F

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:21:48