Подтвердить что ты не робот

Как долго связки сохраняются SyncManager?

У меня есть приложение с SyncAdapter. В дополнение к обычной синхронизации я запускаю событие USER_READ, с которым я просто передаю Bundle в адаптер, не сохраняя его:

Bundle settingsBundle = new Bundle();
settingsBundle.putString(SyncAdapter.USER_READ, uid);
ContentResolver.requestSync(account, authority, settingsBundle);

Это правильно вызовет мою процедуру синхронизации в будущем. Каждый uid, установленный в Bundle, запускает свой собственный запуск, и все синхронизируется, как ожидалось.

Если теперь соединение плохое или время ожидания запроса, я установил мягкую ошибку:

syncResult.stats.numIoExceptions += 1;

который заставит запрос повторить позже. Это также прекрасно работает.


Как долго сохраняются эти SyncRequests/Bundles?

В документации указано, что встреча с мягкой ошибкой приведет к экспоненциальному отклонению и что синхронизация будет запущена через некоторое время.

  • Будет ли он отменен в какой-то момент? После нескольких мягких ошибок?
  • Будет ли он снова установлен в очередь после перезагрузки устройства?

Учитывая, что соединение плохое, и синхронизация несколько раз прерывается с помощью мягких ошибок: я хотел бы знать, достаточно ли просто задать запрос на синхронизацию, или если я должен сам обеспечить некоторую настойчивость, чтобы обеспечить отправку запросов на некоторых точка.

4b9b3361

Ответ 1

Мне пришлось немного выкопать исходный код Android, чтобы найти ответ на ваш вопрос. Пусть начнется с первой части вопроса.

Будет ли это [синхронизация] отменена в какой-то момент? После нескольких мягких ошибок?

И ответ, вероятно, нет, пока не будет выполнено одно из следующих условий:

  • синхронизация отменена
  • вы просите SyncManager не перепланировать синхронизацию, запустив SyncAdapter с помощью ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY
  • вы устанавливаете SyncResult.tooManyRetries в true, а синхронизация не выполняется только для загрузки
  • вы устанавливаете SyncResult.tooManyDeletions в true, не устанавливайте SyncStats.numInserts или SyncStats.numUpdates на ненулевые значения, а синхронизация не выполняется только для загрузки
  • Синхронизация не имеет мягких ошибок, но имеет некоторые жесткие ошибки, и она не загружается только
  • синхронизация выполняется более 30 минут.
  • sync не использует сеть более 1 минуты

Таким образом, множественные мягкие ошибки не отменят синхронизацию, и вот почему.

Обработка всех событий синхронизации начинается в SyncManager.SyncHandler.handleMessage() и продолжается в SyncManager.runSyncFinishedOrCanceledH(). Первый аргумент runSyncFinishedOrCanceledH() равен SyncResult, который может быть null. Это не null либо при завершении синхронизации, либо при отключении службы SyncAdapter, что является мягкой ошибкой. И он null, когда синхронизация отменена, истек (работает более 30 минут), не используя сеть более 1 минуты, а в другом случае я не совсем понимаю.

В случае, если SyncResult не null, а синхронизация завершена с ошибками, SyncManager пытается перенести синхронизацию, вызвав maybeRescheduleSync(). Эти методы проверяют некоторые флаги и результаты синхронизации, такие как ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY и SyncResult.tooManyRetries, чтобы решить, нужно ли перепланировать синхронизацию. И после того, как SyncManager проверит, что синхронизация завершена с мягкой ошибкой syncResult.hasSoftError(), она переписывает синхронизацию без каких-либо дополнительных проверок.

А теперь вторая часть вопроса.

Будет ли [sync] повторно вставлена ​​после перезагрузки устройства?

Да, будет. Когда SystemServer инициализирует, он создает ContentService, а затем вызывает метод systemReady(), который в его поворот создает SyncManager. SyncManager в своем конструкторе создает SyncStorageEngine, который читает все ожидающие операции в своем конструкторе включая дополнительные пакеты. Поэтому набор типов, разрешенных в пакетах синхронизации, очень ограничен. И когда пользователь запускает все ожидающие операции операции, добавляются в SynqQueue, вызывая SyncQueue.addPendingOperations().

Этот ответ является результатом моего анализа кода Android, поэтому я не могу гарантировать его на 100% правильно. Но вы можете использовать эту информацию в качестве отправной точки для своих собственных исследований.