Android SyncAdapter автоматически инициализирует синхронизацию
У меня есть SyncAdapter
для моего приложения и AccountManager
для добавления учетных записей моих приложений в Диспетчер учетных записей Android. Мой код для добавления учетной записи в диспетчер аккаунта выглядит так:
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());
}
Я могу добавить учетную запись в диспетчер аккаунта с помощью настроек, но мне также нужно вручную включить синхронизацию для учетной записи в настройках, даже если фоновые данные и автоматические настройки синхронизации включены в эмуляторе. Если я вручную включу синхронизацию, то синхронизация выполняется нормально, она просто не запускается по умолчанию.
Ответы
Ответ 1
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Как Blehi сказал, что будет инициировать автоматическую синхронизацию данной учетной записи, учитывая глобальные настройки, включены "Фоновые данные" и "Автосинхронизация".
Чтобы предотвратить синхронизацию "back-to-back" (от jcwenger), убедитесь, что если какой-либо метод в
SyncAdapter.onPerformSync(...)
вызывает ContentResolver.notifyChange(...)
он использует ContentResolver.notifyChange(uri, observer, false)
, чтобы отметить уведомление, чтобы не запускать вызов синхронизации (третий параметр syncToNetwork
).
Если вы используете ContentProvider
для выполнения вставок/удалений/обновлений для вас SyncAdapter
, имеет смысл вызвать ContentResolver.notifyChange(...)
, чтобы при видимости приложения пользователь мог получать обновления от SyncAdapter
, что означает, что у вас будет ContentProvider
выполнение ContentResolver.notifyChange(...)
вызовов. Чтобы настроить этот набор на работу, я добавил (после руководство разработчика) CALLER_IS_SYNC_ADAPTER
параметр запроса для каждый URI, который используется для SyncAdapter
. Добавьте этот метод к ContentProvider
для проверки входящих URI
/**
* 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");
}
то вы можете сделать
getContext().getContentResolver().notifyChange(uri, observer, !callerIsSyncAdapter(uri));
когда вам нужно отправить уведомление об изменении.
И если вы хотите запланировать синхронизацию, которая будет выполняться периодически с частотой (опрос сервера), добавьте ее с вызовом ContentResolver.setSyncAutomatically(...)
.
ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), frequency_in_seconds)
Ответ 2
Чтобы подчеркнуть, кажется, что addPeriodicSync() требует setSyncAutomatically(), хотя в документации указано, что setSyncAutomatically() предназначен только для обнаружения сетевых щекоток.
Обратите внимание, что период будет скорректирован до > 60 с, если он меньше минуты.
Ответ 3
По умолчанию вы должны установить синхронизацию:
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Я использую вышеуказанные 2 строки и работает нормально.
Ответ 4
Сначала создайте учетную запись и проверьте поддержку синхронизации для нее с помощью AccountManager. Если учетная запись поддерживает синхронизацию, вызовите setIsSyncable() и setSyncAutomatically().
AccountManager accountManager = (AccountManager) this.getSystemService(ACCOUNT_SERVICE);
if(accountManager.addAccountExplicitly(newAccount, null, null)){
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
}
Затем вы можете запускать синхронизацию в любое время. Он будет срабатывать.
Примечание: onPerformSync() для setSyncAutomatically() будет вызываться первым, тогда будет инициирован только другой запрос синхронизации.
Но для принудительной синхронизации просто добавьте еще 2 дополнительных флага.
Bundle bundle= new Bundle();
bundle.putBoolean(
ContentResolver.SYNC_EXTRAS_MANUAL, true);
bundle.putBoolean(
ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
ContentResolver.requestSync(account, AUTHORITY, bundle);