I have a SyncAdapter
for my app, and an AccountManager
to add my apps accounts to the Android Account Manager. My code for when I add an account to the Account Manager looks like:
Bundle data = new Bundle(5);
data.putString(_PEOPLE_ID, people_id);
data.putString(_FIRST_NAME, first_name);
data.putString(_LAST_NAME, last_name);
data.putString(_PLAN, plan);
data.putString(_BIRTHDAY, birthday);
Account account = new Account(username, _ACCOUNT_TYPE);
try {
boolean created;
created = _account_manager.addAccountExplicitly(account,
_cryptography.encrypt(_SEED, password), data);
response.accountCreated(created);
_account_manager.setAuthToken(account, _TOKEN_TYPE, session_token);
_model.updateActiveAccount(people_id, username, password);
SharedPreferences.Editor settings = _settings.edit();
settings.putString(_ACCOUNT_TYPE, account.name);
settings.putString(_TOKEN_TYPE, session_token);
settings.commit();
// Tells the content provider that it can sync this account
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
final Bundle extras = new Bundle(1);
extras.putBoolean(SYNC_EXTRAS_INITIALIZE, true);
ContentResolver.addPeriodicSync(account, AUTHORITY, extras, 900);
} catch (Exception e) {
Ln.e(e.getCause());
}
I can add the account to the Account Manager successfully through Settings, but I have to manually enable syncing for the account in Settings also, even though background data and sync automatically settings are enabled on the emulator. If I manually enable syncing, then the sync is performed fine, it just isn't started by default.
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
As Blehi said will initiate the automatic syncing of the given account, given the global Settings, "Background data" and "Auto-sync" are enabled.
To prevent the back-to-back syncing (from jcwenger) make sure that if any method in the
SyncAdapter.onPerformSync(...)
calls ContentResolver.notifyChange(...)
it uses ContentResolver.notifyChange(uri, observer, false)
to flag the notify not to trigger a sync call (the third parameter is syncToNetwork
).
If you're using the ContentProvider
to perform the inserts/deletes/updates for you SyncAdapter
it makes sense to call ContentResolver.notifyChange(...)
so that while the app is visible the user can receive updates from the SyncAdapter
, which means you will have the ContentProvider
making ContentResolver.notifyChange(...)
calls. To get this set up to work, I've added (following the dev guide) CALLER_IS_SYNC_ADAPTER
query parameter to every URI that is used for the SyncAdapter
. Add this method to the ContentProvider
to test the incoming URIs
/**
* Determines if the given URI specifies that the request is coming from the sync adapter.
* @param uri the given URI
* @return true if the uri specifies that the request is coming from the sync adapter
*/
private boolean callerIsSyncAdapter(Uri uri) {
final String is_sync_adapter = uri.getQueryParameter(CALLER_IS_SYNC_ADAPTER);
return is_sync_adapter != null && !is_sync_adapter.equals("0");
}
then you can do
getContext().getContentResolver().notifyChange(uri, observer, !callerIsSyncAdapter(uri));
whenever you need send a change notification.
And if you want to schedule the sync to be executed periodically at a frequency (polling the server) add this with the ContentResolver.setSyncAutomatically(...)
call.
ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), frequency_in_seconds)