Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Smart Lock dialogs on orientation change

I recently integrated Google's Smart Lock for Passwords feature into my app and almost everything is running smoothly as expected.

There is just one small issue I was not able to fix yet: In ResultCallback#onResult, if status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED the following command leads to the presentation of a Google resolution dialog that is asking whether to save the credentials via Smart Lock (see attached image) or which credentials to use, if there are already multiple credentials saved in Smart Lock:

status.startResolutionForResult(getActivity(), REQUEST_CODE_READ);

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

When the resolution dialog is presented, and the user does some orientation changes, then the resolution dialog multiplies, each of them overlapping the others. As a user, you first don’t see that there are multiple copies of the dialog, but if you close the first (by tapping on „Never“ or „Save Password“) then the uppermost dialog disappears, revealing another identical dialog below.

like image 630
Johannes Müller Avatar asked Mar 23 '16 17:03

Johannes Müller


1 Answers

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

See use of the mIsResolving variable in this sample code. Simply save whether there is a pending dialog already when onSaveInstanceState() is called and restore in onCreate(), and guard against calling the API again if so, clearing the state once onActivityResult() is received 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 pitfall for many apps, so we'll look into whether we can support this state in Play Services layer, but for now, using the boolean for the activity is the current and general recommendation for maintaining resolution state.

like image 192
Steven Avatar answered Nov 12 '22 11:11

Steven