Android SyncAdapter Callback

2019-04-06 21:25发布

I have implemented a SyncAdapter, AccountManager and private ContentProvider along the lines of the SimpleSyncAdapter sample project in the SDK. It is all working well.

Now I want to show a message to the user when new rows have been downloaded from the remote server that have a specific flag set. I need a callback from the SyncAdapter when a Sync has finished so I can do the query and display the message from an activity. I have seen a few questions on StackOverflow discussing this but none with a good answer.

How does one listen for progress from Android SyncAdapter? says that the SyncStatusObserver is useless. User mobibob suggests using a ResultReceiver to respond back to the UI from the sync thread.

How to know when sync is finished? suggests using an Intent in your SyncService.

How to signal sync-complete to the Android SyncManager? suggests using the SyncResult. The example code linked to by maxpower47 uses the SyncResult class to report exceptions but not to actually report if a sync was successfully completed.

I just don't know which is the best option and I have not seen any example projects where any of these solutions are used.

3条回答
唯我独甜
2楼-- · 2019-04-06 22:04

This is an old question but I did some research in the past days and there are not many exemples on syncAdapter handling network requests and notifying the UI.

First you should use Loaders with contentProvider to make your life easier. You don't need to register for content resolver anymore the Loader does it for you. So it means your UI gets notified for anything that goes into your content provider.

What if nothing changed ? everything was up to date or you had a network error.

  1. You can listen to the status of your syncAdapter as the Google I/O app does, search for mSyncStatusObserver in the BaseActivity
  2. I had a look at the default android email app and they use a Singleton with callBacks.
  3. You can BroadcastIntents or use an eventBus (square Otto for exemple) to notify your UI of any behaviour.

I like the last one better because it gives you more granularity on the events that happen in the syncAdapter.

查看更多
仙女界的扛把子
3楼-- · 2019-04-06 22:17

I know this is an old question, but I was asking the same thing myself. What I found out as a good solution, specially because I'm dealing with local data as you are, is to use the following method from ContentResolver:

registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)

This register an observer class that get callback when data identified by a given content URI changes. But that can only happens if your ContentProvider send the notification. So for example, if you want to get notified on the ContentObserver above for all updates done on your database through a ContentProvider, your ContentProvider should implement update similar to this:

@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
    // code goes here
    this.getContext().getContentResolver().notifyChange(uri, null);
    return 0;
}

Using notifyForDescendents when you do a registerContentObserver can be very useful.

查看更多
趁早两清
4楼-- · 2019-04-06 22:17

We ran into a similar situation and wrote a static Listener interface to the SyncAdapter. The listener is the activity and performs necessary actions when the data is available (update UI). This also works when the sync-adapter is called by the system during autosync where this listener would be null and the sync process would mind its own business.

class SyncAdapter extends AbstractThreadedSyncAdapter {

    protected static Listener uiListener = null;
    public interface Listener {
        public void onSync();
    }
    public static void setListener(Listener l) {
        uiListener = l;
    }
    public static void clearListener() {
        uiListener = null;
    }
    protected void broadcastSync() {
        if (uiListener != null)
            uiListener.onSync();
    }
    public void onPerformSync(Account account, Bundle extras, String authority,
                          ContentProviderClient provider, SyncResult syncResult) {

         // call broadcastSync();
    }

Then in the Activity, implement SyncAdapter.Listener interface.

查看更多
登录 后发表回答