I wanted to implement a Google signin activity which on success opens my next activity. If the user logs out from the next activity, I want to go back to Google signin activity and signout. However when I call signout in onActivityResult I get the following exception
Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
Here's the relevant code
public class LoginActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {
private static final String TAG = "LoginActivity";
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private GoogleSignInOptions gso;
private TextView mStatusTextView;
private ProgressDialog mProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.signin_activity);
// Views
mStatusTextView = (TextView) findViewById(R.id.status);
// Button listeners
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
findViewById(R.id.disconnect_button).setOnClickListener(this);
// [START configure_signin]
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
// [END configure_signin]
// [START build_client]
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [END build_client]
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setScopes(gso.getScopeArray());
// [END customize_button]
}
@Override
public void onStart() {
Log.d(TAG, "onStart()");
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has
// expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
@Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
// [START onActivityResult]
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult()");
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
else if (requestCode == Constants.MAPS_ACTIVITY_FINISHED) {
if (resultCode == Constants.SIGNOUT) {
signOut();
}
}
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
updateUI(true);
Intent intent = new Intent(this, MapsActivity.class);
startActivityForResult(intent, Constants.MAPS_ACTIVITY_FINISHED);
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Log.d(TAG, "signin()");
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
// [START signOut]
private void signOut() {
Log.d(TAG, "signout()");
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END signOut]
}
According to the Javadoc:
1) signOut:
2) getSignInIntent
signOut call requires a connected GoogleApiClient; while getSignInIntent() doesn't. In Google's sample, sign-out button is only enabled after signing-in, which can guarantee a connected GoogleApiClient. However, in your case, you will need to explicitly listen to onConnected before calling signOut. You can use GoogleApiClient.Builder.addConnectionCallbacks to register an onConnected listener, and making sure you queue the signOut request until onConnected is called back.
(Since you used autoManage, GoogleApiClient internal will auto-connect in onStart() and auto-disconnect in onStop)
Your exception tells you what the problem is: your client is not connected. First of all I suggest that you check out this guide about Google API Client.
Anyway, what you should do is add the following code somewhere to your app:
This code will send a connection request, and if everything is fine, your client will get connected. After that, before you use it, you should check if the client is connected to avoid this error in future: