Повторный запрос разрешения после изменения ориентации
Поскольку Android SDK 23 дает пользователям возможность запретить пользователям доступ к определенным функциям, я хотел бы обновить одно из своих приложений, чтобы запросить разрешения, как описано здесь: https://developer.android.com/preview/features/runtime-permissions.html.
В одном из действий я вставляю SupportMapFragment. Чтобы заставить его работать, вам необходимо иметь разрешение WRITE_EXTERNAL_STORAGE
, поэтому я запрашиваю его при запуске операции, которая приводит к созданию диалога запроса на доступ.
Теперь проблема заключается в том, что, когда диалог все еще открыт, и я поворачиваю устройство, действие будет перезапущено и откроется диалог с новым разрешением, в то время как старый все еще там. Результатом является два из этих диалогов друг на друга, и только один из них полезен.
Есть ли способ избавиться от начатого диалога?
Ответы
Ответ 1
Как сообщает CommonsWare в своем comment, лучшим решением является поместить логическое значение в файл savedInstanceState-Bundle, чтобы узнать, открыто ли диалоговое окно.
Пример:
// true if dialog already open
private boolean alreadyAskedForStoragePermission = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
alreadyAskedForStoragePermission = savedInstanceState.getBoolean(STORAGE_PERMISSION_DIALOG_OPEN_KEY, false);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY, alreadyAskedForStoragePermission);
}
private void checkStoragePermission(){
if(alreadyAskedForStoragePermission){
// don't check again because the dialog is still open
return;
}
if(ActivityCompat.checkSelfPermission(this, STORAGE_PERMISSIONS[0]) != PackageManager.PERMISSION_GRANTED){
// the dialog will be opened so we have to keep that in memory
alreadyAskedForStoragePermission = true;
ActivityCompat.requestPermissions(this, STORAGE_PERMISSIONS, STORAGE_PERMISSION_REQUEST_CODE);
} else {
onStoragePermissionGranted();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case STORAGE_PERMISSION_REQUEST_CODE:
// the request returned a result so the dialog is closed
alreadyAskedForStoragePermission = false;
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
onStoragePermissionGranted();
}
break;
}
}
Ответ 2
Как упоминалось в @user1991776, на самом деле есть недокументированная дополнительная информация, содержащая, есть ли в настоящий момент диалоговое окно разрешения, в Activity:
private static final String HAS_CURENT_PERMISSIONS_REQUEST_KEY =
"android:hasCurrentPermissionsRequest";
Однако есть лучший способ. Когда вы запрашиваете диалог разрешения во второй раз (из-за поворота), Activity
автоматически отменяет старое диалоговое окно, вызывая onRequestPermissionResult()
с пустыми массивами:
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can reqeust only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
}
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}
Или, конечно, это поведение не документировано, потому что это Android, и кто хочет документировать сложное поведение?
В любом случае вы всегда можете запрашивать разрешения в onCreate()
, а затем игнорировать вызовы onRequestPermissionsResult()
с массивами permissions
с нулевой длиной.
Ответ 3
Я предполагаю, что это системный диалог, который вы не можете контролировать. Вместо этого вы можете предотвратить перезагрузку своей активности, если вы перевернете свое устройство.