用户登录后重新运行/继续SyncAdapter

时间:2014-05-10 15:16:58

标签: android accountmanager android-syncadapter

如果在SyncAdapter.onPerformSync中固有获取身份验证令牌导致用户需要输入密码,如何成功登录后重新运行或继续同步?< / p>

虽然这似乎是一个相当标准的功能,但我一直无法找到它。 AccountManager.getAuthToken docs似乎暗示使用an OnAccountsUpdatedListener,但我已经尝试过,它永远不会被调用。此外,如果我理解正确的文档,那么将会调用任何更改任何帐户,这似乎有点......间接。

修改

以下是我的代码的相关部分。我密切关注official guide和优秀的blog post by Udinic

在Authenticator.getAuthToken

// There is neither an access nor a refresh token. User has to log in
if (!tokens.hasAccess() && !tokens.hasRefresh()) {
    Intent intent = new Intent(context, LoginActivity.class);
    intent.putExtra(LoginActivity.ARG_ACCOUNT, account);
    intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); // As per AbstractAccountAuthenticator doc
    bundle.putParcelable(AccountManager.KEY_INTENT, intent);
}
...
return bundle;

在LoginActivity.finishLogin

// Store access token if one was provided. Note that this should always be the case anyway,
// otherwise the login would have been unsuccessful
if (tokens.hasAccess()) {
    manager.setAuthToken(account, Authenticator.TOKEN_TYPE_ACCESS, tokens.access);
}
// Store refresh token if one was provided.
if (tokens.hasRefresh()) {
    manager.setAuthToken(account, Authenticator.TOKEN_TYPE_REFRESH, tokens.refresh);
}
final Intent intent = new Intent();
if (tokens.hasAccess()) {
    intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
    intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type);
    intent.putExtra(AccountManager.KEY_AUTHTOKEN, tokens.access);
}

setAccountAuthenticatorResult(intent.getExtras());
setResult(Activity.RESULT_OK, intent);
finish();

而且,即使它有点微不足道: 在SyncAdapter.onPerformSync中:

String token = null;
try {
    token = AccountManager.get(getContext()).blockingGetAuthToken(account, Authenticator.TOKEN_TYPE_ACCESS, true);
    if (token == null) {
        syncResult.stats.numAuthExceptions++;
        return;
    }
} catch (OperationCanceledException x) {
    return;
} catch (AuthenticatorException x) {
    syncResult.stats.numAuthExceptions++;
    return;
} catch (IOException x) {
    syncResult.stats.numIoExceptions++;
    return;
}

1 个答案:

答案 0 :(得分:1)

经过一番讨论,我相信你需要的是:

ContentResolver.requestSync(account, Contract.AUTHORITY, new Bundle());

您的客户经理非常合理地导致blockingGetAuthToken立即返回null,此时需要用户交互才能完成同步。您只需要安排,当用户完成操作(验证自己)时,您请求新的同步。上面的代码就可以了。