Обнаружение разрешения может быть запрошено или постоянно отклонено
ситуация
Один из моих фрагментов получает доступ к камере. Поэтому, конечно, мне нужно сначала проверить разрешение в моей деятельности, прежде чем я перенаправлю на него. Если пользователь отказывает в разрешении, действие завершается и перенаправляет его на предыдущее действие, в котором он находился.
Кроме того, я хотел бы показать другой фрагмент, когда начинается действие и обнаруживает, что разрешение было навсегда отказано. (Маленький флажок "Никогда не спрашивать" в диалоговом окне разрешения 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();
}
Эта библиотека работает хорошо: https://github.com/permissions-dispatcher/PermissionsDispatcher
Также полезна эта средняя статья: определение того, можно ли запросить разрешение или в нем навсегда отказано
Чтобы определить, что пользователю постоянно отказано в разрешении или нет, нам не нужна дополнительная логика, просто используйте ее.
if (ActivityCompat.shouldShowRequestPermissionRationale(UserEditProfileActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)){
// not permanently denied
}
else {
// permanently denied
}
это оно.