【问题标题】:Android SyncAdapter Automatically Initialize SyncingAndroid SyncAdapter 自动初始化同步
【发布时间】:2015-06-23 19:45:53
【问题描述】:

我有一个SyncAdapter 用于我的应用程序,还有一个AccountManager 用于将我的应用程序帐户添加到 Android 帐户管理器。当我将帐户添加到客户经理时,我的代码如下所示:

Bundle data = new Bundle(5);
data.putString(_PEOPLE_ID, people_id);
data.putString(_FIRST_NAME, first_name);
data.putString(_LAST_NAME, last_name);
data.putString(_PLAN, plan);
data.putString(_BIRTHDAY, birthday);
Account account = new Account(username, _ACCOUNT_TYPE);
try {
    boolean created;
    created = _account_manager.addAccountExplicitly(account,
                                   _cryptography.encrypt(_SEED, password), data);
    response.accountCreated(created);
    _account_manager.setAuthToken(account, _TOKEN_TYPE, session_token);
    _model.updateActiveAccount(people_id, username, password);
    SharedPreferences.Editor settings = _settings.edit();
    settings.putString(_ACCOUNT_TYPE, account.name);
    settings.putString(_TOKEN_TYPE, session_token);
    settings.commit();
    // Tells the content provider that it can sync this account
    ContentResolver.setIsSyncable(account, AUTHORITY, 1);
    final Bundle extras = new Bundle(1);
    extras.putBoolean(SYNC_EXTRAS_INITIALIZE, true);
    ContentResolver.addPeriodicSync(account, AUTHORITY, extras, 900);
} catch (Exception e) {
    Ln.e(e.getCause());
}

我可以通过设置成功将帐户添加到帐户管理器,但我还必须在设置中手动为帐户启用同步,即使在模拟器上启用了后台数据和自动同步设置。如果我手动启用同步,则同步执行良好,只是默认情况下不启动。

【问题讨论】:

    标签: android accountmanager android-syncadapter


    【解决方案1】:
    ContentResolver.setIsSyncable(account, AUTHORITY, 1);
    ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
    

    正如Blehi 所说,将启动给定帐户的自动同步,给定全局设置,启用“后台数据”和“自动同步”。

    为防止背靠背同步 (from jcwenger),请确保如果 SyncAdapter.onPerformSync(...) 调用ContentResolver.notifyChange(...) 它使用ContentResolver.notifyChange(uri, observer, false) 标记notify 不触发同步调用(第三个参数是syncToNetwork)。

    如果您使用ContentProvider 为您执行插入/删除/更新SyncAdapter,则调用ContentResolver.notifyChange(...) 是有意义的,这样当应用程序可见时,用户可以从SyncAdapter 接收更新,这意味着您将有ContentProvider 拨打ContentResolver.notifyChange(...) 电话。为了让这个设置正常工作,我添加了(在dev guide 之后)CALLER_IS_SYNC_ADAPTER 查询参数到用于SyncAdapter 的每个 URI。将此方法添加到ContentProvider 以测试传入的URI

    /**
     * Determines if the given URI specifies that the request is coming from the sync adapter.
     * @param uri the given URI
     * @return true if the uri specifies that the request is coming from the sync adapter
     */
    private boolean callerIsSyncAdapter(Uri uri) {
        final String is_sync_adapter = uri.getQueryParameter(CALLER_IS_SYNC_ADAPTER);
        return is_sync_adapter != null && !is_sync_adapter.equals("0");
    }  
    

    那你就可以了

    getContext().getContentResolver().notifyChange(uri, observer, !callerIsSyncAdapter(uri));
    

    当您需要时发送更改通知。

    如果您想安排以一定频率定期执行同步(轮询服务器),请使用 ContentResolver.setSyncAutomatically(...) 调用添加。

    ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), frequency_in_seconds)
    

    【讨论】:

      【解决方案2】:

      强调一下,似乎 addPeriodicSync() 需要 setSyncAutomatically(),尽管文档说 setSyncAutomatically() 仅用于检测网络滴答声。 p>

      请注意,如果小于一分钟,周期将被修正为 >60 秒。

      【讨论】:

        【解决方案3】:

        您必须将帐户设置为默认可同步:

        ContentResolver.setIsSyncable(account, AUTHORITY, 1);
        ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
        

        我使用了上面的 2 行,它工作正常。

        【讨论】:

        • 添加 ContentResolver.setSyncAutomatically(account, AUTHORITY, true);是我需要的,但似乎它不承认定期同步。添加帐户后,它会不断重复同步。
        • 请尝试使用 new Bundle() 而不是 extras 来调用 ContentResolver.addPeriodicSync() 函数。
        • extras 是一个新的 Bundle(),我什至没有尝试设置任何标志(Bundle extras = new Bundle(); addPeriodicSync(account, AUTHORITY, extras, 900); )
        • 这已经很晚了,但是这里的AUTHORITY 是什么?
        • 我刚刚发现这是您在sync-adapter 标记中的android:contentAuthority 属性中的字符串。
        【解决方案4】:

        首先创建一个帐户并使用 AccountManager 检查同步支持。如果帐户支持同步,则调用 setIsSyncable() 和 setSyncAutomatically()。

        AccountManager accountManager = (AccountManager) this.getSystemService(ACCOUNT_SERVICE);
        if(accountManager.addAccountExplicitly(newAccount, null, null)){
                 ContentResolver.setIsSyncable(account, AUTHORITY, 1);
                 ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
        }
        

        然后您可以随时触发同步。它会触发。

        注意:setSyncAutomatically() 的 onPerformSync() 会先被调用,然后才会触发其他同步请求。 但是要进行强制同步,只需添加 2 个额外的标志。

        Bundle bundle= new Bundle();
            bundle.putBoolean(
                    ContentResolver.SYNC_EXTRAS_MANUAL, true);
            bundle.putBoolean(
                    ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
            ContentResolver.requestSync(account, AUTHORITY, bundle);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-17
          • 1970-01-01
          • 2017-07-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多