Google sign in and sign out in android using g-plus latest API-ThrowExceptions

Exception or error:

I have gone through some of the stackoverflow questions related to sign-in and sign-out of google plus. And most of them are outdated. I am not able to achieve what I actually want.

Once I have sign-out, the next time I sign-in, I would like the user to choose the available google account to sign-in again.

I am using custom sign-in and sign-out button. And for sign-out, I have two cases,

  1. sign-out just before sign-in if any user is already sign-in in the same login activity.
  2. sign-out from the different activity.

Here is what I have implemented so far:

public class LoginActivity extends AppCompatActivity implements OnClickListener{

    private static final int RC_SIGN_IN = 9001;
    private GoogleApiClient mGoogleApiClient;
    private ConnectionResult mGoogleConnectionResult;
    private Button login;
    private ProgressDialog mProgressDialog;
    private Context mContext;
    private String mUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext= LoginActivity.this;
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.login_layout);

        login= (Button) findViewById(R.id.lg_login_btn);
        login.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if(isOnline(mContext)){
            if(v.getId()== R.id.lg_login_btn) {
                if(mGoogleApiClient!=null){
                    mGoogleApiClient.disconnect();
                }
            GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(new Scope(Scopes.PLUS_LOGIN))
            .requestEmail()
            .build();

    mGoogleApiClient = new GoogleApiClient.Builder(mContext.getApplicationContext())
            .enableAutoManage(this , mGPlusConnectionFailedListener)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .addApi(Plus.API)
            .build();

        signOutGPlus();
        Intent lSignInIntent= Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
        startActivityForResult(lSignInIntent, RC_SIGN_IN);

            }
        } else{
            showAlertDialog(mContext, "Error", "Please check internet connection");
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        logD("&&onActivityResult", "requestCode: "+requestCode);     // first

        if (requestCode == RC_SIGN_IN) {
            if(resultCode == RESULT_OK){
                showProgressDialog();
                getGPlusUserInfo(data);
            } else {
                logD("&&onActivityResult", "requestCode: RESULT_ NOT Ok"+requestCode);
            }
        }
    }

    GoogleApiClient.OnConnectionFailedListener mGPlusConnectionFailedListener= new GoogleApiClient.OnConnectionFailedListener() {
        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
            logD("&&mGPlusConnectionFailedListener", "onConnectionFailed");
        }
    };

    private void getGPlusUserInfo(Intent data){
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        handleSignInResult(result);
    }

    private void handleSignInResult(GoogleSignInResult result) {
        Log.d("&&handleSignInResult", "handleSignInResult:" + result.isSuccess());
        if (result.isSuccess()) {
            // Signed in successfully, show authenticated UI.
            String lDisplayName="";
            String lEmail="";
            String lFirstName="";
            String lLastName="";
            String lGender="";

            // G+
            if (mGoogleApiClient.hasConnectedApi(Plus.API)) {
                logD("&&GPlusUserInfo", "&hasConnectedApi--------------------------------");
                // Deprecated
                Person person = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
                if(null != person) {
                    logD("&&GPlusUserInfo", "&--------------------------------");
                    logD("&&GPlusUserInfo", "&Display Name: " + person.getDisplayName());
                lDisplayName= person.getDisplayName();
                    logD("&&GPlusUserInfo", "Gender: " + person.getGender());
                    if(person.getGender()< MyHalConstants.GENDER.length){
                        lGender= MyHalConstants.GENDER[person.getGender()];
                    } else{
                        lGender= "Other";
                    }
                }
            }
            GoogleSignInAccount acct = result.getSignInAccount();

            if(null != acct) {
                if (null != acct.getDisplayName()) {
                    logD("&&GPlusUserInfo", "&Display Name: " + acct.getDisplayName());
                }
                lFirstName= acct.getGivenName();
                lLastName= acct.getFamilyName();
                // Views inside NavigationView's header
                Uri uri = acct.getPhotoUrl();                  
            }
        } else {
            // Signed out, show unauthenticated UI.
            signOutGPlus();
        }
    }


    // sign - out 
    private void signOutGPlus(){
        logD("&&signOutGPlus", "signOutGPlus");
        if(null != mGoogleApiClient){
            mGoogleApiClient.connect();
            mGoogleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {

                @Override
                public void onConnected(@Nullable Bundle bundle) {
                    if(mGoogleApiClient.isConnected()) {
                        logD("&&signOutGPlus", "inside");
                    Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                            new ResultCallback<Status>() {
                                    @Override
                                    public void onResult(@NonNull Status status) {
                                        logD("&&signOutGPlus", "onResult");
                                        if(mGoogleApiClient.isConnected()){
                                        mGoogleApiClient.clearDefaultAccountAndReconnect();
                                            mGoogleApiClient.disconnect();
                                    }
                                    // Deprecated
                                    /*Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
                                    //Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient);
                                    //revokeAccess();*/
                                    }
                                }
                    );
                    }
                }

                @Override
                public void onConnectionSuspended(int i) {

                }
            });
        }
    }

