我也观察到了这种行为。
正确的是, addAccountExplicit() 将触发系统范围内的过期帐户重新同步。
澄清
但是,Zapek 关于 addPeriodic 同步或请求同步是“立即”同步的观察并不完全正确。两者都只是排队。此外,对于 addPeriodicSync(),以下内容成立:
这些定期同步遵循“syncAutomatically”和“masterSyncAutomatically”设置。尽管这些同步是按指定的频率安排的,但如果同步操作队列中其他同步在它之前,它可能需要更长的时间才能真正启动。这意味着实际开始时间可能会漂移。(文档)
与您的问题有关
在运行同步适配器的培训中描述了您的体验:
addPeriodicSync() 方法不会禁用 setSyncAutomatically(),因此您可能会在相对较短的时间内获得多次同步运行。此外,在对 addPeriodicSync() 的调用中只允许使用少数同步适配器控制标志;addPeriodicSync() 的参考文档中描述了不允许的标志。
Android 训练同步适配器
谷歌自己的解决方案看起来像你的,甚至频率更低(60*60=3600):
if (accountManager.addAccountExplicitly(account, null, null)) {
// Inform the system that this account supports sync
ContentResolver.setIsSyncable(account, CONTENT_AUTHORITY, 1);
// Inform the system that this account is eligible for auto sync when the network is up
ContentResolver.setSyncAutomatically(account, CONTENT_AUTHORITY, true);
// Recommend a schedule for automatic synchronization. The system may modify this based
// on other scheduled syncs and network utilization.
ContentResolver.addPeriodicSync(
account, CONTENT_AUTHORITY, new Bundle(),SYNC_FREQUENCY);
newAccount = true;
}
主张
我建议使用 onPerformSync() 中的 SyncStats 将有关初始同步的一些信息实际返回到系统,以便更有效地进行调度。
syncResult.stats.numEntries++; // For every dataset
如果已经安排了其他任务,这可能无济于事 - 调查
此外,可以设置一个标志“isInitialOnPerformSync”(w.sharedPreferences),以使其他任务备份。
syncResult.delayUntil = <time>;
我个人不太喜欢在初始同步后创建固定的不同步时间范围。
进一步考虑 - 立即初始同步
如说明中所述,同步不会立即使用您的设置运行。有一个解决方案,可以让您立即同步。这不会影响同步设置,也不会导致它们回退,这就是为什么这不能解决您的问题,但它的效果是您的用户不必等待同步启动。如果您使用此功能很重要以这种方式在您的应用中显示主要内容。
代码:在您的正常应用程序进程中为isInitialSync设置一个标志(例如保存在 defaultSharedPreferences 中)。您甚至可以使用在初始完成安装或登录(如果需要身份验证)后,您可以调用立即同步,如下所示。
/**
* Start an asynchronous sync operation immediately. </br>
*
* @param account
*/
public static void requestSyncImmediately(Account account) {
// Disable sync backoff and ignore sync preferences. In other words...perform sync NOW!
Bundle settingsBundle = new Bundle();
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
// Request sync with settings
ContentResolver.requestSync(account, SyncConstants.CONTENT_AUTHORITY, settingsBundle);
}