Zaloguj się dwa razy podczas korzystania z SyncAdapters

Tworzę nową aplikację na Androida za pomocą SyncAdapter do obsługi db sync. Mam wszystko na miejscu i aplikacja działa dobrze, ale zauważyłem, że jestem zalogowany dwa razy.

Pierwsze logowanie odbywa się, gdy klasa AuthenticatorActivity (rozszerza AccountAuthenticatorActivity) waliduje użytkownika i hasło.

Jeśli użytkownik i hasło są poprawne {[2] } to robi:

  • Jeśli account nie istnieje, tworzy go za pomocą mAccountManager.addAccountExplicitly()
  • authToken jest zapisywany za pomocą intent.putExtra(AccountManager.KEY_AUTHTOKEN, authToken);

To było zasadniczo skopiowane / wklejone z próbek Androida, więc myślę, że jest ok.

Problem polega na tym, że gdy SyncAdapter uruchamia i używa

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

Wywoływana jest metoda getAuthToken() wewnątrz klasy Authenticator, która rozszerza AbstractAccountAuthenticator. I wewnątrz tej metody ponownie uderzam w punkt końcowy logowania.

Od tego momentu punkt końcowy logowania nie zostanie ponownie trafiony, dopóki authToken nie wygaśnie.

To nie jest coś, co przeszkadza mi bardzo, ale chciałbym wiedzieć, czy jest sposób, aby unikaj logowania dwa razy.

Author: Kyle Clegg, 2012-07-11

1 answers

Jak już widzieliście, choć Authenticator.java w SampleSyncAdapter mówi

Interesującą rzeczą, którą demonstruje ta klasa, jest użycie authTokens jako części procesu uwierzytelniania. ... Jeśli mamy już authtoken zapisane na koncie, zwracamy ten authToken. Jeśli nie, ale mamy nazwę użytkownika i hasło, spróbujemy porozmawiać z usługą przykładową, aby pobrać authToken.

To kłamstwo. Authenticator.getAuthToken nie sprawdza pamięci podręcznej, tylko uderza w sieć, aby uzyskać token.

Rozwiązaniem jest dodanie w brakującym czeku:

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

Zauważ, że reszta twojego projektu musi być religijnie używana AccountManager.invalidateAuthToken, gdy wywołania się nie powiodą, w przeciwnym razie skończysz z nieskończoną pętlą wywołań, próbując uzyskać nowy token auth, a następnie zawiedziesz ponownie, gdy ten sam buforowany Token auth zostanie zwrócony.

 14
Author: blahdiblah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-30 20:24:07