Multiple Smart Lock dialogs when changing orientation

I recently included the Google Smart Lock for Passwords feature in my application, and pretty much everything is working fine, as expected.

There is only one small problem that I have not been able to fix: In ResultCallback#onResult , if status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED , the following command displays a Google permission dialog that asks if credentials should be saved using Smart Lock (see attached image) or which credentials to use if several credentials have already been saved in Smart Lock:

 status.startResolutionForResult(getActivity(), REQUEST_CODE_READ); 

Google Smart Lock dialog: Save password with Smart Lock? Never or Save Password

When a permission dialog is displayed and the user makes some orientation changes, then the permission dialog is multiplied, each of which overlaps the others. As a user, at first you do not see that there are several copies of the dialog, but if you close the first one (by clicking "Never" or "Save Password"), the topmost dialog will disappear, showing another identical dialog below.

+6
source share
2 answers

You can handle this by maintaining some state between starting and stopping activity.

See the use of the mIsResolving variable in this code sample . Just save if there is a pending dialog already when onSaveInstanceState() is called and restored to onCreate() , and protect it from calling the API again, if so, clear the state after receiving onActivityResult() for the intent.

 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; ... 

This is a common mistake for many applications, so we’ll consider whether we can maintain this state at the Play Services level, but at the moment, using logical for this activity is the current and general recommendation for maintaining the permission state.

+5
source

I know this is an old question, but lately I have to deal with this problem, in my case I used status.startResolutionForResult() in a custom class and I did not have access to onSaveInstanceState() (I could do some then a user callback with an interface, but I didn’t want it), but in my user class I had an action instance, so always before startResolutionForResult() I check mActivity.hasWindowFocus() to see if the activity loses focus, becouse of the dialog which shows if this is true then i call startResolutionForResult() startResolutionForResult() , otherwise I'm not doing anything

 @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; } } 
0
source

All Articles