Search code examples
javaandroidgoogle-apigoogle-plusgoogle-play-services

Google+ sign in for android not working, error code 4


I have followed the guide on how to setup google+ sign in. I did every step and basically copy and pasted the code.

Here is the scenario. I develop on two different computers. I have two different client-ids in my console. One for computer A and one for computer B.

When i install the application and launch it, it will attempt to sign in and fail with the following error from logcat. If i back out of the app and re-launch, it will then sign in fine. When it fails, it will seem to be trying to launch an Activity but the Activity is never launched. Here is the logcat.

06-04 10:14:57.801  19948-19948/carbon.android.game.legions D/AccountFragment﹕ ResolveSignInError ErrorCode:4
06-04 10:14:57.801      602-823/? I/ActivityManager﹕ START u0 {cmp=com.google.android.gms/.plus.activity.AccountSignUpActivity (has extras)} from pid -1
06-04 10:14:57.811      178-646/? D/audio_hw_primary﹕ select_devices: out_snd_device(2: speaker) in_snd_device(0: )
06-04 10:14:57.811      178-646/? D/ACDB-LOADER﹕ ACDB -> send_afe_cal
06-04 10:14:57.821     602-2816/? I/ActivityManager﹕ START u0 {act=com.google.android.gms.common.account.CHOOSE_ACCOUNT pkg=com.google.android.gms cmp=com.google.android.gms/.common.account.AccountPickerActivity (has extras)} from pid 20027
06-04 10:14:57.941  20027-20031/? D/dalvikvm﹕ GC_CONCURRENT freed 601K, 7% free 9304K/9940K, paused 2ms+2ms, total 19ms
06-04 10:14:58.071      949-959/? W/GLSUser﹕ GoogleAccountDataService.getToken()

What am i doing wrong? I followed the guide word for word and basically copy and pasted the code. The only difference is that i am inside of a Fragment and not an Activity. But, that shouldn't matter.

Here is the code:

public class AccountFragment extends Fragment implements View.OnClickListener,
        ConnectionCallbacks,
        OnConnectionFailedListener {

    private static final int RC_SIGN_IN = 1524;

    private GoogleApiClient googleApiClient;
    private boolean intentInProgress;
    private boolean signInClicked;
    private ConnectionResult connectionResult;

    private SignInButton signInButton;

    public AccountFragment() {}

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG, "The connection failed: " + connectionResult.getErrorCode());

        if (!this.intentInProgress) {
            this.connectionResult = connectionResult;

            if (this.signInClicked) {
                this.resolveSignInError();
            }
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        this.googleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();

        if (this.googleApiClient.isConnected()) {
            this.googleApiClient.disconnect();
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.googleApiClient = new GoogleApiClient.Builder(this.getActivity())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(Plus.API)
                .addScope(Plus.SCOPE_PLUS_PROFILE)
                .build();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.sign_in_button:
                if (!this.googleApiClient.isConnecting() && !this.googleApiClient.isConnected()) {
                    this.signInClicked = true;
                    this.resolveSignInError();
                } else {
                    Log.d(TAG, "OnClick else");
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onConnected(Bundle bundle) {
        this.signInClicked = false;
        Person currentPerson = Plus.PeopleApi.getCurrentPerson(this.googleApiClient);
        Log.d(TAG, "User connected: " + currentPerson.getDisplayName());
        Log.d(TAG, "User id: " + currentPerson.getId());
        Toast.makeText(this.getActivity(), "User connected: " + currentPerson.getDisplayName(), Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionSuspended(int i) {
        this.googleApiClient.connect();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == RC_SIGN_IN) {

            if (resultCode != Activity.RESULT_OK) {
                this.signInClicked = false;
            }

            this.intentInProgress = false;

            if (!this.googleApiClient.isConnecting()) {
                this.googleApiClient.connect();
            }
        }
    }

    private void resolveSignInError() {
        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this.getActivity()) != ConnectionResult.SUCCESS) {
            Log.e(TAG, "Google Play Services is not available.");
        }

        Log.d(TAG, "ResolveSignInError ErrorCode:" + this.connectionResult.getErrorCode());

        if (this.connectionResult.hasResolution()) {
            this.intentInProgress = true;
            try {
                this.connectionResult.startResolutionForResult(this.getActivity(), RC_SIGN_IN);
            } catch (SendIntentException e) {
                e.printStackTrace();
                this.intentInProgress = false;
                this.googleApiClient.connect();
            }
        }
    }
}

Solution

  • I figured out my issue.

    There were a couple of issues.

    1. With all my testing, i have been attempting to sign in the whole time. And was successful sometimes. Somehow, i was remaining authenticated even though my app was not signed in. I added the ability to sign out and revoke access. After revoking access and attempting to sign in again, the Activity would launch to resolve any errors.
    2. I was also having the issue that is being discussed here. My host Activity was consuming my onActivityResult(...) from my connectionResult.startResolutionForResult(...);. So, after some trial and error i finally found a solution to that issue as well. The question linked helped but did not fully solve the issue. Please view my answer to that question for how i solved the problem.

    Lesson, make sure that you are signing out and revoking access while testing. If you are having these issues, try revoking access and then signing back in.