大家。
我使用AbstractAccountAuthenticator实现帐户身份验证,我需要在函数调用getAuthToken异步方法,以验证用户。 我的code是这样的:
I'm implementing an account authenticator using AbstractAccountAuthenticator and I need call an asynchronous method in the function getAuthToken, to authenticate a user. My code is like this:
public class AccountAuthenticator extends AbstractAccountAuthenticator {
...
@Override
public Bundle getAuthToken( final AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options )
throws NetworkErrorException
{
final AccountManager accountManager = AccountManager.get(context);
String authToken = accountManager.peekAuthToken( account, authTokenType );
// !!!!
if( TextUtils.isEmpty(authToken) ) {
<<call asynchronous method to acquire token>>
return null;
}
// !!!!
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
return result;
}
...
}
据谷歌的文档,以getAuthToken的方法:
它返回一个Bundle结果或空,如果结果是经由响应被返回的。
其结果将包含:
• AccountManager.KEY_INTENT
,或
• AccountManager.KEY_ACCOUNT_NAME
, AccountManager.KEY_ACCOUNT_TYPE
和 AccountManager.KEY_AUTHTOKEN
,或
• AccountManager.KEY_ERROR_ code
和 AccountManager.KEY_ERROR_MESSAGE
来指示错误
According to Google's documentation for the 'getAuthToken' method:
it returns a Bundle result or null if the result is to be returned via the response.
The result will contain either:
• AccountManager.KEY_INTENT
, or
• AccountManager.KEY_ACCOUNT_NAME
, AccountManager.KEY_ACCOUNT_TYPE
, and AccountManager.KEY_AUTHTOKEN
, or
• AccountManager.KEY_ERROR_CODE
and AccountManager.KEY_ERROR_MESSAGE
to indicate an error
和我需要返回null,因为认证方法是异步的,但如何通过'回应'参数返回该包,根据文档? 感谢所有,对不起我的英语水平。
And I need to return null because the authenticator method is asynchronous, but how I return the Bundle via the 'response' parameter, according to the documentation? Thanks for all, and sorry my english.
是的,我找到了解决办法。您必须使用'回应'参数来返回结果。下面是我在我的应用程序中使用的源代码。 我希望这可以帮助。
Yes, I found the solution. You must use the 'response' parameter to return the results. Below is the source that I use in my application. I hope this can help.
public Bundle getAuthToken( final AccountAuthenticatorResponse response, final Account account, String authTokenType, Bundle options )
throws NetworkErrorException
{
final Bundle result = new Bundle();
// We will not allow authentication for a type of account not used by the service.
if( false == authTokenType.equals(Accounts.TokenTypes.User) ) {
result.putString( AccountManager.KEY_ERROR_MESSAGE, context.getString(R.string.error_invalid_auth_token_type) );
return result;
}
final AccountManager accountManager = AccountManager.get(context);
String authToken = accountManager.peekAuthToken( account, authTokenType );
Token token = null;
// If the account already has an authorization key ...
if( ! TextUtils.isEmpty(authToken) )
{
// ...load its details from the userdata's account.
String tokenStr = accountManager.getUserData( account, Token.class.getName() );
JSONObject tokenJson = null;
try {
tokenJson = new JSONObject( tokenStr );
token = new Token( tokenJson );
}
catch( JSONException e ) {
token = new Token();
}
}
// But if the key is invalid or expired ...
if( token == null || token.isExpired() )
{
// ...loads the account user credentials to try to authenticate it.
new SignInRequest( new Client(), account.name, accountManager.getPassword(account),
new Response.Listener() {
@Override
public void onResponse( Token token ) {
/*
Response: a Bundle result or null if the result is to be returned via the response.
The result will contain either:
• AccountManager.KEY_INTENT (!!qdo envia o bundle para uma atividade!!), or
• AccountManager.KEY_ACCOUNT_NAME, AccountManager.KEY_ACCOUNT_TYPE, and AccountManager.KEY_AUTHTOKEN, or
• AccountManager.KEY_ERROR_CODE and AccountManager.KEY_ERROR_MESSAGE to indicate an error
*/
result.putString( AccountManager.KEY_ACCOUNT_NAME, account.name );
result.putString( AccountManager.KEY_ACCOUNT_TYPE, account.type );
result.putString( AccountManager.KEY_AUTHTOKEN, token.getAccessToken() );
response.onResult( result );
}
}
,
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
int errorCode = (volleyError.networkResponse == null ? -1 : volleyError.networkResponse.statusCode);
String errorMessage = null;
if( volleyError.getLocalizedMessage() != null )
errorMessage = volleyError.getLocalizedMessage();
else if( volleyError.getMessage() != null )
errorMessage = volleyError.getMessage();
else
errorMessage = volleyError.toString();
result.putInt( AccountManager.KEY_ERROR_CODE, errorCode );
result.putString( AccountManager.KEY_ERROR_MESSAGE, errorMessage );
response.onError( errorCode, errorMessage );
}
}
).execute( this.context );
// Returns null because we use the response parameter. See callbacks above.
return null;
}
// Otherwise, the key is valid, it returns.
result.putString( AccountManager.KEY_ACCOUNT_NAME, account.name );
result.putString( AccountManager.KEY_ACCOUNT_TYPE, account.type );
result.putString( AccountManager.KEY_AUTHTOKEN, authToken );
return result;
}