Android SyncAdapter自动初始化同步

我有一个适用于我的应用程序的SyncAdapter ,以及一个AccountManager可以将我的应用程序帐户添加到Android帐户pipe理器。 我的帐户添加到帐户pipe理器时的代码如下所示:

 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()); } 

我可以通过设置成功将帐户添加到帐户pipe理器,但即使在模拟器上启用了背景数据和同步自动设置,我也必须在“设置”中手动启用帐户同步。 如果我手动启用同步,那么同步执行正常,它只是默认情况下不启动。

Solutions Collecting From Web of "Android SyncAdapter自动初始化同步"

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

由于Blehi表示会启动给定帐户的自动同步,因为在全局设置下,“背景数据”和“自动同步”被启用。

要防止背靠背同步( 从jcwenger ),请确保SyncAdapter.onPerformSync(...)中的任何方法调用ContentResolver.notifyChange(...)时使用ContentResolver.notifyChange(uri, observer, false)标记通知不触发同步调用(第三个参数是syncToNetwork )。

如果使用ContentProviderSyncAdapter执行插入/删除/更新,则调用ContentResolver.notifyChange(...)是有意义的,以便在应用程序可见时用户可以从SyncAdapter接收更新,这意味着您将有ContentProvider进行ContentResolver.notifyChange(...)调用。 为了使这个设置起作用,我已经将(根据开发指南 ) CALLER_IS_SYNC_ADAPTER查询参数添加到用于SyncAdapter每个URI。 将此方法添加到ContentProvider以testing传入的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) 

为了强调一下,即使文档说setSyncAutomatically()只是用来检测networking问题,addPeriodicSync()似乎也需要 setSyncAutomatically()。

请注意,如果不到一分钟,这段时间将被修正为> 60s。

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

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

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

最初创build一个帐户,并使用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);