I have implemented a sync adapter and I want to get a callback when it finishes in my activity. I have tried using ContentResolver.addStatusChangeListener
, but I am only getting callbacks when the sync is pending / act开发者_StackOverflow社区ive. Here's some relevant code from my activity:
@Override
protected void onResume() {
super.onResume();
final int mask = ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE | ContentResolver.SYNC_OBSERVER_TYPE_PENDING;
syncObserverHandle = ContentResolver.addStatusChangeListener(mask, syncStatusObserver);
}
@Override
protected void onPause() {
super.onPause();
if (syncObserverHandle != null) {
ContentResolver.removeStatusChangeListener(syncObserverHandle);
syncObserverHandle = null;
}
}
private SyncStatusObserver syncStatusObserver = new SyncStatusObserver() {
@Override
public void onStatusChanged(int which) {
AccountManager am = AccountManager.get(TodosActivity.this);
Account a = am.getAccountsByType(Const.ACCOUNT_TYPE)[0];
Log.d(Const.TAG, "Sync status changed: " + which);
if (!ContentResolver.isSyncActive(a, DataProvider.AUTHORITY) &&
!ContentResolver.isSyncPending(a, DataProvider.AUTHORITY)) {
Log.d(Const.TAG, "Sync finished, should refresh nao!!");
}
}
};
However, the if
in the onStatusChanged
method is never valid. I have taken this example from the JumpNote demo where it works probably because it is also called manually in onResume()
, so it's probably never called by the system when the sync is finished. Or is it, and I'm doing something wrong? Here's what I get in logcat:
D/MYAPP (10903): Sync status changed: 2
D/MYAPP (10903): Sync status changed: 2
D/MYAPP (10903): Sync status changed: 4
D/MYAPP (10981): --> DataSyncAdapter.onPerformSync()
D/MYAPP (10981): <-- DataSyncAdapter.onPerformSync()
D/MYAPP (10903): Sync status changed: 4
So, it seems that I could rely on the second SYNC_OBSERVER_TYPE_ACTIVE
(4) status change to refresh my data, but that seems really ugly. Any ideas?
One solution that I have found is to ditch the ContentResolver
completely, and implement my own broadcast. Basically, add this in the sync adapter, at the end of onPerformSync
:
Intent i = new Intent(SYNC_FINISHED);
sendBroadcast(i);
And this in the activity:
@Override
protected void onResume() {
super.onResume();
registerReceiver(syncFinishedReceiver, new IntentFilter(DataSyncService.SYNC_FINISHED));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(syncFinishedReceiver);
}
private BroadcastReceiver syncFinishedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(Const.TAG, "Sync finished, should refresh nao!!");
}
};
This seems to work just fine, however I was hoping to find something in the SDK that directly notify me when a sync is finished.
Strange, it does work for me.
In my Activity
I have:
@Override
protected void onPause() {
super.onPause();
ContentResolver.removeStatusChangeListener(mContentProviderHandle);
}
@Override
protected void onResume() {
super.onResume();
mContentProviderHandle = ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, this);
}
@Override
public void onStatusChanged(int which) {
AccountManager accountManager = AccountManager.get(this);
Account[] accounts = accountManager
.getAccountsByType(AuthenticatorActivity.PARAM_ACCOUNT_TYPE);
if (accounts.length <= 0) {
return;
}
updateRefresh(ContentResolver.isSyncActive(accounts[0],
MyContentProvider.AUTHORITY));
}
// Since onStatusChanged() is not called from the main thread
// I need to update the ui in the ui-thread.
private void updateRefresh(final boolean isSyncing) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (isSyncing) {
mRefreshMenu.setActionView(R.layout.menu_item_refresh);
} else {
mRefreshMenu.setActionView(null);
}
}
});
}
I was working on something similar, and I have one more Log.d at the end of the onStatusChanged function, and it wasn't executing!
So after 15 minutes of debugging and trial on error, I realize that I need to add the READ_SYNC_STATS permission, I already have the GET_ACCOUNTS permission though. So, please check that you get the right permission, its not that the "if" doesn't becomes true, its that it bails all the time.
精彩评论