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,
- sign-out just before sign-in if any user is already sign-in in the same login activity.
- 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.
5
Answers
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()
STEP 2: Handle the Google Sign in through your onClick() method
MISCALLANEOUS
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.
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.
For Sign-out you can use following method:
For sign-in you can follow these methods: