SyncManager 会保留 bundle 多长时间?
How long do bundles get persisted by SyncManager?
我有一个 SyncAdapter
的应用程序。除了正常同步之外,我还触发了一个 USER_READ
事件,我只是将 Bundle
传递给适配器而不保留它:
Bundle settingsBundle = new Bundle();
settingsBundle.putString(SyncAdapter.USER_READ, uid);
ContentResolver.requestSync(account, authority, settingsBundle);
这将在将来的某个时候正确调用我的同步例程。在 Bundle
中设置的每个 uid
都会触发它自己的 运行 并且所有内容都会按预期同步。
如果现在连接不好,或者请求超时,那么我设置一个软错误:
syncResult.stats.numIoExceptions += 1;
这将导致稍后重复请求。这也很好用。
这些 SyncRequests/Bundle 会持续多久?
文档指出,遇到软错误将导致指数退避,并且同步将在 运行 一段时间后。
- 它会在某个时候被取消吗?在多次软错误之后?
- 设备重启后是否会再次入队?
考虑到连接不好并且同步因软错误多次失败:我想知道仅将同步请求排入队列是否足够,或者我是否必须自己提供某种持久性以确保发送请求在某个时候。
我不得不深入研究 Android 运行时源代码才能找到您问题的答案。让我们从问题的第一部分开始。
Will it [sync] be canceled at some point? After multiple soft errors?
在满足以下条件之一之前,答案可能是否定的:
- 同步被取消
- 您要求
SyncManager
不要通过从 SyncAdapter
开始与 ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY
重新安排同步
- 您将
SyncResult.tooManyRetries
设置为 true
并且同步不是仅上传
- 您将
SyncResult.tooManyDeletions
设置为 true
,不要将 SyncStats.numInserts
或 SyncStats.numUpdates
设置为非空值,并且同步不是仅上传
- sync 没有软错误但有一些硬错误,而且它不是仅上传
- 同步运行超过 30 分钟
- 同步未使用网络超过 1 分钟
所以多个软错误不会取消同步,原因如下。
处理所有同步事件从 SyncManager.SyncHandler.handleMessage()
method and continues in SyncManager.runSyncFinishedOrCanceledH()
方法开始。 runSyncFinishedOrCanceledH()
的第一个参数是SyncResult
,可以是null
。同步完成后或SyncAdapter
服务断开时都不是null
,这是一个软错误。还有null
当同步被取消,过期(运行超过30分钟),不使用网络超过1分钟,还有一种情况我不完全理解。
如果 SyncResult
不是 null
并且同步完成时出现错误,SyncManager
会尝试通过调用 maybeRescheduleSync()
. This methods checks some flags and sync results, like ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY
and SyncResult.tooManyRetries
do decide if it needs to reschedule sync. And after SyncManager
checks that sync finished with a soft error syncResult.hasSoftError()
重新安排同步,它会在不进行任何额外检查的情况下重新安排同步。
现在是问题的第二部分。
Will it [sync] be enqueued again after a reboot of the device?
是的,会的。当 SystemServer
初始化时,它创建 ContentService
and then calls its systemReady()
method, which in its turn creates SyncManager
. SyncManager
in its constructor creates SyncStorageEngine
, which reads all pending operations in its constructor including extra bundles. That's why a set of types allowed in sync bundles is very limited. And when user is starting all pending operations are added to SynqQueue
by calling SyncQueue.addPendingOperations()
.
这个答案是我分析 Android 代码的结果,所以我不能保证它 100% 正确。但您可以将这些信息作为您自己研究的起点。
我有一个 SyncAdapter
的应用程序。除了正常同步之外,我还触发了一个 USER_READ
事件,我只是将 Bundle
传递给适配器而不保留它:
Bundle settingsBundle = new Bundle();
settingsBundle.putString(SyncAdapter.USER_READ, uid);
ContentResolver.requestSync(account, authority, settingsBundle);
这将在将来的某个时候正确调用我的同步例程。在 Bundle
中设置的每个 uid
都会触发它自己的 运行 并且所有内容都会按预期同步。
如果现在连接不好,或者请求超时,那么我设置一个软错误:
syncResult.stats.numIoExceptions += 1;
这将导致稍后重复请求。这也很好用。
这些 SyncRequests/Bundle 会持续多久?
文档指出,遇到软错误将导致指数退避,并且同步将在 运行 一段时间后。
- 它会在某个时候被取消吗?在多次软错误之后?
- 设备重启后是否会再次入队?
考虑到连接不好并且同步因软错误多次失败:我想知道仅将同步请求排入队列是否足够,或者我是否必须自己提供某种持久性以确保发送请求在某个时候。
我不得不深入研究 Android 运行时源代码才能找到您问题的答案。让我们从问题的第一部分开始。
Will it [sync] be canceled at some point? After multiple soft errors?
在满足以下条件之一之前,答案可能是否定的:
- 同步被取消
- 您要求
SyncManager
不要通过从SyncAdapter
开始与ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY
重新安排同步
- 您将
SyncResult.tooManyRetries
设置为true
并且同步不是仅上传 - 您将
SyncResult.tooManyDeletions
设置为true
,不要将SyncStats.numInserts
或SyncStats.numUpdates
设置为非空值,并且同步不是仅上传 - sync 没有软错误但有一些硬错误,而且它不是仅上传
- 同步运行超过 30 分钟
- 同步未使用网络超过 1 分钟
所以多个软错误不会取消同步,原因如下。
处理所有同步事件从 SyncManager.SyncHandler.handleMessage()
method and continues in SyncManager.runSyncFinishedOrCanceledH()
方法开始。 runSyncFinishedOrCanceledH()
的第一个参数是SyncResult
,可以是null
。同步完成后或SyncAdapter
服务断开时都不是null
,这是一个软错误。还有null
当同步被取消,过期(运行超过30分钟),不使用网络超过1分钟,还有一种情况我不完全理解。
如果 SyncResult
不是 null
并且同步完成时出现错误,SyncManager
会尝试通过调用 maybeRescheduleSync()
. This methods checks some flags and sync results, like ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY
and SyncResult.tooManyRetries
do decide if it needs to reschedule sync. And after SyncManager
checks that sync finished with a soft error syncResult.hasSoftError()
重新安排同步,它会在不进行任何额外检查的情况下重新安排同步。
现在是问题的第二部分。
Will it [sync] be enqueued again after a reboot of the device?
是的,会的。当 SystemServer
初始化时,它创建 ContentService
and then calls its systemReady()
method, which in its turn creates SyncManager
. SyncManager
in its constructor creates SyncStorageEngine
, which reads all pending operations in its constructor including extra bundles. That's why a set of types allowed in sync bundles is very limited. And when user is starting all pending operations are added to SynqQueue
by calling SyncQueue.addPendingOperations()
.
这个答案是我分析 Android 代码的结果,所以我不能保证它 100% 正确。但您可以将这些信息作为您自己研究的起点。