android android-syncadapter

android - Inicie sesión dos veces cuando use SyncAdapters



android-syncadapter (1)

Estoy creando una nueva aplicación de Android usando SyncAdapter para manejar db sync. Tengo todo en su lugar y la aplicación funciona bien, pero me di cuenta de que me conecté dos veces.

El primer inicio de sesión tiene lugar cuando la clase AuthenticatorActivity (extiende AccountAuthenticatorActivity ) valida el usuario y la contraseña.

Si el usuario y la contraseña son correctos, AuthenticatorActivity entonces:

  • Si la account no existía, la crea utilizando mAccountManager.addAccountExplicitly()
  • El authToken se guarda utilizando intent.putExtra(AccountManager.KEY_AUTHTOKEN, authToken);

Esto fue básicamente copiado / pegado de las muestras de Android, así que supongo que está bien.

El problema es que cuando SyncAdapter inicia y usa

authtoken = mAccountManager.blockingGetAuthToken(account, AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, true);

Se getAuthToken() método getAuthToken() dentro de la clase Authenticator que extiende AbstractAccountAuthenticator . Y dentro de este método estoy golpeando el punto final de inicio de sesión una vez más.

A partir de ese momento, el punto final de inicio de sesión no se volverá a alcanzar hasta que authToken la authToken .

Esto no es algo que me moleste mucho, pero me gustaría saber si hay una manera de evitar hacer el inicio de sesión dos veces.


Como has visto, aunque Authenticator.java en el SampleSyncAdapter dice

Lo interesante que demuestra esta clase es el uso de authTokens como parte del proceso de autenticación. ... Si ya tenemos un authToken almacenado en la cuenta, devolvemos ese authToken. Si no lo hacemos, pero tenemos un nombre de usuario y una contraseña, intentaremos hablar con el servicio de muestra para obtener un authToken.

eso es una mentira. Authenticator.getAuthToken no realiza ninguna comprobación de caché, solo llega a la red para obtener un token.

La solución es agregar en el cheque faltante:

Authenticator.java: @Override public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws NetworkErrorException { // check that authToken type supported ... // Check if we already have a cached token to return final AccountManager am = AccountManager.get(mContext); String cachedAuthToken = am.peekAuthToken(account, authTokenType); if (cachedAuthToken != null) { final Bundle result = new Bundle(); result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE); result.putString(AccountManager.KEY_AUTHTOKEN, cachedAuthToken); return result; } // Get new authToken from server ... // If all else fails, prompt the user for credentials ... }

Tenga en cuenta que el resto de su proyecto necesita usar religiosamente AccountManager.invalidateAuthToken cuando las llamadas fallan o de lo contrario terminará con un bucle infinito de llamadas que fallan, tratando de obtener un nuevo token de autenticación, y luego fallan de nuevo cuando el mismo token de autenticación en caché es regresado.