Android 动态权限申请 | 2次不允许权限导致申请权限不再弹框

一、问题描述

Android 14平台,录音应用需要申请麦克风权限,点击录音按钮时候会先检测是否有麦克风权限,如果有则直接开始录音,否则申请麦克风权限,当用户测试时候2次出现权限申请弹框都都选择不允许,第三次次就不再权限申请弹框。

请添加图片描述

二、问题分析

这里需要引入一个方法ActivityCompat.shouldShowRequestPermissionRationale(activity, permission),大部分应用申请动态权限时,都没有用这个做判断是否应该弹框,系统默认是返回true,但用户拒绝并不再询问或者2次不允许,此时就会一直返回false

shouldShowRequestPermissionRationale() 是 Android 系统中的一个 API,用于检查用户是否应该看到权限请求解释. 当您第一次请求一个危险权限时,系统会自动显示一个解释对话框,说明该权限的用途以及为什么您的应用需要它。

shouldShowRequestPermissionRationale() 方法可以帮助您确定是否应该再次显示该解释对话框。 该方法会返回一个 boolean 值:

  • true: 表示用户应该看到权限请求解释。
  • false: 表示用户不应该看到权限请求解释。
    /**
     * Gets whether you should show UI with rationale for requesting a permission.
     * You should do this only if you do not have the permission and the context in
     * which the permission is requested does not clearly communicate to the user
     * what would be the benefit from granting this permission.
     * <p>
     * For example, if you write a camera app, requesting the camera permission
     * would be expected by the user and no rationale for why it is requested is
     * needed. If however, the app needs location for tagging photos then a non-tech
     * savvy user may wonder how location is related to taking photos. In this case
     * you may choose to show UI with rationale of requesting this permission.
     * </p>
     *
     * @param activity The target activity.
     * @param permission A permission your app wants to request.
     * @return Whether you can show permission rationale UI.
     *
     * @see #checkSelfPermission(android.content.Context, String)
     * @see #requestPermissions(android.app.Activity, String[], int)
     */
    public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity,
            @NonNull String permission) {
        if (Build.VERSION.SDK_INT >= 23) {
            return activity.shouldShowRequestPermissionRationale(permission);
        }
        return false;
    }

获取是否应显示 UI 以及请求权限的理由。仅当您没有该权限并且请求权限的上下文无法清楚地向用户传达授予此权限有何好处时,您才应执行此操作

当请求权限被拒绝时,如果只是普通的拒绝,调用这个方法的返回值是true;如果是“拒绝并不再询问”或者2次不允许,则返回值是false,意思是这时都一直拒绝了,不需要显示请求权限理由了,这个时候调用requestPermissions去申请权限时就不会在出现权限弹框了。

三、解决方案

在 Android 中,应用程序需要申请 RECORD_AUDIO 权限才能使用设备的麦克风进行录音。以下是申请 RECORD_AUDIO 权限的代码示例:

1. 在 AndroidManifest.xml 文件中声明权限:

<uses-permission android:name="android.permission.RECORD_AUDIO" />

2. 在代码中检查权限:

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
    // 权限未授权,请求权限
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUSET_CODE);
} else {
    // 权限已授权,可以开始录音
    // ...
}

3. 处理权限请求结果:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case FmUtils.REQUSET_CODE:
            if (permissions.length > 0) {
                for (int i = 0; i < permissions.length; i++) {
                    if (grantResults.length > 0 && grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                        // 权限授权失败
                        if (ActivityCompat.shouldShowRequestPermissionRationale(RecordingActivity.this, permission)) {
                            // 返回 true,Toast 提示
                            Toast.makeText(this, "无法访问麦克风,请授权后再试", Toast.LENGTH_SHORT).show();
                        } else {
                            // 返回 false,需要显示对话框引导跳转到设置手动授权
                            showDialog(RecordingActivity.this);
                        }
                        return;
                    }
                }
                // 权限授权成功,可以开始录音
                // ...
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

4. 引导用户跳转到APP设置界面:

public static void showDialog(final Activity activity) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        Resources resources = activity.getResources();
        builder.setMessage(resources.getString(R.string.setting_permission_content));
        builder.setNegativeButton(resources.getString(R.string.cancel),
                (dialog, which) -> {
                    dialog.dismiss();
                });
        builder.setPositiveButton(activity.getString(R.string.setting_permission),
                (dialog, which) -> {
                    dialog.dismiss();
                    Intent settingsIntent = new Intent();
                    settingsIntent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    settingsIntent.setData(Uri.parse("package:" + activity.getPackageName()));
                    activity.startActivity(settingsIntent);
                });
        builder.setCancelable(false);
        builder.show();
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 10 及以上的版本中,权限申请弹框的样式已经由系统进行了重构,并且提供了更多的自定义选项。如果您想要自定义权限申请弹框的样式,可以使用 `PermissionControllerCompat` 类中的 `createPermissionDialog()` 方法来创建一个自定义的弹框。具体的代码可以参考以下示例: ```java AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(title); builder.setMessage(message); builder.setPositiveButton(android.R.string.ok, listener); builder.setNegativeButton(android.R.string.cancel, null); AlertDialog dialog = builder.create(); Window window = dialog.getWindow(); window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 300, context.getResources().getDisplayMetrics()); int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200, context.getResources().getDisplayMetrics()); window.setLayout(width, height); return dialog; ``` 在上述代码中,`context` 参数表示上下文;`title` 和 `message` 分别表示弹框的标题和内容;`listener` 表示点击确定按钮后的回调函数。弹框的样式可以通过设置 `AlertDialog.Builder` 对象来实现,包括标题、内容、按钮等。在最后,调用 `create()` 方法创建 `AlertDialog` 对象,并设置其大小和位置。 需要注意的是,为了在 Android 10 及以上的版本中能够显示弹框,需要将窗口类型设置为 `TYPE_APPLICATION_OVERLAY`,并添加相关的标志位。此外,需要在 AndroidManifest.xml 文件中添加 `android.permission.SYSTEM_ALERT_WINDOW` 权限

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值