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

Android 11如何读取相机拍摄图片?更新裁剪库后onActivityResult返回null

问题根因

  1. Android 7.0开始就禁止跨应用传递file://类型的Uri,Android 11对分区存储的管控进一步收严,你原有代码里用Uri.fromFile生成的Uri无法被相机应用正常识别写入,导致拍照后返回数据异常。
  2. 你注释的FileProvider调用参数错误,且没有给相机应用授予临时Uri访问权限,同时预先指定拍照输出路径时,系统本身就不会在onActivityResult的Intent里携带数据,返回null属于预期行为。

解决方案

1. 配置FileProvider

首先在AndroidManifest.xml的<application>标签内添加Provider声明:

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

然后在res/xml目录下新建file_paths.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-cache-path
        name="external_cache"
        path="." />
</paths>

这里配置的路径对应你代码里用的应用外存缓存目录,保证FileProvider可以正常生成该路径下的Uri。

2. 修正Uri生成方法

修改你的getCaptureImageOutputUri方法,正确使用FileProvider生成Uri:

public static Uri getCaptureImageOutputUri(@NonNull Context context) {
    Uri outputFileUri = null;
    File getImage = context.getExternalCacheDir();
    if (getImage != null) {
        File outputFile = new File(getImage.getPath(), "pickImageResult.jpeg");
        // 注意这里的authorities要和Manifest里配置的一致,必须加.fileprovider后缀
        outputFileUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", outputFile);
    }
    return outputFileUri;
}

3. 调整裁剪库调用逻辑

启动裁剪的时候主动传入你生成的输出Uri,同时不需要依赖返回Intent携带数据,先把生成的Uri保存为全局变量:

// 先生成拍照输出Uri,保存为全局变量方便后续读取
Uri captureUri = getCaptureImageOutputUri(AbcActivity.this);
CropImage
        .activity()
        .setGuidelines(CropImageView.Guidelines.ON)
        .setBorderCornerColor(Color.RED)
        .setBorderLineColor(Color.CYAN)
        .setAutoZoomEnabled(true)
        .setRequestedSize(300, 300)
        // 主动指定拍照输出的Uri
        .setOutputUri(captureUri)
        .start(AbcActivity.this);

4. 修正onActivityResult处理逻辑

预先指定输出路径的场景下,返回的Intent为null是正常情况,直接读取你之前生成的captureUri即可:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
        CropImage.ActivityResult result = CropImage.getActivityResult(data);
        if (resultCode == RESULT_OK) {
            // 优先读取返回的Uri,为空的话直接读你预先定义的captureUri
            Uri resultUri = result != null ? result.getUri() : captureUri;
            // 后续处理resultUri即可
        } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
            Exception error = result.getError();
            // 处理错误逻辑
        }
    }
}

额外注意事项

  • 原版ArthurHub的Android Image Cropper库已经停止维护,未适配Android11以上系统,建议切换到社区维护的分支,避免后续出现更多兼容性问题。
  • Android11及以上版本不需要申请存储权限即可读写应用私有目录(包括内部存储、外存缓存、外存私有目录),不需要额外申请READ_EXTERNAL_STORAGE等权限。
  • 如果需要访问其他应用的公共媒体文件,再按需申请对应媒体权限即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 04:06:05