I want to show a ProgressBar in the ActionBar while my SyncAdapter is actively synchronizing content to and from the web.
I have tried using the SyncStatusObserver together with ContentProvider.addStatusChangeListener. However, I cannot check if a SyncAdapter is actively running. I can only check:
- SyncAdapter is pending using ContentResolver.isSyncPending
- SyncAdapter is pending OR actively working using ContentResolver.isSyncActive
These flags can be combined: !isSyncPending && isSyncActive so that it is possible to check that a SyncAdapter is actively working and does not have any pending work. However, in some cases the SyncAdapter is actively working AND have a second pending request waiting for it.
It seems so simple but I can’t find a way around this problem. Having the ProgressBar visible when the SyncAdapter is not running is giving users the impression that the synchronization is very slow. Having it not show the ProgressBar makes the user think nothing is happening.
The above solution in code is shown below. We register the observer in the activity.onResume:
int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING | ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE;
syncHandle = ContentResolver.addStatusChangeListener(mask, syncObserver);
The syncObserver is here defined as:
syncObserver = new SyncStatusObserver()
{
@Override
public void onStatusChanged(int which)
{
Account account = getSomeAccount();
boolean syncActive = ContentResolver.isSyncActive(account, CONTENT_AUTHORITY);
boolean syncPending = ContentResolver.isSyncPending(account, CONTENT_AUTHORITY);
boolean isSynchronizing = syncActive && !syncPending;
updateRefreshButtonState();
}
}
I finally found a solution to the problem. The idea is to use the ContentResolver’s getCurrentSyncs() or getCurrentSync() methods, whichever is available. The methods below will check if a sync operation is currently working for an account and authority. It requires API level 8 (Froyo = Android 2.2).
An Activity then registers for updates in
onResume()and unregisters inonDestroy(). Also, one have to update state manually inonResume()to catch up with current status.Here is an implementation that does just that. Subclasses should themselves define
getAccount())CONTENT_AUTHORITY)updateState(boolean isSynchronizing))I hope it will help someone in the future.