2014-10-01 12 views
5

wszyscy.Asynchroniczne uwierzytelnianie konta z Volley

Wdrażam konto uwierzytelniające przy użyciu AbstractAccountAuthenticator i potrzebuję wywołać metodę asynchroniczną w funkcji getAuthToken, aby uwierzytelnić użytkownika. Mój kod to tak:

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

Według dokumentacji Google na metodzie „getAuthToken”: zwraca wynik Bundle lub null, jeśli wynik ma być zwrócony przez odpowiedź. Wynik będzie zawierać albo:
AccountManager.KEY_INTENT lub
AccountManager.KEY_ACCOUNT_NAME, AccountManager.KEY_ACCOUNT_TYPE i AccountManager.KEY_AUTHTOKEN lub
AccountManager.KEY_ERROR_CODE i AccountManager.KEY_ERROR_MESSAGE wskazać błąd

I muszę zwróci null ponieważ metody Authenticator jest asynchroniczny, ale w jaki sposób zwracam pakiet za pomocą parametru "odpowiedzi", zgodnie z dokumentacją?
Dziękuję za wszystko i przepraszam za angielski.

Odpowiedz

5

Tak, znalazłem rozwiązanie. Musisz użyć parametru "response", aby zwrócić wyniki. Poniżej znajduje się źródło, którego używam w mojej aplikacji. Mam nadzieję, że to może pomóc.

 


    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

dziękuję, ale zwrot null i OnResponse przebiegają przez różne wątki !!!! – SanatiSharif

+0

@SanatiSharif Bez problemu! Argument "odpowiedź" to facet od którego zwrócisz odpowiedź. Używa się go naprawdę do tego, kiedy twoja metoda nie może natychmiast wrócić. Na przykład zobacz linie: 'response.onResult (result)'; oraz 'response.onError (result);' – Luciano

Powiązane problemy