Syncadapter onPerformSync第一次被调用两次

我的syncadapter效果很好,除了一件事。 用户安装应用程序后,我的应用程序会同步两次。 稍后,如果我在“设置”中手动同步它,它只会按预期同步一次。 这只是应用程序的第一次运行。

这是我的“onCreate”中的代码,如果尚未创建帐户,则创建帐户并设置syncadapter。 关于我做错的任何想法?

if (accountManager.addAccountExplicitly(appAccount, null, null)) { ContentResolver.setIsSyncable(appAccount, PROVIDER, 1); ContentResolver.setSyncAutomatically(appAccount, PROVIDER, true); Bundle extras = new Bundle(); extras.putBoolean("dummy stuff", true); ContentResolver.addPeriodicSync(appAccount, PROVIDER, extras, 43200); } 

我希望的行为是让应用程序在安装后立即同步一次,然后根据“addPeriodicSync”语句定期进行同步。

我也观察到了这种行为。

这是正确的,addAccountExplicit()将触发过时帐户的系统范围帐户重新同步。

Clarificiation

但是,Zapek关于addPeriodic同步或请求同步是“立即”同步的观察结果并不完全正确。 两者都排队等候。 此外,以下适用于addPeriodicSync():

这些定期同步支持“syncAutomatically”和“masterSyncAutomatically”设置。 虽然这些同步是按指定的频率进行调度的,但如果在同步操作队列中其他同步位于其前面,则实际启动它可能需要更长的时间。 这意味着实际开始时间可能会漂移。 ( 文件 )

与您的问题有关

在运行同步适配器的培训中描述了您的体验:

方法addPeriodicSync()不会禁用setSyncAutomatically(),因此您可以在相对较短的时间内获得多个同步运行。 此外,在调用addPeriodicSync()时,只允许使用几个同步适配器控制标志。 addPeriodicSync()的引用文档中描述了不允许的标志。 Android培训同步适配器

Google自己的解决方案与您的解决方案相似,甚至频率较低(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 =  

我个人并不喜欢在初始同步后创建固定的无同步时间帧。

进一步的考虑 – 立即初始同步

如澄清中所述,同步不会立即与您的设置一起运行。 有一个解决方案,可让您立即同步。 这不会影响同步设置,也不会导致它们退避,这就是为什么这不能解决您的问题,但这会导致您的用户不必等待同步启动。重要的是,如果您使用此function以这种方式在您的应用中显示主要内容。

代码:在正常的应用程序进程中设置isInitialSync的标志(例如,在defaultSharedPreferences中保存)。 您甚至可以使用在初始完成安装或登录时(如果需要validation),您可以调用立即同步,如下所示。

 /** * Start an asynchronous sync operation immediately.  * * @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); } 

您是否要求addPeriodicSync()之外的同步?

首次添加帐户时,它应自行同步。 因此任何额外的同步请求都会考虑双重同步。

如果这没有帮助,您可以始终在首选项中保存上次同步的时间并检查每次同步,以便您可以将同步频率限制为您想要的任何频率。

希望有所帮助!

addAccountExplicitely() 导致具有未知可同步状态的所有帐户(包括新添加的SyncAdapter)的同步。

问题是执行时间可能需要几秒到几分钟,具体取决于安装了SyncAdapter和配置帐户的其他应用程序的数量。

addPeriodicSync()(或requestSync())将立即执行同步,这在用户需要在启动应用程序时尽快查看数据时是理想的。

除了确保在客户端和服务器之间没有数据发生变化的情况下快速优化同步时,您无能为力。