【问题标题】:How do I switch accounts under the NEW Google Drive Android API如何在新的 Google Drive Android API 下切换帐户
【发布时间】:2014-02-06 17:46:34
【问题描述】:

我在新版 Google Drive Android API 中的授权流程如下:

  1. 菜单:选择帐户
  2. 连接();
  3. onConnectionFailed() 结果.startResolutionForResult() 调用 AccountSelectDialog / DriveAuthorization
  4. onConnected() 做你的事

像魅力一样工作。现在重复一遍,目的是切换帐户:

  1. 菜单:选择帐户
  2. 连接();
  3. onConnected()

在这里,我没有机会进入 AccountSelectDialog,因为我从来没有得到带有“结果”的 onConnectionFailed() 来调用 startResolutionForResult()。这次我错过了什么?

【问题讨论】:

    标签: android google-drive-api google-drive-android-api


    【解决方案1】:

    首先,添加 Plus.API:

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

    然后你可以像这样切换帐户:

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

    欲了解更多信息,请参阅here

    【讨论】:

    • 我必须补充一下,我不知道为什么会这样 - 它不应该只是更改 Plus 帐户吗? - 但看起来确实如此......希望其他人确认。
    • 这对我也有用。我想知道它是否只是因为您传入mGoogleApiClient而清除了Google Drive的帐户。
    【解决方案2】:

    打电话就行了

    mGoogleApiClient.clearDefaultAccountAndReconnect();

    看看docs

    这将调用 onConnectionFailed 回调,该回调将显示布局以在可用的 Google 帐户中进行选择:

    @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();
        }
    
    }
    

    【讨论】:

    • 谢谢,这可行,但我的应用仍然需要知道用户在此过程中选择的活动帐户(电子邮件)。在应用程序级别管理它(根据我下面的回答)是 1/ 混乱,2/ 需要 'GET_ACCOUNTS 权限。有任何想法吗?顺便说一句,当我问这个问题时,你提到的方法不存在。
    • 现在,26 年 5 月 16 日。只要打电话。 mGoogleApiClient.clearDefaultAccountAndReconnect(); / "clearDefaultAccountAndReconnect" 已弃用。
    • @BrownsooHan 你在哪里看到的?代码或文档中没有任何指示。
    【解决方案3】:

    我意识到我打开了两个关于基本相同主题的 SO 问题,弄得一团糟。因此,现在是巩固答案的好时机。我在 GDAA 中搜索直接 getter / setter 方法,但只找到了“setter” - setAccountName()) - SO question 21583828(实际上没有,但 Burcu 帮助了我)。

    另一方面,“getter”可以通过从“onActivityResult()”获取帐户名称来替换 - SO question 21501829

    关于同一主题的另一个 SO 问题 - 这个问题 - 也已解决。

    所以结论是:

    1. 从“onActivityResult()”获取帐号
    2. 在 'setAccountName()' 中设置帐户
    3. 保留您当前的帐户电子邮件,以便您可以检测到新的电子邮件(如果用户决定切换)并在必要时重置 Google 帐户客户端。

    2014 年 11 月 4 日更新:

    这是我用来在我的应用中保存和管理 Google 帐户的包装器。

    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));
      }
    }
    

    向 Alex Lockwood 致以最初的灵感。不幸的是,我找不到对他原始代码的引用。

    【讨论】:

      【解决方案4】:

      听起来您依赖于默认帐户选择。在此设置中,系统会提示用户选择一个帐户,并且会记住此状态。

      如果您想在您的应用中提供帐户切换功能,则需要从您自己的应用中启动帐户选择器并提供在您实例化 GoogleApiClient 时选择的帐户名称。

      您可以将最后选择的帐户名称保留在共享首选项中,以便在用户下次切换帐户时记住它。

      【讨论】:

      • 感谢您的回答。不幸的是,这不是我所追求的。我的问题与从 Drive SDK v2 (SDKV2) 移植到新的 Google Drive Android API (GDAA) developers.google.com/drive/android 有关。在 SDKV2 中,我可以启动帐户选择器“startActivityForResult(newChooseAccountIntent(),...)”。在 GDAA 中,我必须按照您提到的方式进行操作,从而导致具有冗余的复杂代码。所以问题不是“如何解决”,而是 GDAA 中的“我有什么遗漏”。很抱歉第一次没有更具体。
      • 在 GDAA 中,如果您不提供帐户名称,它将使用默认帐户选择。如果尚未选择默认帐户,则会提示用户选择一个。在那之后,将始终使用该默认帐户。目前没有办法重置它。如果你想完全支持多个账户并在它们之间切换,你需要自己做账户选择逻辑。
      • 谢谢谢丽尔,我在下面添加了另一个答案,只是为了清理我造成的混乱。
      • 嗨 Cheryl,我想使用设备上不存在的帐户,例如第三方帐户。这可能吗?
      【解决方案5】:

      如果您使用 GoogleApiClient,只需致电 mGoogleApiClient.clearDefaultAccountAndReconnect()

      如果您将 DriveClient 与 GoogleSignInAccount(驱动器库 16.0.0)一起使用,请尝试此操作。

      // 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")
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-29
        • 1970-01-01
        • 2014-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-21
        相关资源
        最近更新 更多