Asynchronous account authentication with Volley

all.

I am using an account authenticator using AbstractAccountAuthenticator, and I need to call the asynchronous method in the getAuthToken function to authenticate the user. My code is as follows:

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

According to Google documentation for the getAuthToken method: it returns a Bundle result or null if the result should be returned via a response . The result will contain:
AccountManager.KEY_INTENT , 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

And I need to return null because the authentication method is asynchronous, but how do I return the Bundle via the "response" parameter, as per the documentation?
Thanks to everyone and excuse my English.

+5
source share
1 answer

Yes, I found a solution. You must use the "response" parameter to return the results. Below is the source that I use in my application. Hope this helps.

 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 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; }
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 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; } 
+5
source

Source: https://habr.com/ru/post/1203796/


All Articles