2014-10-01 35 views
5

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的?
謝謝大家,對不起我的英語。

回答

5

是的,我找到了解決方案。您必須使用'響應'參數來返回結果。以下是我在應用程序中使用的源代碼。 我希望這可以幫助。

 


    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