3

I am attempting to check if the user is signed in and weather or not they are, send them to the login or keep them on the main activity.

Main Activity

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.plus.Plus;

public class MainActivity extends Activity {

    private GoogleApiClient mGoogleApiClient;

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

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

        if (!mGoogleApiClient.isConnected()) {
            Intent intent = new Intent(MainActivity.this, LoginActivity.class);
            startActivity(intent);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

LoginActivity

package com.alfalfa.thisthat;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
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.plus.Plus;

public class LoginActivity extends Activity implements ConnectionCallbacks,
        OnConnectionFailedListener, OnClickListener {

    private static final int RC_SIGN_IN = 0;
    private GoogleApiClient mGoogleApiClient;
    private boolean mIntentInProgress;
    private boolean mSignInClicked;
    private static SignInButton mSignInButton;
    private ConnectionResult mConnectionResult;

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

        mSignInButton = (SignInButton) findViewById(R.id.sign_in_button);
        mSignInButton.setOnClickListener(this);
        mSignInButton.setEnabled(true);
        mSignInButton.setSize(SignInButton.SIZE_WIDE);

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

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

    protected void onStop() {
        super.onStop();

        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
    }

    protected void onActivityResult(int requestCode, int responseCode,
            Intent intent) {
        if (requestCode == RC_SIGN_IN) {
            if (responseCode != RESULT_OK) {
                mSignInClicked = false;
            }

            mIntentInProgress = false;

            if (!mGoogleApiClient.isConnecting()) {
                mGoogleApiClient.connect();
            }
        }
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.sign_in_button
                && !mGoogleApiClient.isConnecting()) {
            mSignInClicked = true;
            resolveSignInErrors();
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        if (!mIntentInProgress) {
            mConnectionResult = result;

            if (mSignInClicked) {
                resolveSignInErrors();
            }
        }
    }

    private void resolveSignInErrors() {
        if (mConnectionResult.hasResolution()) {
            try {
                mIntentInProgress = true;
                mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
            } catch (SendIntentException e) {
                mIntentInProgress = false;
                mGoogleApiClient.connect();
            }
        }
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        mSignInClicked = false;
        navigateToMainActivity();
        Toast.makeText(this, "User is connected!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionSuspended(int cause) {
        mGoogleApiClient.connect();
    }

    public void navigateToMainActivity() {
        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
        startActivity(intent);
    }
}

When I start the app, it loads into the login screen. When I click the sign in button, the app backs in and our of the LoginActivity infinitely.

Eric Goncalves
  • 5,253
  • 4
  • 35
  • 59
  • Ill risk it by asking a question first - do you need to define the activity to be launched upon connection with ggole plus? (same as on facebook) in case you do you are disconnecting upon connection which might get you back to the main activity defined in g+ your loop is a direct result of your g+ connection location (onCreate), meaning you are connecting get redirected to the next activity then disconnecting and get redirected back thats just a GUESS though... – crazyPixel Feb 14 '14 at 17:57
  • I don't know another way to handle two separate screens (one login, the other main) without having 2 activities – Eric Goncalves Feb 14 '14 at 18:16
  • I probably failed to explain myself - do you need to define the activity to be launched upon connection \ The activity you are using for connection on google plus (assuming you need to create a ggole plus application)? – crazyPixel Feb 14 '14 at 18:18
  • I'm sorry, I don't understand your question :/ – Eric Goncalves Feb 14 '14 at 18:23
  • Well... place a logic check before moving on to the next activity use this code - public void navigateToMainActivity() { Intent intent = new Intent(LoginActivity.this, MainActivity.class); if(mGoogleApiClient.isConnected()) { startActivity(intent); } else { Log.e("Loginactivity","not connected"); } } – crazyPixel Feb 14 '14 at 18:32
  • I finally got to look at your question (long after posting a quick answer below). Your MainActivity doesn't need custom login activity. 1/After instantiating of GoogleAccountClient (GAC) you call connect() 2/if the user is connected everything continues OK 3/ if not, Account Picker (build in activity) pops up and comes back in onActivityResult - this is where you can catch the current user. Switching users to a new one must be initiated by your app invoking AccounPicker, getting the new user from onActitvityResult. Then you kill GAC and build a new one with the new user. Call connect()... – seanpj Feb 17 '14 at 18:39

2 Answers2

1

I removed a piece of code from my app that does something similar. It is Google Drive related, but easy to adapt.
On menu selection, it pops-up account picker and connects to GAC with the selected account. Checking if the user is signed-in is irrelevant in my situation. If there has been a valid user connected before, the connect() is successful, otherwise the account picker pops-up. There is more about it in SO 21610239. And I believe there is no way to get current signed user, unless you pop-up the account picker and get it from the return (KEY_ACCOUNT_NAME below).

public class SomeActivity extends Activity
                                implements ConnectionCallbacks, OnConnectionFailedListener {
  GoogleApiClient mGAC;
  // from menu: user pops up account picker and selects account
  @Override public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.acc_select:
      Intent intent = AccountPicker.newChooseAccountIntent(null, null, 
              new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, false, null, null, null, null);
      startActivityForResult(intent, AUTH_REQUEST);
    return true;
    }
    return super.onOptionsItemSelected(item);
  }
  // back from account picker (invoked from menu OR from onConnectionFailed())
  @Override protected void onActivityResult(final int rqst, final int rslt, final Intent it) { 
    switch (rqst) {
    case AUTH_REQUEST:                                    
      if (mGAC == null) {
        mGAC = new GoogleApiClient.Builder(this).addApi(Drive.API).addScope(Drive.SCOPE_FILE)
        .setAccountName(it.getStringExtra(AccountManager.KEY_ACCOUNT_NAME))
        .addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
      }
      if ((mGAC != null) && !mGAC.isConnected())
        mGAC.connect();
      break;
    }
  }
  // connection failed, either fatal, or needs account / authorization
  @Override public void onConnectionFailed(ConnectionResult rslt) {
    if (!rslt.hasResolution()) {        // FATAL ------->>>>
      Toast.makeText(this, "FAILED", Toast.LENGTH_LONG).show();
    } else try {                     // needs authorization
      rslt.startResolutionForResult(this, AUTH_REQUEST);
    } catch (SendIntentException e) {}
  }
  @Override public void onConnected(Bundle connectionHint) {
    // do my stuff here
  }
  @Override public void onConnectionSuspended(int i) {}
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
seanpj
  • 6,735
  • 2
  • 33
  • 54
  • I think you can get the account name if you add `.addApi(Plus.API)` to your Builder, and then call `Plus.Account.getAccountName()`, but it still requires the Android `GET_ACCOUNTS` permission. – Hounshell Feb 19 '14 at 04:46
  • @Hounshell. This is probably specific to Plus.API (i.e. correctly applies to this specific question). I work in the area of Drive.API and there is no "Drive.Account" available there. Probably omission in the Drive API. Your solution may make it even easier, the app does not have to keep account email around. – seanpj Feb 19 '14 at 14:06
  • Yes, it is specific to Plus, but I think if you add Plus.API without any scopes you can use that method without it asking the user for additional permissions. – Hounshell Feb 21 '14 at 15:31
0

There's one glaring issue I see in the code you posted:

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

    if (!mGoogleApiClient.isConnected()) {
        Intent intent = new Intent(MainActivity.this, LoginActivity.class);
        startActivity(intent);
    }

At this point mGoogleApiClient will never be connected. To determine if the user isn't successfully connected (there are a number of reasons this could happen), you want to add an OnConnectionFailedListener to the Builder, then call .connect() on mGoogleApiClient and wait for OnConnectionFailedListener#onConnectionFailed() to be called. If that happens, then redirect the user back to the login Activity.

Hounshell
  • 5,321
  • 4
  • 34
  • 51
  • The answer I already posted has all the items you mention:. "implements OnConnectionFailedListener", ".addOnConnectionFailedListener(this)", "@Override public void onConnectionFailed(ConnectionResult rslt)". Are we in the same universe? – seanpj Feb 19 '14 at 14:13