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 utilizandomAccountManager.addAccountExplicitly()
- El
authToken
se guarda utilizandointent.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.