You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 16应用存储权限请求失效致崩溃问题求助

问题排查与解决建议

核心问题原因

Android 13(API 33)开始彻底废弃了READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限,你的目标设备是Android 16(API 35),系统会直接忽略对这两个旧权限的请求——这就导致你的代码能检测到权限未授予,但无法触发申请弹窗,最终App因无权限访问存储而崩溃。

具体解决方案

1. 更新Manifest权限声明

打开AndroidManifest.xml,根据你的业务需求替换旧存储权限:

  • 若仅需访问媒体文件(图片/视频/音频),添加以下权限:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
  • 若需访问所有文件(非媒体目录),添加特殊权限:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
    android:minSdkVersion="30" />

2. 修改权限请求逻辑

根据系统版本动态适配请求的权限,调整你原有的requestPermissions()方法:

private void requestPermissions() {
    List<String> permissionsToRequest = new ArrayList<>();

    // 位置权限(不受版本影响,正常请求)
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        permissionsToRequest.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    }
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        permissionsToRequest.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }

    // 网络状态权限(正常请求)
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
        permissionsToRequest.add(Manifest.permission.ACCESS_NETWORK_STATE);
    }

    // 存储权限版本适配
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        // API 33+:请求对应媒体权限(按需选择)
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
            permissionsToRequest.add(Manifest.permission.READ_MEDIA_IMAGES);
        }
        // 如需视频/音频权限,同上添加对应权限
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // API 23-32:保留旧存储权限请求逻辑
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionsToRequest.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionsToRequest.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
    }

    // 发起普通权限请求
    if (!permissionsToRequest.isEmpty()) {
        ActivityCompat.requestPermissions(
                this,
                permissionsToRequest.toArray(new String[0]),
                PERMISSION_REQUEST_CODE
        );
    }

    // 特殊处理全文件访问权限(如果需要)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        if (!Environment.isExternalStorageManager()) {
            // 跳转到系统设置页面让用户手动开启
            Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
            intent.setData(Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, 1001); // 自定义请求码
        }
    }
}

3. 确保权限授予后再执行文件操作

你的App当前可能在调用requestPermissions()后立刻执行文件访问逻辑,导致权限未授予就崩溃。需要在权限回调中确认授权后,再启动文件处理流程:

@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) {
            // 所有普通权限已授予,启动文件操作
            startFileProcessing();
        } else {
            Toast.makeText(this, "部分权限未授予,App无法正常运行", Toast.LENGTH_SHORT).show();
        }
    }
}

// 处理全文件访问权限的回调
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1001) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (Environment.isExternalStorageManager()) {
                startFileProcessing();
            } else {
                Toast.makeText(this, "全文件访问权限未开启,无法访问所有文件", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

// 把你的文件访问逻辑放在这个方法里
private void startFileProcessing() {
    // 执行读取存储文件的代码
}

4. 补充说明

  • MANAGE_EXTERNAL_STORAGE属于特殊权限,Google Play对该权限的审核非常严格,仅允许文件管理器、备份工具等特定类型App使用。如果你的App只是访问媒体文件,优先使用媒体权限。
  • 建议迁移到Activity Result API替代旧的requestPermissionsonRequestPermissionsResult,兼容性更强。

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

火山引擎 最新活动