// Not used
    private void revokeAccess() {
    logD("&&revokeAccess", "revokeAccess");
    Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        // ...
                    }
                });
    }

    private void showProgressDialog() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage(getString(R.string.loading));
            mProgressDialog.setIndeterminate(true);
        }

        mProgressDialog.show();
    }

    private void hideProgressDialog() {
        if (mProgressDialog != null && mProgressDialog.isShowing()) {
            mProgressDialog.hide();
        }
    }

    private void showAlertDialog(Context pContext, String pTitle, String pMessage){
        AlertDialog.Builder ldialogBuilder= new AlertDialog.Builder(pContext);
        ldialogBuilder.setTitle(pTitle)
            .setMessage(pMessage)
        .setPositiveButton("Ok", null);
        ldialogBuilder.show();
    }

    private void dismissDialog(){
        if(null != mProgressDialog){
            mProgressDialog.dismiss();
            mProgressDialog= null;
        }
    }
}

As for sign-out from different activity, none of the answers that I came across define how to initilaize mGoogleApiClient in the new activity.

For the sign-out if I implement the below code:

private GoogleApiClient mGoogleApiClient;

// sign - out 
private void signOutGPlusFromDifferentActivity(){
    logD("&&signOutGPlus", "signOutGPlus");
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(new Scope(Scopes.PLUS_LOGIN))
            .requestEmail()
            .build();

    mGoogleApiClient = new GoogleApiClient.Builder(mContext.getApplicationContext())
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .addApi(Plus.API)
            .build();
    if(null != mGoogleApiClient){
        mGoogleApiClient.connect();
        mGoogleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
            @Override
            public void onConnected(@Nullable Bundle bundle) {
                if(mGoogleApiClient.isConnected()) {
                    logD("&&signOutGPlus", "inside");
                    Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                            new ResultCallback<Status>() {
                                @Override
                                public void onResult(@NonNull Status status) {
                                    logD("&&signOutGPlus", "onResult");
                                    if(mGoogleApiClient.isConnected()){
                                        mGoogleApiClient.clearDefaultAccountAndReconnect();
                                        mGoogleApiClient.disconnect();
                                    }
                                }
                            }
                    );
                }
            }
            @Override
            public void onConnectionSuspended(int i) {

            }
        });
    }
}

It throws error.

By removing the sign-out part from the Login activity, I am able to sign-in properly from GPlus.

Gradle:

compile 'com.google.android.gms:play-services-auth:9.2.1'
compile 'com.google.android.gms:play-services:9.2.1'

NOTE: from the login activity I can login from either google plus or face-book.

Activity A (Login from g+ or fb).

After login, user is directed to Activity B, from Activity B user can logout from the appropriate portal (g+ or fb).

Facebook part is done. Only remaining is g+.

Please help in signing-out properly in both the case BY USING UPDATED GOOGLE LOGIN LOGOUT APIs.

How to solve:

Do this in your second activity.If you are saving any preference
regarding login in first activity then clear it on logout click

package com.ccc.bbbb;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.plus.People;
import com.google.android.gms.plus.People.LoadPeopleResult;
import com.google.android.gms.plus.Plus;



//implement ConnectionCallbacks, OnConnectionFailedListener,ResultCallback<People.LoadPeopleResult> 

public class HomeActivity extends Activity implements OnClickListener ,ConnectionCallbacks, OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult> 
{

    public static boolean isLogout=false;
    GoogleApiClient mGoogleApiClient;


    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

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

            //Logout button click


                    if(networkCheck.isNetworkAvailable(HomeActivity.this))
                    {
                        Log.d(TAG, "logout if condition working....");  


                            isLogout=true;

                            if(mGoogleApiClient.isConnected())
                            {
                                Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
                                mGoogleApiClient.disconnect();
                                mGoogleApiClient.connect();
                            }
                            Toast.makeText(HomeActivity.this, "you are logged out", Toast.LENGTH_SHORT).show();

                            Intent intent=new Intent(HomeActivity.this,MainActivity.class);
                            startActivity(intent);
                            finish();

                        }



//override below methods and copy those codes

        @Override
         public void onResult(@NonNull LoadPeopleResult arg0) {
            // TODO Auto-generated method stub

         }


         @Override
         public void onConnectionFailed(@NonNull ConnectionResult arg0) {
            // TODO Auto-generated method stub

         }


         @Override
         public void onConnected(@Nullable Bundle arg0) {
            // TODO Auto-generated method stub
            mSignInClicked = false;

             // updateUI(true);
             Plus.PeopleApi.loadVisible(mGoogleApiClient, null).setResultCallback(
                     this);

         }


         @Override
         public void onConnectionSuspended(int arg0) {
            // TODO Auto-generated method stub
            mGoogleApiClient.connect();

         }

