【问题标题】:Why is AccountAuthenticator#getAuthToken() not called?为什么没有调用 AccountAuthenticator#getAuthToken()?
【发布时间】:2015-09-13 00:11:03
【问题描述】:

我通过扩展AbstractAccountAuthenticator 并实现addAccount()getAuthToken() 创建了自己的Android 帐户验证器。其中的一些方法被AccountManager 调用,而另一些则不是。

这很好用:

AccountManager#addAccount()

AccountManager accountManager = AccountManager.get(activity);
accountManager.addAccount(MyAccountAuthenticator.ACCOUNT_TYPE,
    MyAccountAuthenticator.AUTHTOKEN_TYPE_FULL_ACCESS, null, null,
    activity, callback, null);

当我在我的Activity 中调用AccountManager#getAuthToken() 时,就会出现问题。 AccountManager 不会调用我在AccountAuthenticator 中定义的getAuthToken() 方法。它调用其他一些默认方法,仅在启动AuthenticatorActivity 之前检查authToken 的存在。

这不起作用。它不会调用我的getAuthToken() 方法:

AccountManager#getAuthToken()

AccountManager accountManager = AccountManager.get(activity);
accountManager.getAuthToken(
        mAccount, MyAccountAuthenticator.AUTHTOKEN_TYPE_FULL_ACCESS, null,
        activity, callback, handler);

AuthenticatorService

我创建了我的服务并定义了onBind()addAccount() 不应该工作。

public IBinder onBind(Intent intent) {
    return intent.getAction().equals(ACTION_AUTHENTICATOR_INTENT) ? new MyAccountAuthenticator(this).getIBinder() : null;
}

编辑:在应用为用户取回授权令牌后,我在MyAuthenticatorActivity 中调用addAccountExplicitly

来自MyAuthenticatorActivity extends AccountAuthenticatorActivity类的片段:

if (getIntent().getBooleanExtra(KEY_IS_ADDING_NEW_ACCOUNT, false)) {
    // Creating the account on the device and setting the auth token we recieved
    accountManager.addAccountExplicitly(account, null, null);
}

【问题讨论】:

  • 你在活动中使用过addAccountExplicitly吗?
  • 是的,我在 AccountAuthenticatorActivity 的子类中调用它。我已将其添加到问题的 EDIT 中。
  • 如果调用 getAuthToken 的结果是您的登录活动已启动,那么您的身份验证器将被调用 -- Android 没有其他方法可以确定要启动的活动,而不是您作为 Intent 返回的内容.我注意到您正在使用空密码添加帐户。如果你的实现找到一个空通道,也许它会短路?从您的身份验证者那里发布getAuthToken 的正文。
  • 正如我在问题中提到的,getAuthToken() 在存在现有身份验证令牌集时甚至不会被调用。它绕过调用并只返回身份验证令牌,这不是我期望它做的。我如何解释文档,它仍然应该调用我的方法。然后我可以决定是要返回现有令牌还是获取新令牌(我在返回之前检查身份验证令牌是否已过期)。
  • 密码为空,因为我使用的是 OAuth Bearer 令牌。无需设置密码,我从不使用该字段。 getAuthToken 方法在实际调用时效果很好,无需在那里查看源代码。

标签: java android accountmanager


【解决方案1】:

您的评论清楚地表明了一切——如果您为帐户设置了身份验证令牌,那么在令牌失效之前不会调用您的 getAuthToken 方法。您通常通过在收到 401 或 403 或来自网络服务的信息时致电 invalidateAuthToken 来执行此操作。

来自 getAuthToken 方法的 Javadoc:

如果为该帐户和类型缓存了先前生成的身份验证令牌,则将其返回。否则,如果保存的密码可用,则将其发送到服务器以生成新的身份验证令牌。否则,系统会提示用户输入密码。

由于你的令牌在缓存中,所以直接返回,不咨询你的验证器。

【讨论】:

  • 谢谢。文档对于何时调用身份验证器以及何时仅调用自己的代码非常模棱两可。我认为我的身份验证器应该实现您报价中描述的功能。
  • 没问题——我同意验证器文档通常很差。
  • 此外,如果 getAuthToken() 成功返回 KEY_AUTHTOKEN 一次,它会自动缓存(即使您的应用程序中没有任何对 AccountManager.setAuthToken() 的调用)。因此,对 AccountManager.getAuthToken() 的所有后续调用都不会导致调用 Authenticator.getAuthToken() 而只是立即返回 String 令牌。在 Android 4.3 Samsung Note 2 上测试。
  • 谢谢你们!那么,如果调用 getAuthToken() 已经为您完成了所有工作,为什么还有 peekAuthToken() 呢?我在 Authenticator 之外调用 setAuthToken,然后在我的 getAuthToken 中调用 peekAuthToken 来检查我们是否有缓存的 authToken ......但它没有被调用,因为 getAuthToken 已经为你完成了这项工作,对吧?
  • 这让我很开心!!那句话-如果您为帐户设置了身份验证令牌,那么在令牌无效之前不会调用您的 getAuthToken 方法-让我明白了一切
【解决方案2】:

在AccountManager#getAuthToken方法中调用AuthenticatorActivity,必须通过parcelable向Activity发送intent,例如:

    final Intent intent = new Intent(mContext, LoginActivity.class);
    intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, accountAuthenticatorResponse);
    intent.putExtra(LoginActivity.ARG_ACCOUNT_TYPE, account.type);
    intent.putExtra(LoginActivity.ARG_AUTH_TYPE, authTokenType);
    intent.putExtra(LoginActivity.ARG_ACCOUNT_NAME, account.name);
    final Bundle bundle = new Bundle();
    bundle.putParcelable(AccountManager.KEY_INTENT, intent);

【讨论】:

  • 这根本不能回答问题。
猜你喜欢
  • 2023-03-24
  • 2012-04-06
  • 2012-08-11
  • 2011-10-27
  • 2020-07-19
  • 2019-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多