in my project I need to connect regularly to a server. Therefore I'm implementing an AccountAuthenticator and SyncAdapter to plug them into androids framework. It is critical for the application to connect regularly, say every 5 or 10 minutes.
No matter whether I store the password or an authToken, both can become invalid and the SyncAdapter wouldn't be able to sync any more. Logically the user needs to be informed.
I wanted to display the login form if AccountAuthenticator.getAuthToken(..)
can't get a new authToken:
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response,
Account account, String authTokenType,
Bundle options) throws NetworkErrorException {
// code derived from SampleSyncAdapter
// If the caller requested an authToken type we don't support, then
// return an error
if (!authTokenType.equals(Helper.ACCOUNT_TYPE)) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ERROR_MESSAGE,
"invalid authTokenType");
return result;
}
// Extract the username and password from the Account Manager, and ask
// the server for an appropriate AuthToken.
final AccountManager am = AccountManager.get(context);
final String password = am.getPassword(account);
if (password != null) {
final LoginData loginData =
NetworkUtility.authenticate(account.name, password);
if (loginData.wasSuccessful() &&
!TextUtils.isEmpty(loginData.getAuthenticationToken())) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE,
Helper.ACCOUNT_TYPE);
result.putString(AccountManager.KEY_AUTHTOKEN,
loginData.getAuthenticationToken());
return result;
}
}
// If we get here, then we couldn't access the user's password - so we
// need to re-prompt them for their credentials. We do that by creating
// an intent to display our AuthenticatorActivity panel.
final Intent intent = new Intent(context, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
but unfortunately this doesn't work, no prompt is created.
I didn't find any information on what would be the best practise way. I've checked the new CouchSurfing app and they simply remove the account. I didn't check now, but I think Google would disable synchronisation. Neither solution would work for my use case.
The solution is simpler than i thought and google also does it:
Post a message to the notification area (http://developer.android.com/guide/topics/ui/notifiers/notifications.html), and when opening it, the login screen can be shown.