         @Override
         protected void onStart() {
            // TODO Auto-generated method stub
            super.onStart();
            mGoogleApiClient.connect();

         }
         @Override
         protected void onStop() 
         {
            // TODO Auto-generated method stub
            super.onStop();
            if (mGoogleApiClient.isConnected()) {
                 mGoogleApiClient.disconnect();
             }
            if (mDialog.isShowing()) {
                mDialog.dismiss();
            }

         }




}

###

For Sign-out you can use following method:

private void signOut() {
    Auth.GoogleSignInApi.signOut(googleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    Timber.d("Logged out");
                }
            });
}

For sign-in you can follow these methods:

public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
    this.activity = activity;
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        handleSignInResult(result);
    }

   /*For inintializing googleapiclient*/
    private void initGoogleClient() {

    gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();

    googleApiClient = new GoogleApiClient.Builder(activity)
            .enableAutoManage((FragmentActivity) activity /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .addOnConnectionFailedListener(this)
            .addApi(Plus.API)
            .addScope(new Scope(Scopes.PROFILE))
            .build();
}

private void signIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
    activity.startActivityForResult(signInIntent, RC_SIGN_IN);
}

###

Once I have sign-out, the next time I sign-in, I would like the user to choose the available google account to sign-in again.

The trick is to clearDefaultAccountAndReconnect the GoogleApiClient just after the user clicks on the Google Sign in button to login. This ensures that all the available Google accounts are always shown whenever you click on Login Button.

STEP 1: Initialize GoogleAPIClient and set onClickListener to googleSignInButton in Activity onCreate()

private GoogleApiClient mApiClient;

private void initializeGoogleSignIn() {
    GoogleSignInOptions signInOptions = new GoogleSignInOptions
            .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestProfile()
            .build();

    mApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this, this)
            .addApi(Auth.GOOGLE_SIGN_IN_API, signInOptions)
            .build();

    SignInButton googleSignInButton = (SignInButton) findViewById(R.id.google_sign_in);

    googleSignInButton.setOnClickListener(this);
}

STEP 2: Handle the Google Sign in through your onClick() method

@Override
public void onClick(View v) {

    switch (v.getId()) {
        case R.id.google_sign_in:

            if (mApiClient.isConnected()) {
                mApiClient.clearDefaultAccountAndReconnect();
            } else {
                mApiClient.connect();
            }

            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mApiClient);
            startActivityForResult(signInIntent, RC_SIGN_IN);

            break;
    }
}

MISCALLANEOUS

// Make sure you connect and disconnect the GoogleApiClient in onStart and onStop lifecycle methods
@Override
protected void onStart() {
    super.onStart();
    mApiClient.connect();
}

@Override
protected void onStop() {
    super.onStop();
    if (mApiClient.isConnected())
        mApiClient.disconnect();
}



 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);

            if (result != null && result.isSuccess()) {

                GoogleSignInAccount account = result.getSignInAccount();

                setAppPreferenceData(account.getId(), account.getEmail(), String.valueOf(account.getPhotoUrl()), account.getDisplayName());

                startActivity(new Intent(this, NavigationActivity.class));


                finish();
            } else {
                mProgressLayout.setVisibility(View.GONE);

                if (Utils.isNetworkAvailable(this))
                    Toast.makeText(this, "Google Authentication Failed! Please try again", Toast.LENGTH_SHORT).show();
                else
                    Toast.makeText(this, "Network Error! Please connect to your wifi.", Toast.LENGTH_LONG).show();
            }
        } 
    }

Why do you need so many callback methods in your code? I suppose you complicated your code a bit. The main trick is to disconnect and clear the default account whenever user tries to login which ensures that he is always shown a list of valid google accounts.
I have used the same procedure, it’s tried, tested and working.

Only one call back method for the login state used in my app.

public class SignInActivity extends AppCompatActivity implements
        GoogleApiClient.OnConnectionFailedListener {
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Toast.makeText(SignInActivity.this, "Google Play connection error", Toast.LENGTH_SHORT).show();
    mProgressLayout.setVisibility(View.GONE);
}

###

Once I have sign-out, the next time I sign-in, I would like the user to choose the available google account to sign-in again.

Simply, sign out the user and revoke access whenever the user clicks sign out button. Next time, when the users try to sign in he/she will be asked to choose their preferred google account.

Since you are signing in and signing out from different activities, you are ending up with duplicate code. Instead of duplicating the code, simply use a helper class and initialize the Google SignIn Option and Google API Client. Now, Whenever you want to use Google API Client, you can initialize the helper class.

Case 1. If you want to sign out before signing in, use clearDefaultAccountAndReconnect.

Case 2. For signing out the user (It doesn’t matter whatever the activity is), use Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback.

Here is the github link to the project. You can take a look if you still have doubts.

###

This Solved my issue:-

Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                @Override
                public void onResult(@NonNull Status status) {
                    Toast.makeText(context, "Success"+status.getStatusMessage(), Toast.LENGTH_SHORT).show();
                }
            });

Leave a Reply

Your email address will not be published. Required fields are marked *