Несколько диалогов Smart Lock при смене ориентации
Недавно я включил в приложение функцию Smart Lock для паролей от Google, и почти все работает, как и ожидалось.
Есть только одна небольшая проблема, которую я пока не смог исправить: ResultCallback#onResult
, если status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED
Следующая команда приводит к открытию диалогового окна разрешения Google, в котором спрашивается, сохранять ли учетные данные через Smart Lock (см. прикрепленное изображение) или какие учетные данные использовать, если в Smart Lock уже сохранено несколько учетных данных:
status.startResolutionForResult(getActivity(), REQUEST_CODE_READ);
Когда отображается диалоговое окно разрешения, и пользователь выполняет некоторые изменения ориентации, диалоговое окно разрешения умножается, причем каждое из них перекрывает другие. Как пользователь, вы сначала не видите, что есть несколько копий диалога, но если вы закроете первую (нажав "Никогда" или "Сохранить пароль"), то самый верхний диалог исчезнет, открыв еще одно идентичное диалоговое окно ниже.
2 ответа
Вы можете справиться с этим, поддерживая некоторое состояние между началом и прекращением действия.
Смотрите использование mIsResolving
переменная в этом примере кода. Просто сохраните, есть ли уже ожидающий диалог, когда onSaveInstanceState()
называется и восстановить в onCreate()
и защититься от повторного вызова API, если это так, очистив состояние один раз onActivityResult()
получено для намерения.
private void resolveResult(Status status, int requestCode) {
// We don't want to fire multiple resolutions at once since that can result
// in stacked dialogs after rotation or another similar event.
if (mIsResolving) {
Log.w(TAG, "resolveResult: already resolving.");
return;
}
if (status.hasResolution()) {
try {
status.startResolutionForResult(MainActivity.this, requestCode);
mIsResolving = true;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
if (savedInstanceState != null) {
mIsResolving = savedInstanceState.getBoolean(KEY_IS_RESOLVING);
}
...
@Override
protected void onSaveInstanceState(Bundle outState) {
...
outState.putBoolean(KEY_IS_RESOLVING, mIsResolving);
...
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
...
mIsResolving = false;
...
Это распространенная ошибка для многих приложений, поэтому мы рассмотрим, можем ли мы поддерживать это состояние в слое Play Services, но сейчас использование логического значения для активности является текущей и общей рекомендацией для поддержания состояния разрешения.
Я знаю, что это старый вопрос, но недавно мне пришлось бороться с этим вопросом, в моем случае я использовал status.startResolutionForResult()
в пользовательском классе, и у меня не было никакого доступа к onSaveInstanceState()
(Я мог сделать некоторый пользовательский обратный вызов с интерфейсом, но я не хотел), но в моем пользовательском классе у меня был экземпляр действия, поэтому всегда перед вызовом startResolutionForResult()
я проверяю mActivity.hasWindowFocus()
чтобы увидеть, если активность теряет фокус, из-за диалога, который показывает, если это правда, то я звоню startResolutionForResult()
иначе я ничего не делаю
@Override
public void onResult(@NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()){
case LocationSettingsStatusCodes.SUCCESS:
getLocation();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
if (mActivity.hasWindowFocus()) {
try {
status.startResolutionForResult(mActivity, SETTINGS_CHECK);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
mReceiver.unableToObtainLocation();
break;
}
}