我的应用有一个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());
}
我可以通过“设置”成功将帐户添加到“帐户管理器”,但我必须手动为“设置”中的帐户启用同步,即使在模拟器上启用了后台数据和自动同步设置。如果我手动启用同步,则同步执行正常,默认情况下不会启动。
答案 0 :(得分:30)
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
正如Blehi所述将启动给定帐户的自动同步,在全局设置下,启用“后台数据”和“自动同步”。
要防止背靠背同步(from jcwenger),请确保如果有任何方法
SyncAdapter.onPerformSync(...)
调用ContentResolver.notifyChange(...)
使用ContentResolver.notifyChange(uri, observer, false)
标记通知不触发同步调用(第三个参数为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)
答案 1 :(得分:13)
只是要强调,似乎addPeriodicSync() 需要 setSyncAutomatically(),即使文档说setSyncAutomatically()仅用于检测网络元数据。
请注意,如果时间不到一分钟,则会将时间段更正为> 60秒。
答案 2 :(得分:6)
默认情况下,您必须将帐户设置为可同步:
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
我使用上面两行并且它正常工作。
答案 3 :(得分:2)
最初使用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);