18
votes

I use OAuth to let users sign in to the android app via Google account. When the user taps the Google login button for the first time, it produces a dialog to choose the account. Again, when the user logs out and decides to login with different Google account, it doesn't prompt to choose the account, it logs in the account the user had chose the previous time

'

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.login);
    initialize();
    Firebase.setAndroidContext(this);
    ref=new Firebase("https://texter10c.firebaseio.com");

    loginButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            progressDialog.setMessage("Logging in !");
            progressDialog.setTitle("Hang on!");
            progressDialog.show();

            ref.authWithPassword(emailField.getText().toString(), passwordField.getText().toString(), new Firebase.AuthResultHandler() {
                @Override
                public void onAuthenticated(AuthData authData) {
                    Log.e("Authenticated","Authenticated");
                    getUserIdandLogin();
                }

                @Override
                public void onAuthenticationError(FirebaseError firebaseError) {
                    progressDialog.dismiss();
                    Toast.makeText(LoginActivity.this, firebaseError.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    });

    signupButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(LoginActivity.this, SignupActivity.class);
            startActivity(intent);
        }
    });

    googleSignInButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            progressDialog.setTitle("Contacting Google");
            progressDialog.setMessage("Logging you in");
            progressDialog.show();
            if(!mGoogleApiClient.isConnected())
            mGoogleApiClient.connect();
        }
    });

}

private void getGoogleToken(){

    AsyncTask<Void,Void,String> task=new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            final String scopes="oauth2:"+"https://www.googleapis.com/auth/plus.login"+" "+"https://www.googleapis.com/auth/plus.me";
            try {
                if(!mGoogleApiClient.isConnected())
                {
                    mGoogleApiClient.connect();
                }
                googleAccessToken= GoogleAuthUtil.getToken(LoginActivity.this,Plus.AccountApi.getAccountName(mGoogleApiClient),scopes);
                Log.e("AccessToken",googleAccessToken+"");
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            catch (GoogleAuthException e)
            {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                ref.authWithOAuthToken("google", googleAccessToken, new Firebase.AuthResultHandler() {
                    @Override
                    public void onAuthenticated(final AuthData authData) {
                        try {
                            Log.e("Firebase", "Google Authentication Success");
                            Log.e("Username", authData.getProviderData().get("displayName").toString());
                            Log.e("Id", authData.getProviderData().get("id").toString());


                            Firebase googleUserRef = ref.child("UserDetails/names/" + authData.getProviderData().get("id").toString());
                            Map<String, String> googleUserMap = new HashMap<String, String>();
                            googleUserMap.put("Username", authData.getProviderData().get("displayName").toString());
                            final String UserID = "GoogleUser" + authData.getProviderData().get("displayName") + authData.getProviderData().get("id");
                            googleUserMap.put("UserId", UserID);

                            googleUserRef.setValue(googleUserMap, new Firebase.CompletionListener() {
                                @Override
                                public void onComplete(FirebaseError firebaseError, Firebase firebase) {
                                    progressDialog.dismiss();
                                    dataStore.setCurrentUserName(authData.getProviderData().get("displayName").toString());
                                    dataStore.setCurrentUserID(UserID);
                                    storeDatainSharedPreferences();
                                    Intent intent = new Intent(LoginActivity.this, DialogActivity.class);
                                    startActivity(intent);
                                }
                            });
                        }
                        catch (NullPointerException e)
                        {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onAuthenticationError(FirebaseError firebaseError) {
                        Log.e("GogoleAuthFailed", firebaseError.getMessage());

                    }
                });
            }
            catch (NullPointerException e)
            {
                Log.e("Accesstoken problem",e.getMessage());
            }
        }
    };
    task.execute();
}

public void getUserIdandLogin()
{
    dataStore.userDialogMap=new ArrayList<Map<String,String>>();
    dataStore.generatedChatIds=new ArrayList<>();
    Firebase refUser=ref.child("UserDetails/names");
    refUser.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            Map<String, String> map = new HashMap<String, String>();
            map = dataSnapshot.getValue(Map.class);
            try{
                if (map.get("Email").equals(emailField.getText().toString()))
                {
                    Toast.makeText(LoginActivity.this, "Successfilly Logged in", Toast.LENGTH_SHORT).show();
                    dataStore.setCurrentUserName(map.get("Username"));
                    dataStore.setCurrentUserID(map.get("UserId"));
                    intent=new Intent(LoginActivity.this,DialogActivity.class);
                    startActivity(intent);
                    storeDatainSharedPreferences();
                    progressDialog.dismiss();
                }

            }
            catch (NullPointerException e)
            {
                Log.e("NullPointerGUser",e.getMessage());
            }
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });
}

