9

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

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

    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”语句定期同步。

4

3 回答 3

4

我也观察到了这种行为。

正确的是, 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);
}
于 2014-01-14T10:14:42.093 回答
2

除了 addPeriodicSync() 之外,您还请求同步吗?

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

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

希望有帮助!

于 2012-08-28T18:46:24.993 回答
1

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

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

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

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

于 2013-03-26T09:58:35.383 回答