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

Android多API级别下相机与存储权限适配问题咨询

适配多API版本的相机+存储权限解决方案

没错,你确实需要针对不同API版本调整权限和相机存储代码——Android 6.0(API 23)引入了动态权限机制,而API 24又对文件Uri的安全访问做了限制,这两个变化就是你遇到问题的核心原因。我来一步步帮你适配到所有兼容设备:

问题根源拆解

  • API 22及以下:只要在AndroidManifest.xml里声明权限就够了,系统会在安装时自动授予所有声明的权限。
  • API 23+:像CAMERA、WRITE_EXTERNAL_STORAGE这类危险权限,必须在运行时主动向用户申请,用户同意后才能使用相关功能。
  • API 24+:直接用Uri.fromFile()会抛出FileUriExposedException,因为Android禁止向其他应用暴露file://格式的Uri,必须用FileProvider生成安全的content://格式Uri。

具体适配步骤

1. 处理动态权限申请

首先添加权限检查方法,判断是否已获得所需权限:

private boolean hasRequiredPermissions() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
    }
    // API22及以下默认已授权
    return true;
}

修改startCameraIntent方法,先检查权限再启动相机:

private static final int PERMISSION_REQUEST_CODE = 100;
private static final int CAMERA_INTENT = 101;
private File takenPicture;

public void startCameraIntent() {
    if (hasRequiredPermissions()) {
        // 权限已授权,启动相机逻辑
        launchCamera();
    } else {
        // 未授权则发起权限请求
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(
                    new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_CODE
            );
        }
    }
}

重写权限申请结果处理方法:

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

2. 适配API24+的文件Uri安全访问

第一步:在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>

第二步:创建file_paths.xml配置文件

在res/xml目录下新建该文件(无xml目录则手动创建),内容如下:

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

这个配置允许FileProvider共享APP私有外部存储的Pictures目录。

第三步:修改相机启动逻辑,用FileProvider生成Uri

private void launchCamera() {
    // 使用APP私有外部存储,API29+无需WRITE权限也能访问
    takenPicture = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "image.jpg");
    Uri tempURI;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // API24及以上用FileProvider生成安全Uri
        tempURI = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", takenPicture);
    } else {
        // API23及以下保留原方式
        tempURI = Uri.fromFile(takenPicture);
    }

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, tempURI);
    intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
    // 给相机应用授予Uri读写权限
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    startActivityForResult(intent, CAMERA_INTENT);
}

额外注意事项

  • 确保项目依赖了AndroidX库(推荐使用),比如androidx.core:core(Java项目)或androidx.core:core-ktx(Kotlin项目)。
  • 测试时记得在API23+设备上验证权限请求流程,用户拒绝权限后要给出友好提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:30:19