private void storeDatainSharedPreferences() {
    try {
        SharedPreferences.Editor editor = getSharedPreferences(NEW_PREFS, MODE_PRIVATE).edit();
        editor.putString("CurrentUsername", dataStore.getCurrentUserName());
        editor.putString("CurrentUserId", dataStore.getCurrentUserID());
        editor.commit();
    }
    catch (NoSuchElementException e)
    {
        new AlertDialog.Builder(LoginActivity.this).setMessage("There was an error whil logging in")
                .setTitle("Little Problem here!").setPositiveButton("Retry", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent=new Intent(LoginActivity.this,LoginActivity.class);
                removeDatainSharedPreferences();
                mGoogleApiClient.disconnect();
                startActivity(intent);
            }
        }).show();
    }
}

private void removeDatainSharedPreferences() {
    SharedPreferences.Editor editor = getSharedPreferences(NEW_PREFS, MODE_PRIVATE).edit();
    editor.remove("CurrentUsername");
    editor.remove("CurrentUserId");
    editor.commit();
}


private void initialize() {
    emailInputLayout=(TextInputLayout)findViewById(R.id.emailInputLayout);
    emailField=(EditText)findViewById(R.id.emailField);
    passwordField=(EditText)findViewById(R.id.passwordField);
    passwordInputLayout=(TextInputLayout)findViewById(R.id.passwordInputLayout);
    loginButton=(Button)findViewById(R.id.loginButton);
    emailInputLayout.setHint("Email");
    passwordInputLayout.setHint("Password");
    progressDialog=new ProgressDialog(LoginActivity.this);
    signupButton=(TextView)findViewById(R.id.signupButton);
    forgotPasswordButton=(TextView)findViewById(R.id.forgotPasswordField);
    googleSignInButton=(SignInButton)findViewById(R.id.googleSignInButton);
    googleSignInButton.setColorScheme(SignInButton.COLOR_AUTO);
    forgotPasswordButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent=new Intent(LoginActivity.this,ForgotPasswordActivity.class);
            startActivity(intent);
        }
    });

    SharedPreferences sharePreferences=getSharedPreferences(NEW_PREFS,MODE_PRIVATE);
    if(!sharePreferences.getString("CurrentUsername","null").equals("null")) {
        Log.e("SharedPreferences", sharePreferences.getString("CurrentUsername", "null"));
        Log.e("SharedPreferences",sharePreferences.getString("CurrentUserId",null));
        Intent intent=new Intent(LoginActivity.this,DialogActivity.class);
        startActivity(intent);
    }

    mGoogleApiClient=new GoogleApiClient.Builder(this)
            .addApi(Plus.API)
            .addScope(Plus.SCOPE_PLUS_LOGIN)
            .addScope(Plus.SCOPE_PLUS_PROFILE)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this).build();


   if(!isNetworkAvailable())
   {
      snackbar=Snackbar.make(findViewById(android.R.id.content),"You are offline",Snackbar.LENGTH_INDEFINITE)
              .setAction("Retry", new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      if(!isNetworkAvailable())
                          dismissSnackBar();
                      else
                          snackbar.show();
                  }

              });
       snackbar.show();
   }

}

private void dismissSnackBar() {
    snackbar.dismiss();
}


private boolean isNetworkAvailable()
{
    ConnectivityManager manager=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkIngo=manager.getActiveNetworkInfo();
    return networkIngo!=null&& networkIngo.isConnected();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
        Log.e("GoogleApi","Connected");
        getGoogleToken();
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.e("GoogleApi",connectionResult.toString());
    if(!connectionResult.hasResolution())
    {
        GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(),LoginActivity.this,0).show();
    }
    if(connectionResult.isSuccess())
    {
        getGoogleToken();
    }
    try
    {
        connectionResult.startResolutionForResult(this,100);
    }
    catch (IntentSender.SendIntentException e)
    {
        e.printStackTrace();
    }
}

}

