如何在新版Google云端硬盘Android API下切换帐户

时间:2014-02-06 17:46:34

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

我在新版Google云端硬盘Android API中的授权流程如下:

  1. 菜单:选择帐户
  2. 连接();
  3. onConnectionFailed() result.startResolutionForResult() 调用AccountSelectDialog / DriveAuthorization
  4. onConnected()   做你的东西
  5. 像魅力一样工作。现在重复目的是切换帐户:

    1. 菜单:选择帐户
    2. 连接();
    3. onConnected()
    4. 在这里,我没有机会进入 AccountSelectDialog 因为我从来没有得到 onConnectionFailed()和'result'来调用 startResolutionForResult()。我这次错过了什么?

5 个答案:

答案 0 :(得分:8)

首先,添加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

答案 1 :(得分:7)

致电

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

}

答案 2 :(得分:6)

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

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

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

所以结论是:

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

    这是一个包装器,用于在我的应用中保留和管理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));
      }
    }
    

    为亚历克斯洛克伍德提供最初的灵感。不幸的是,我找不到他原始代码的参考。

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

如果您使用GoogleApiClient,只需致电// 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") } }

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

public class CustomInfoWindow implements GoogleMap.InfoWindowAdapter {
    Context context; 
    LayoutInflater inflater;
    public CustomInfoWindow(Context context) {
           this.context = context;
    }
    @Override    
    public View getInfoContents(Marker marker) {        
        return null;    
    }
    @Override
    public View getInfoWindow(Marker marker) {
    inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  

   // R.layout.custom_info_window is a layout
   // res/layout folder. You can provide your own
    View v = inflater.inflate(R.layout.custom_info_window, null);   

    TextView title = (TextView) v.findViewById(R.id.info_window_title);     
  TextView subtitle = (TextView) v.findViewById(R.id.info_window_subtitle);
    title.setText(marker.getTitle());
    subtitle.setText(marker.getSnippet());
    return v;
    }
}