2014-10-01 9 views
5

tutti.Autenticazione asincrona dell'account con Volley

Sto implementando un account authenticator utilizzando AbstractAccountAuthenticator e ho bisogno di chiamare un metodo asincrono nella funzione getAuthToken, per autenticare un utente. Il mio codice è simile a questo:

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

Secondo la documentazione di Google per il metodo 'getAuthToken': si restituisce un risultato Bundle o null se il risultato deve essere restituito tramite la risposta. Il risultato sarà contenere alternativamente:
AccountManager.KEY_INTENT, o
AccountManager.KEY_ACCOUNT_NAME, AccountManager.KEY_ACCOUNT_TYPE e AccountManager.KEY_AUTHTOKEN, o
AccountManager.KEY_ERROR_CODE e AccountManager.KEY_ERROR_MESSAGE per indicare un errore

e ho bisogno di restituire null perché il metodo di autenticazione è asincrono, ma come restituisco il pacchetto tramite il parametro 'response', secondo la documentazione?
Grazie a tutti, e scusa il mio inglese.

risposta

5

Sì, ho trovato la soluzione. È necessario utilizzare il parametro 'response' per restituire i risultati. Di seguito è la fonte che utilizzo nella mia applicazione. Spero che questo possa aiutare.

 


    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

grazie, ma restituire null e OnResponse eseguire su thread diversi !!!! – SanatiSharif

+0

@SanatiSharif Nessun problema! L'argomento 'risposta' è il tipo da te restituirai il tuo responso. È usato davvero per questo, quando il tuo metodo non può tornare immediatamente. Ad esempio, vedi le linee: 'response.onResult (result)'; e 'response.onError (result);' – Luciano