Android外部存储权限请求:用户拒绝后如何重新发起询问
解决Android权限拒绝后无法再次请求的问题
我来帮你搞定这个权限请求的问题!其实核心原因是Android的权限机制:当用户第一次拒绝权限后,再次请求时系统会弹出「不再询问」的选项,如果用户勾选了它,直接调用requestPermissions()就不会再触发系统权限对话框了。我们需要分场景处理,确保每次点击按钮都能有合理的响应。
第一步:完善权限检查方法
先确保你的checkPermission()能正确检查外部存储权限:
private boolean checkPermission() { // 针对Android 6.0+,检查读写外部存储权限 int readPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); int writePerm = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); return readPerm == PackageManager.PERMISSION_GRANTED && writePerm == PackageManager.PERMISSION_GRANTED; }
第二步:修改权限请求逻辑,加入解释与引导
修改你的requestPermission()方法,增加权限解释对话框,以及处理「不再询问」的情况:
private void requestPermission() { // 判断是否需要向用户解释权限用途(用户之前拒绝过但没勾选不再询问) boolean needRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (needRationale) { // 先弹对话框说明权限用途,再发起请求 new AlertDialog.Builder(this) .setTitle("需要存储权限") .setMessage("我们需要存储权限来保存或读取您的文件,请允许这个权限") .setPositiveButton("好的", (dialog, which) -> { // 发起权限请求 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); // 100是自定义的请求码 }) .setNegativeButton("取消", null) .show(); } else { // 直接请求权限(首次请求,或用户已勾选不再询问) ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); } }
第三步:处理权限请求回调
重写onRequestPermissionsResult方法,根据用户的选择做出不同处理:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 100) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (allGranted) { // 权限全部授予,执行你的业务逻辑 Toast.makeText(this, "权限已授予,可正常操作", Toast.LENGTH_SHORT).show(); // 这里写你需要执行的代码 } else { // 判断用户是否勾选了「不再询问」 boolean canRequestAgain = false; for (String perm : permissions) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, perm)) { canRequestAgain = true; break; } } if (!canRequestAgain) { // 用户勾选了不再询问,引导去应用设置开启权限 new AlertDialog.Builder(this) .setTitle("权限被拒绝") .setMessage("您已拒绝存储权限并勾选了不再询问,请前往应用设置手动开启") .setPositiveButton("去设置", (dialog, which) -> { // 跳转到当前应用的设置页面 Intent settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); settingsIntent.setData(uri); startActivity(settingsIntent); }) .setNegativeButton("取消", null) .show(); } else { // 用户只是拒绝,没勾选不再询问,提示可再次尝试 Toast.makeText(this, "权限被拒绝,您可以再次点击按钮请求", Toast.LENGTH_SHORT).show(); } } } }
第四步:按钮点击事件的处理
确保你的按钮点击逻辑调用上述方法:
// 假设按钮id是btn_request_storage Button requestBtn = findViewById(R.id.btn_request_storage); requestBtn.setOnClickListener(v -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkPermission()) { // 权限已存在,直接执行逻辑 Toast.makeText(this, "权限已拥有", Toast.LENGTH_SHORT).show(); } else { // 发起权限请求 requestPermission(); } } else { // Android 6.0以下无需动态请求,直接执行逻辑 Toast.makeText(this, "无需请求权限,可直接操作", Toast.LENGTH_SHORT).show(); } });
关键逻辑说明
shouldShowRequestPermissionRationale:这个方法返回true时,表示用户之前拒绝过权限但没勾选「不再询问」,此时我们可以先解释权限用途再请求;返回false时,要么是首次请求,要么是用户已经勾选了「不再询问」。- 当用户勾选「不再询问」后,系统不会再弹出权限对话框,这时候我们需要引导用户去应用设置页面手动开启权限,这是唯一能让用户重新授予权限的方式。
这样修改后,不管用户是第一次拒绝、多次拒绝,还是勾选了不再询问,点击按钮都能得到对应的响应,不会出现点击后毫无反应的情况。
内容的提问来源于stack exchange,提问作者DomingoMG




