使用Volley进行异步帐户身份验证

时间:2014-10-01 12:45:26

标签: android asynchronous token android-volley accountmanager

大家。

我正在使用AbstractAccountAuthenticator实现帐户身份验证器,我需要在函数getAuthToken中调用异步方法来验证用户身份。 我的代码是这样的:

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

根据Google针对'getAuthToken'方法的文档: 如果要通过响应返回结果,则返回Bundle结果或 null。 结果将包含:
AccountManager.KEY_INTENT
AccountManager.KEY_ACCOUNT_NAMEAccountManager.KEY_ACCOUNT_TYPEAccountManager.KEY_AUTHTOKEN
AccountManager.KEY_ERROR_CODEAccountManager.KEY_ERROR_MESSAGE表示错误

我需要返回null,因为authenticator方法是异步的,但是根据文档我如何通过'response'参数返回Bundle?
谢谢大家,对不起我的英语。

1 个答案:

答案 0 :(得分:6)

是的,我找到了解决方案。您必须使用'response'参数来返回结果。以下是我在我的应用程序中使用的源代码。 我希望这可以提供帮助。



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