Volley的异步账号认证

问题描述:

everyone。Volley的异步账号认证

我正在使用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; 
    } 
    ... 
} 

根据谷歌的文档,以“getAuthToken”的方法: 它返回一个Bundle结果或NULL,如果结果是通过响应归还。 结果将包含两种:0​​ •AccountManager.KEY_INTENT,或
AccountManager.KEY_ACCOUNT_NAMEAccountManager.KEY_ACCOUNT_TYPEAccountManager.KEY_AUTHTOKEN,或
AccountManager.KEY_ERROR_CODEAccountManager.KEY_ERROR_MESSAGE指示错误

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

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

 


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

 
+0

谢谢,但返回null和OnResponse运行在不同的线程!!!! – SanatiSharif 2015-02-28 20:24:14

+0

@SanatiSharif没问题! “回应”这个论点是你的家伙会退回你的respost。当你的方法不能立即返回的时候,它真的用于这个。例如,请参阅行:'response.onResult(result)';和'response.onError(result);' – Luciano 2015-10-19 18:12:44