How do I switch accounts under the NEW Google Drive Android API

限于喜欢 提交于 2019-12-17 10:55:10

问题


My authorization flow in the new Google Drive Android API is as follows:

  1. Menu: SELECT ACCOUNT
  2. connect();
  3. onConnectionFailed() result.startResolutionForResult() invokes AccountSelectDialog / DriveAuthorization
  4. onConnected() do your stuff

Works like a charm. Now repeating with the aim to switch accounts:

  1. Menu: SELECT ACCOUNT
  2. connect();
  3. onConnected()

Here, I have no chance to get to the AccountSelectDialog since I never get onConnectionFailed() with 'result' to invoke startResolutionForResult(). What am I missing this time?


回答1:


Just call

mGoogleApiClient.clearDefaultAccountAndReconnect();

have a look at the docs.

This will call the onConnectionFailed callback that will present the layout to choose among the available Google accounts:

@Override
public void onConnectionFailed(ConnectionResult connectionResult) 
{
    if (connectionResult.hasResolution()) {
        try {                                              
            connectionResult.startResolutionForResult(this, RESOLVE_CONNECTION_REQUEST_CODE);
        } catch (IntentSender.SendIntentException e) {
            // Unable to resolve, message user appropriately
        }
    } else {                                           
        GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), this, 0).show();
    }

}



回答2:


First, add the Plus.API:

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

Then you can switch accounts like this:

public void onClick(View view) {
  if (view.getId() == R.id.sign_out_button) {
    if (mGoogleApiClient.isConnected()) {
      Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
      mGoogleApiClient.disconnect();
      mGoogleApiClient.connect();
    }
  }
}

For more, see here.




回答3:


I realize I made quite a mess by opening two SO questions about essentially the same topic. So, it is a good time to consolidate the answers. I was searching for direct getter / setter methods in GDAA but found only the 'setter' - setAccountName()) - SO question 21583828 (actually did not, but Burcu helped me).

On the other side, 'getter' can be substituted by getting the account name from "onActivityResult()" - SO question 21501829

And yet another SO question - this one - on the same topic has been resolved as well.

So the conclusion is:

  1. get account from 'onActivityResult()'
  2. set account in 'setAccountName()'
  3. keep your current account email around, so you can detect a new one (should user decide to switch) and reset Google Account Client if necessary.

UPDATE 2014-11-04:

Here is a wrapper that I use to persist and manage the Google accounts within my app.

import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.google.android.gms.auth.GoogleAuthUtil;

public class GooAccMgr {
  private static final String ACC_NAME = "account_name";
  public  static final int FAIL = -1;
  public  static final int UNCHANGED =  0;
  public  static final int CHANGED = +1;

  private String mCurrEmail = null;  // cache locally

  public Account[] getAllAccnts(Context ctx) {
    return AccountManager.get(acx(ctx)).getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
  }

  public Account getPrimaryAccnt(Context ctx) {
    Account[] accts = getAllAccnts(ctx);
    return accts == null || accts.length == 0 ? null : accts[0];
  }

  public Account getActiveAccnt(Context ctx) {
    return email2Accnt(ctx, getActiveEmail(ctx));
  }

  public String getActiveEmail(Context ctx) {
    if (mCurrEmail != null) {
      return mCurrEmail;
    }
    mCurrEmail = ctx == null ? null : pfs(ctx).getString(ACC_NAME, null);
    return mCurrEmail;
  }

  public Account email2Accnt(Context ctx, String emil) {
    if (emil != null) {
      Account[] accounts =
       AccountManager.get(acx(ctx)).getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
      for (Account account : accounts) {
        if (emil.equalsIgnoreCase(account.name)) {
          return account;
        }
      }
    }
    return null;
  }

  /**
   * Stores a new email in persistent app storage, reporting result
   * @param ctx activity context
   * @param newEmail new email, optionally null
   * @return FAIL, CHANGED or UNCHANGED (based on the following table)
   * OLD    NEW   SAVED   RESULT
   * ERROR                FAIL
   * null   null  null    FAIL
   * null   new   new     CHANGED
   * old    null  old     UNCHANGED
   * old != new   new     CHANGED
   * old == new   new     UNCHANGED
   */
  public int setEmail(Context ctx, String newEmail) {
    int result = FAIL;  // 0  0

    String prevEmail = getActiveEmail(ctx);
    if        ((prevEmail == null) && (newEmail != null)) {
      result = CHANGED;
    } else if ((prevEmail != null) && (newEmail == null)) {
      result = UNCHANGED;
    } else if ((prevEmail != null) && (newEmail != null)) {
      result = prevEmail.equalsIgnoreCase(newEmail) ? UNCHANGED : CHANGED;
    }
    if (result == CHANGED) {
      mCurrEmail = newEmail;
      pfs(ctx).edit().putString(ACC_NAME, newEmail).apply();
    }
    return result;
  }

  private Context acx(Context ctx) {
    return ctx == null ? null : ctx.getApplicationContext();
  }
  private SharedPreferences pfs(Context ctx) {
    return ctx == null ? null : PreferenceManager.getDefaultSharedPreferences(acx(ctx));
  }
}

Hat-tip to Alex Lockwood for initial inspiration. Unfortunately, I can't find reference to his original code.




回答4:


It sounds like you are relying on the default account selection. In this setup, the user is prompted once to select an account, and this status is remembered.

If you want to provide account switching capabilities in your app, you need to instead launch the account picker from your own app and provide the account name selected when you instantiate the GoogleApiClient.

You could persist the last selected account name in shared preferences so you remember it until the next time the user switches accounts.




回答5:


if you use GoogleApiClient, just call mGoogleApiClient.clearDefaultAccountAndReconnect().

if you use DriveClient with GoogleSignInAccount (drive library 16.0.0), try this.

// try connect Drive
fun startSignIn() {
    val requiredScopes = HashSet<Scope>()
    requiredScopes.add(Drive.SCOPE_FILE)
    requiredScopes.add(Drive.SCOPE_APPFOLDER)
    val account = GoogleSignIn.getLastSignedInAccount(this)
    if (account != null && account.grantedScopes.containsAll(requiredScopes)) {
        // TODO: Get DriveClient and DriveResourceClient
    } else {
        val option = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(Drive.SCOPE_FILE, Drive.SCOPE_APPFOLDER)
            .build()
        val client = GoogleSignIn.getClient(this, option)
        startActivityForResult(client.signInIntent, REQUEST_CODE_SIGN_IN)
    }
}

// try change account
fun changeAccount() {
    val option = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
    .build()
    val client = GoogleSignIn.getClient(activity, option)
    client.signOut()
        .addOnSuccessListener {
            Log.d(TAG, "signOut success")
            // Try again sign-in
            startSignIn()
        }
        .addOnFailureListener {
            Log.e(TAG, "signOut failed $it")
        }
    }


来源:https://stackoverflow.com/questions/21610239/how-do-i-switch-accounts-under-the-new-google-drive-android-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!