Обнаружение разрешения может быть запрошено или постоянно отклонено

ситуация
Один из моих фрагментов получает доступ к камере. Поэтому, конечно, мне нужно сначала проверить разрешение в моей деятельности, прежде чем я перенаправлю на него. Если пользователь отказывает в разрешении, действие завершается и перенаправляет его на предыдущее действие, в котором он находился.
Кроме того, я хотел бы показать другой фрагмент, когда начинается действие и обнаруживает, что разрешение было навсегда отказано. (Маленький флажок "Никогда не спрашивать" в диалоговом окне разрешения Android)

проблема
Я не мог найти правильный способ обнаружения, было ли в разрешении отказано только один раз, или если флажок "Никогда не спрашивать снова" был установлен в последний раз и запретил разрешение навсегда.
Имейте в виду, что я не хочу знать, что в обратном вызове onRequestPermissionsResult. Мне нужно знать в onCreate моей Деятельности, если разрешение в настоящее время предоставлено, отказано или навсегда отказано.

Что я пробовал
ActivityCompat#shouldShowRequestPermissionRationale Кажется, обнаруживает, было ли в прошлом отказано в разрешении или нет. Он также возвращает true, если ему было отказано только один раз, а не навсегда.

PermissionChecker#checkPermission() Похоже, не заметил никакой разницы между постоянно и только один раз отказано в разрешении государства.

Вопрос
Есть ли какой-либо способ обнаружения, если в разрешении отказано, но все еще можно запросить или если оно постоянно отклонено?

2 ответа

Решение

Есть ли какой-нибудь способ определить, отказано ли в разрешении, но все еще может быть запрошено, или если ему постоянно отказано?

К сожалению, нет официального API для обнаружения, если в разрешении постоянно отказано, когда пользователь выбирает "Никогда не спрашивать"

Есть одна работа, которая использует shouldShowRequestPermissionRationale, Создайте SharedPreference со значением по умолчанию false и хранить значение, возвращаемое shouldShowRequestPermissionRationale в этом. Перед обновлением значения проверьте, было ли установлено значение true, Если бы это было true тогда не обновляйте его.

Всякий раз, когда вы хотите проверить разрешение, получите значение от SharedPreference и текущее значение, возвращаемое shouldShowRequestPermissionRationale, Если shouldShowRequestPermissionRationale возвращается false но значение от SharedPreference является true, вы можете сделать вывод, что Never ask again был выбран пользователем.

Вы можете обратиться к моему блогу, где я описал этот подход.

shouldShowRequestPermissionRationale возвращает истину или ложь в зависимости от предпочтений пользователя в предыдущем запросе разрешения.

Если пользователь просто отказал в разрешении (не навсегда) shouldShowRequestPermissionRationale вернусь true. Если отказано в разрешении навсегда, возвращаетсяfalse. И фокус в том, что даже пользователь разрешил разрешение, тогдаshouldShowRequestPermissionRationale вернусь false.

Таким образом, мы можем комбинировать оба условия, чтобы выбрать вариант "Никогда больше не спрашивать" или нет.

Итак, если пользователю не разрешено разрешение и shouldShowRequestPermissionRationale возвращается false тогда это означает, что пользователь выберет никогда больше не запрашивать разрешение.

Вы можете использовать Dexter library, библиотека, которая упрощает обработку разрешений Android. Я решил проблему так:

private void checkUserPermission() {
    Dexter.withActivity(this)
            .withPermissions(
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.CALL_PHONE,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.CAMERA
            ).withListener(new MultiplePermissionsListener() {
        @Override
        public void onPermissionsChecked(MultiplePermissionsReport report) {
            //check if all permission are granted
            if (report.areAllPermissionsGranted()) {
                initSocket();
            } else {
                List<PermissionDeniedResponse> responses = report.getDeniedPermissionResponses();
                StringBuilder permissionsDenied = new StringBuilder("Permissions denied: ");
                for (PermissionDeniedResponse response : responses) {
                    permissionsDenied.append(response.getPermissionName()).append(" ") ;
                }
                showInfoMessageToast(permissionsDenied.toString());
            }

            if (report.isAnyPermissionPermanentlyDenied()) {
                //permission is permanently denied navigate to user setting
                AlertDialog.Builder dialog = new AlertDialog.Builder(HomeActivity.this)
                        .setTitle("Need Permissions")
                        .setMessage("This application need to use some permissions, " +
                                "you can grant them in the application settings.")
                        .setPositiveButton("GOTO SETTINGS", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.cancel();
                                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package", getPackageName(), null);
                                intent.setData(uri);
                                startActivityForResult(intent, 101);
                            }
                        })
                        .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.cancel();
                            }
                        });
                dialog.show();

            }
        }

        @Override
        public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
            token.continuePermissionRequest();
        }
    })
            .onSameThread()
            .check();

}

то есть после создания импорта таким образом

import com.karumi.dexter.Dexter;

Настройка того, чего вы хотите достичь, должна решить вашу проблему.

Вы можете проверить разрешение,

if (permissionStatus.getBoolean(Manifest.permission.CALL_PHONE, false)){}

Обычно я проверяю разрешение, используя следующее,

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {

   if (ActivityCompat.shouldShowRequestPermissionRationale(TrackActivity.this, Manifest.permission.CALL_PHONE)) {
                ActivityCompat.requestPermissions(TrackActivity.this, new String[]{Manifest.permission.CALL_PHONE}, EXTERNAL_STORAGE_PERMISSION_CONSTANT);
       } else if (permissionStatus.getBoolean(Manifest.permission.CALL_PHONE, false)) {

       } else {
                ActivityCompat.requestPermissions(TrackActivity.this, new String[]{Manifest.permission.CALL_PHONE}, EXTERNAL_STORAGE_PERMISSION_CONSTANT);
       }
            SharedPreferences.Editor editor = permissionStatus.edit();
            editor.putBoolean(Manifest.permission.CALL_PHONE, true);
            editor.apply();
   }

Чтобы определить, что пользователю постоянно отказано в разрешении или нет, нам не нужна дополнительная логика, просто используйте ее.

if (ActivityCompat.shouldShowRequestPermissionRationale(UserEditProfileActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)){
                // not permanently denied 
            }
            else {
               // permanently denied 
            }

это оно.

Другие вопросы по тегам