`

14
Paste in relevant code so we can help, please! - Matthew
Fine ! Give me a minute ! - Dinesh Adhithya
Disconnect the mGoogleApiClient right after you get login details. As you don't need it further. - Janki Gadhiya
It didn't work.. it uses the same account the next time I try to login. Only when i clear the the cache data in the settings, it prompts to choose the account. - Dinesh Adhithya
you need to explicitly signout your user. - rushabhshah1693

14 Answers

15
votes

Just add this signIn() method after getting data from the intent.

Intent signInIntent=Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
mGoogleApiClient.clearDefaultAccountAndReconnect(); 
14
votes

You needed to log out the user from google client.

public void signOut() {
   mAuth.signOut();
   mGoogleSignInClient.signOut();
   LoginManager.getInstance().logOut();
}

Where

private FirebaseAuth mAuth;
private GoogleSignInClient mGoogleSignInClient;

and

mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
mAuth = FirebaseAuth.getInstance();
12
votes

You have to just clear pre-signed in accounts. To do so, add the following as first line under signIn() function: mGoogleSignInClient.signOut();

 private void signIn() {
    // clearing previous signin caches
       mGoogleSignInClient.signOut();

    //getting the google signin intent
    Intent signInIntent = mGoogleSignInClient.getSignInIntent();
    //starting the activity for result
    startActivityForResult(signInIntent, RC_SIGN_IN);
}
6
votes

The simplest way is to logout the client after you handle your result (onActivityResult). Just make sure that the client is connected before you trigger the logout. Here's a snippet of my code:

private void handleGoogleLoginResult(Intent data) {
    if (data != null) {
        // get result from data received
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        int statusCode = result.getStatus().getStatusCode();
        if (result.isSuccess() && result.getSignInAccount() != null) {
            // Signed in successfully

        } 
        // logout
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            Auth.GoogleSignInApi.signOut(mGoogleApiClient);
        }
    }
}
2
votes

I am using the Firebase Auth UI, and For me the fix was;

AuthUI.getInstance().setIsSmartLockEnabled(false)...

When logging in, and then;

AuthUI.signOut(context)

When Signing out

2
votes

Without calling SignOut

Those who needs it in kotlin, this worked for me, I do clear current login cache before a new login request is made

/**
 * signInGoogle
 */

private fun signInGoogle() = launch(Dispatchers.IO){

    //init google sigin
    val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(GOOGLE_WEBCLIENT_ID)
            .requestEmail()
            .build()

    val gApiClient = GoogleApiClient.Builder(activity)
            .addApi(Auth.GOOGLE_SIGN_IN_API,gso)
            .build()

    val c = gApiClient.blockingConnect()

    if(c.isSuccess && gApiClient.isConnected){
        gApiClient.clearDefaultAccountAndReconnect().await()
    }

    val mGoogleSignInClient = GoogleSignIn.getClient(activity, gso)
    val signInIntent = mGoogleSignInClient.signInIntent

    launch (Dispatchers.Main){
        // IN MAIN THREAD
        startActivityForResult(signInIntent, GOOGLE_SIGNIN)
    }.start()

    //start activity

}//end request google login

You can view the full source here : https://github.com/transcodium/TNSMoney-Android/blob/master/app/src/main/java/com/transcodium/tnsmoney/SocialLoginActivity.kt

for Java users :

/**
 * signInGoogle
 */

private void signInGoogle() {

    new Thread(new Runnable() {
        @Override
        public void run() {


            //init google sigin
            GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestIdToken(getString(R.string.default_web_client_id)) // required to get accesstoken
                    .requestEmail()
                    .build();

            GoogleApiClient gApiClient = new GoogleApiClient.Builder(activity)
                    .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                    .build();

            ConnectionResult c = gApiClient.blockingConnect();

            if (c.isSuccess() && gApiClient.isConnected()) {
                gApiClient.clearDefaultAccountAndReconnect().await();
            }

            GoogleSignInClient mGoogleSignInClient = GoogleSignIn.getClient(activity, gso);
            Intent signInIntent = mGoogleSignInClient.getSignInIntent();

            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {


                    //start activit
                    getActivity().startActivityForResult(signInIntent, RC_SIGN_IN);


                }
            });

        }
    }).start();


}//end request google login
1
votes

Simplely workout for me

1>Activity implements GoogleApiClient.OnConnectionFailedListener {

2> mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) .addApi(Auth.GOOGLE_SIGN_IN_API, gso) .build();

3>In OnButtonClicked

Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                startActivityForResult(signInIntent, 2);

4>

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 2) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                GoogleSignInAccount acct = result.getSignInAccount();
                if(acct!=null) {            
                    //Take all data You Want
                    String identifier = acct.getId()+"";                 
                    String displayName = acct.getDisplayName()+"";
                    //After You got your data add this to clear the priviously selected mail
                    mGoogleApiClient.clearDefaultAccountAndReconnect();
                }
            }else Log.e("handleSignInResult","Failed ; "+result.getStatus());
        }
    }
0
votes

Signout your user using:

 Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    // ...
                }
            });
0
votes

I found this question while searching for a solution using the javascript client, but it might be similar with Android.

signIn({ prompt: 'select_account' })

select_account

The authorization server prompts the user to select a Google account. This allows a user who has multiple accounts to select amongst the multiple accounts that they may have current sessions for.

See https://developers.google.com/identity/sign-in/web/reference#googleauthsigninoptions.

0
votes

You are not revoking user by sign out them use the following to achieve what you need :

Put this code in any activity and call it in sign out button click :

private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
        new ResultCallback<Status>() {
            @Override
            public void onResult(Status status) {
                // ...
            }
        });

}

write this in onCreate() :

mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API)
            .build();

override this in onStart() :

 @Override
protected void onStart() {
    super.onStart();
    mGoogleApiClient.connect();
}

Reference Link : Google Developer Page

0
votes

This is worked for me. !!

  @Override
            public void onPause() {
                super.onPause();
                if (mGoogleApiClient.isConnected()) {
                    Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                            new ResultCallback<Status>() {
                                @Override
                                public void onResult(Status status) {
                                    // ...
                                }
                            });
                }
                mGoogleApiClient.stopAutoManage(Objects.requireNonNull(getActivity()));
                mGoogleApiClient.disconnect();

            }

if you want to enter again within the Fragment or Activity , you need to recreate these variables

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();

        mGoogleApiClient = new GoogleApiClient.Builder(Objects.requireNonNull(getActivity()))
                .enableAutoManage(getActivity(), (this))
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();
0
votes

Just add mGoogleSignInClient.signOut(); After succesfully handling sign in.

private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
    try {
        GoogleSignInAccount account = completedTask.getResult(ApiException.class);
        AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null);
        mAuth.signInWithCredential(credential).addOnCompleteListener(this, task -> {
            if(task.isSuccessful()) {
                mGoogleSignInClient.signOut();
                updateUI();
            } else {
                Toast.makeText(this, "Something went wrong.", Toast.LENGTH_SHORT).show();
            }
        });
    } catch (ApiException e) {
        Log.w("SignIn Failed", "signInResult:failed code=" + e.getStatusCode());
        updateUI(null);
    }
}
0
votes

For people in 2K21 Here is what you need to do,

private static final int RC_GOOGLE_SIGN_IN = 500;

private void signWithGoogle() {
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();
        GoogleSignInClient googleSignInClient=GoogleSignIn.getClient(this, gso);
        googleSignInClient.signOut();
        Intent signInIntent = googleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_GOOGLE_SIGN_IN);
    }
-1
votes

If you are having any logout functionality. Put the below code just before your logout code:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {

       CookieManager.getInstance().removeAllCookies(null);
       CookieManager.getInstance().flush();
}
else
{
       CookieSyncManager cookieSyncMngr=CookieSyncManager.createInstance(activity);
       cookieSyncMngr.startSync();
       CookieManager cookieManager=CookieManager.getInstance();
       cookieManager.removeAllCookie();
       cookieManager.removeSessionCookie();
       cookieSyncMngr.stopSync();
       cookieSyncMngr.sync();
}

Hope this will help.

EDIT: you can also try replacing you storeDatainSharedPreferences method with below code:

private void storeDatainSharedPreferences() {
try {

    SharedPreferences.Editor editor = getSharedPreferences(NEW_PREFS, MODE_PRIVATE).edit();
    editor.putString("CurrentUsername", dataStore.getCurrentUserName());
    editor.putString("CurrentUserId", dataStore.getCurrentUserID());
    editor.commit();
    if(mGoogleApiClient!=null)
          mGoogleApiClient.disconnect();
}
catch (NoSuchElementException e)
{
    new AlertDialog.Builder(LoginActivity.this).setMessage("There was an error whil logging in")
            .setTitle("Little Problem here!").setPositiveButton("Retry", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            Intent intent=new Intent(LoginActivity.this,LoginActivity.class);
            removeDatainSharedPreferences();
            mGoogleApiClient.disconnect();
            startActivity(intent);
        }
    }).show();
}}

Explanation : For First solution : It is the code to clear all Cookies related to your application. This can be help full in your situation because you want to clear the previous data which might be stored in Cookies.

Explanation : For Second solution : It is the code which disconnects the mGoogleApiClient. which will be helpful because You have stored the data in sharedPref now you don't need mGoogleApiClient.