Android SyncAdapter Automatically Initialize Syncing

痴心易碎 提交于 2019-11-29 21:53:56
Dandre Allison
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);

As Blehi said will initiate the automatic syncing of the given account, given the global Settings, "Background data" and "Auto-sync" are enabled.

To prevent the back-to-back syncing (from jcwenger) make sure that if any method in the SyncAdapter.onPerformSync(...) calls ContentResolver.notifyChange(...) it uses ContentResolver.notifyChange(uri, observer, false) to flag the notify not to trigger a sync call (the third parameter is syncToNetwork).

If you're using the ContentProvider to perform the inserts/deletes/updates for you SyncAdapter it makes sense to call ContentResolver.notifyChange(...) so that while the app is visible the user can receive updates from the SyncAdapter, which means you will have the ContentProvider making ContentResolver.notifyChange(...) calls. To get this set up to work, I've added (following the dev guide) CALLER_IS_SYNC_ADAPTER query parameter to every URI that is used for the SyncAdapter. Add this method to the ContentProvider to test the incoming URIs

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

then you can do

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

whenever you need send a change notification.

And if you want to schedule the sync to be executed periodically at a frequency (polling the server) add this with the ContentResolver.setSyncAutomatically(...) call.

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

Just to emphasise, it seems that addPeriodicSync() needs setSyncAutomatically(), even though the documentation says that setSyncAutomatically() is only for detecting network tickles.

Note that the period will be corrected to >60s if it's less than a minute.

Blehi

You have to set the account to be syncable by default:

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

I use the above 2 lines and it is working properly.

Initially create an account and check the sync support for the same using AccountManager. If the account supports sync then call setIsSyncable() and setSyncAutomatically().

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

Then you can trigger sync anytime. It will trigger.

Note: onPerformSync() of setSyncAutomatically() will be called first then only other sync request will be triggered. But to make force sync just add 2 extra flags.

Bundle bundle= new Bundle();
    bundle.putBoolean(
            ContentResolver.SYNC_EXTRAS_MANUAL, true);
    bundle.putBoolean(
            ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
    ContentResolver.requestSync(account, AUTHORITY, bundle);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!