Несколько диалогов Smart Lock при изменении ориентации

Недавно я интегрировал функцию Google Smart Lock для паролей в свое приложение, и почти все работает без сбоев, как и ожидалось.

Есть только одна небольшая проблема, которую я пока не смог исправить: в ResultCallback#onResult, если status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED следующая команда приводит к представлению диалогового окна разрешения Google, в котором спрашивается, сохранять ли учетные данные через Smart Lock (см. Прикрепленное изображение) или какие учетные данные использовать, если в Smart Lock уже сохранено несколько учетных данных:

status.startResolutionForResult(getActivity(), REQUEST_CODE_READ);

Диалоговое окно Google Smart Lock: сохранить пароль с помощью Smart Lock? Никогда или сохранять пароль

Когда отображается диалоговое окно разрешения, и пользователь выполняет некоторые изменения ориентации, диалоговое окно разрешения множится, и каждое из них перекрывает другие. Как пользователь, вы сначала не видите, что существует несколько копий диалога, но если вы закроете первую (нажав «Никогда» или «Сохранить пароль»), то самое верхнее диалоговое окно исчезнет, ​​открыв другой идентичный диалог ниже.


person Johannes Müller    schedule 23.03.2016    source источник


Ответы (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, но на данный момент использование логического значения для действия является текущей и общей рекомендацией для поддержания состояния разрешения.

person Steven    schedule 23.03.2016

Я знаю, что это старый вопрос, но в последнее время мне приходится бороться с этой проблемой, в моем случае я использовал 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;
    }
}
person Panczur    schedule 19.03.2017