Syncadapter onPerformSync在第一次被调用两次

我的同步适配器运行良好,除了一件事。 用户安装应用程序后,我的应用程序同步两次。 之后,如果我在“设置”中手动同步它,则只会按照预期同步一次。 这只是应用程序的第一次运行,发生这种情况。

这是我的“onCreate”中的代码,如果尚未创build帐户,则创build帐户并设置同步适配器。 任何想法,我做错了什么?

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”语句。

Solutions Collecting From Web of "Syncadapter onPerformSync在第一次被调用两次"

我也观察到了这种行为。

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

Clarificiation

然而,Zapek关于addPeriodic同步或请求同步是“立即”同步的观察并不完全正确。 两人都在排队。 此外,以下适用于addPeriodicSync():

这些定期同步将遵循“syncAutomatically”和“masterSyncAutomatically”设置。 尽pipe这些同步按照指定的频率进行安排,但是如果同步操作队列中的其他同步超前,则可能需要更长时间才能启动。 这意味着实际的开始时间可能会漂移。 ( 文档 )

关于你的问题

在运行同步适配器的培训中介绍了您遇到的情况:

addPeriodicSync()方法不会禁用setSyncAutomatically(),因此您可能会在相对较短的时间内执行多个同步操作。 此外,在调用addPeriodicSync();时,只允许less数同步适配器控制标志。 addPeriodicSync()的参考文档中描述了不允许的标志。 Android培训同步适配器

Google自己的解决scheme与您的解决scheme相似,甚至更低(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; } 

主张

我build议使用onPerformSync()中的SyncStats实际上将有关初始同步的一些信息返回给系统,以便更有效地进行调度。

 syncResult.stats.numEntries++; // For every dataset 

如果另一项任务已经安排好,这可能无济于事 – 调查

另外可以设置一个标志“isInitialOnPerformSync”(w。sharedPreferences),以使其他任务备份。

 syncResult.delayUntil = <time>; 

我个人并不喜欢在初始同步之后创build一个固定的不同步时间范围。

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

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

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

 /** * 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); } 

你是否要求除了addPeriodicSync()之外的同步?

首次添加帐户时,它应该自动同步。 因此,任何额外的同步请求都会导致双重同步。

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

希望有所帮助!

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

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

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

除了确保您的同步在客户端和服务器之间没有数据更改的情况下进行了优化之后,您无能为力。