Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/197.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 用户登录后重新运行/继续SyncAdapter_Android_Accountmanager_Android Syncadapter - Fatal编程技术网

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

Android 用户登录后重新运行/继续SyncAdapter,android,accountmanager,android-syncadapter,Android,Accountmanager,Android Syncadapter,如果在SyncAdapter.onPerformSync中,固有的身份验证令牌获取导致用户需要输入密码,用户成功登录后,如何重新运行或继续同步 虽然这似乎是一个相当标准的功能,但我一直找不到它的任何内容。似乎暗示要使用,但我尝试过,它从未被调用。此外,如果我对文档理解正确的话,任何账户的任何变更都会被要求,这似乎有点……间接 编辑 下面是我代码的相关部分。我一直密切关注这一点,这一点非常好 在Authenticator.getAuthToken中 // There is neither an a

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

虽然这似乎是一个相当标准的功能,但我一直找不到它的任何内容。似乎暗示要使用,但我尝试过,它从未被调用。此外,如果我对文档理解正确的话,任何账户的任何变更都会被要求,这似乎有点……间接

编辑 下面是我代码的相关部分。我一直密切关注这一点,这一点非常好

在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;
// 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();
在LoginActivity.finishLogin中

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

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

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

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

您不必重新运行它。如果您使用AccountManager.blockingGetAuthToken,您应该获得一个有效的令牌,或者没有。不,它返回
null
。啊!你的会计经理做得不对。它返回的bundle需要有一个KEY_INTENT值,用于命名验证活动。该活动需要获取响应对象(也在bundle中)并调用其onResponse方法。除了正在重新运行的同步外,一切都正常。返回
null
blockingGetAuthToken
记录行为的一部分。实际上,您不必重新运行同步。当blockingGetAuthToken返回时,您应该拥有已验证的帐户。如果验证器工作正常,则仅当帐户无效时,它才会返回null。见: