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

Android 14:用户拒绝照片视频权限后如何再次请求?需用shouldShowPermissionRationale

修复权限拒绝后无法再次发起请求的问题

核心逻辑补充

当用户首次拒绝权限后,系统会根据用户是否勾选「不再询问」,决定是否允许再次弹出权限请求。我们需要通过shouldShowRequestPermissionRationale方法区分两种拒绝场景:临时拒绝(可再次请求)、永久拒绝(需引导至设置页),同时在请求前添加权限用途解释的逻辑。

修改后的完整代码

1. 权限请求方法(添加Rationale检查)

public void requestPhotoAndVideoPermissions() {
    List<String> permissions = new ArrayList<>();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        permissions.add(Manifest.permission.READ_MEDIA_IMAGES);
        permissions.add(Manifest.permission.READ_MEDIA_VIDEO);
    } else {
        permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
    }

    // 筛选需要显示权限说明的权限
    List<String> needRationalePerms = new ArrayList<>();
    for (String perm : permissions) {
        if (ContextCompat.checkSelfPermission(requireContext(), perm) != PackageManager.PERMISSION_GRANTED
                && shouldShowRequestPermissionRationale(perm)) {
            needRationalePerms.add(perm);
        }
    }

    if (!needRationalePerms.isEmpty()) {
        // 弹出弹窗解释权限用途,用户确认后再发起请求
        new AlertDialog.Builder(requireContext())
                .setTitle("需要媒体权限")
                .setMessage("应用需要访问您的照片和视频以完成相关功能,请授予权限。")
                .setPositiveButton("确定", (dialog, which) -> {
                    dialog.dismiss();
                    requestPermissionLauncher.launch(permissions.toArray(new String[0]));
                })
                .setNegativeButton("取消", (dialog, which) -> {
                    dialog.dismiss();
                    onPermissionDenied();
                })
                .show();
    } else {
        // 无需要解释的权限,直接发起请求
        requestPermissionLauncher.launch(permissions.toArray(new String[0]));
    }
}

2. 权限回调(区分拒绝类型)

private ActivityResultLauncher<String[]> requestPermissionLauncher =
        registerForActivityResult(
                new ActivityResultContracts.RequestMultiplePermissions(),
                permissionsMap -> {
                    boolean allGranted = true;
                    boolean isPermanentlyDenied = false;

                    for (Map.Entry<String, Boolean> entry : permissionsMap.entrySet()) {
                        String perm = entry.getKey();
                        Boolean granted = entry.getValue();

                        if (!granted) {
                            allGranted = false;
                            // 判断是否永久拒绝(用户勾选了「不再询问」)
                            if (!shouldShowRequestPermissionRationale(perm)) {
                                isPermanentlyDenied = true;
                            }
                        }
                    }

                    if (allGranted) {
                        Toast.makeText(requireContext(), "权限已授予", Toast.LENGTH_LONG).show();
                        onPermissionGranted();
                    } else {
                        if (isPermanentlyDenied) {
                            // 永久拒绝,引导用户去设置页开启权限
                            new AlertDialog.Builder(requireContext())
                                    .setTitle("权限被永久拒绝")
                                    .setMessage("您已关闭媒体权限的请求提示,请前往应用设置开启权限以使用相关功能。")
                                    .setPositiveButton("去设置", (dialog, which) -> {
                                        dialog.dismiss();
                                        Intent settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                        Uri uri = Uri.fromParts("package", requireContext().getPackageName(), null);
                                        settingsIntent.setData(uri);
                                        startActivity(settingsIntent);
                                    })
                                    .setNegativeButton("取消", (dialog, which) -> {
                                        dialog.dismiss();
                                        onPermissionDenied();
                                    })
                                    .show();
                        } else {
                            // 临时拒绝,提示用户可再次请求
                            Toast.makeText(requireContext(), "权限被拒绝,您可以再次发起请求", Toast.LENGTH_LONG).show();
                            onPermissionDenied();
                        }
                    }
                }
        );

关键逻辑说明

  • 请求前的Rationale检查:shouldShowRequestPermissionRationale返回true时,说明用户之前拒绝过权限但未勾选「不再询问」,此时必须先向用户解释权限用途,再发起请求,否则系统会拦截后续请求。
  • 回调中的拒绝类型区分:在权限回调中,再次调用shouldShowRequestPermissionRationale,若返回false则表示用户永久拒绝了权限,此时只能引导用户前往应用设置页手动开启;若返回true则是临时拒绝,用户可再次触发权限请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 17:28:29