开发者

Has anyone implemented (or got more info) on Android SyncObserver

I am developing an app in Android that performs a background sync开发者_开发知识库 with a server (using SyncAdapter and authentication etc).

When the foreground app (with UI) is started, there maybe a background sync in progress, or optionally it may start one via a UI button.

I would like a way to "plug into" an on-going background sync (whether started by the system, or the periodic sync setting or the UI) and show it's progress in the foreground activity.

The ContentResolver documentation (http://developer.android.com/reference/android/content/ContentResolver.html) mentions a mysterious "SyncObserver" that has no link to javadoc and is not documented (that I can find).

There are some other pages around that mention it (http://www.chinaup.org/docs/migrating/m5-0.9/changes/android.content.ContentResolver.html) but I can't find out more about it.

Has anyone implemented this beast?

If not, does anyone have example code or recommendations on tracking the progress of a background sync in a foreground Activity?


Thanks for the answer.

Due to the async nature of the background sync your App (activity) could be started with a background sync already underway, which you detect with the status stored in a preference.

What I have done is to implement a SyncObserver class that implements the SyncStatusObserver interface and create/destroy on suspend/resume.

syncObserverHandle = ContentResolver.addStatusChangeListener( ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, new SyncObserver() );

This gets informed of any event related to sync (pending, started, etc) and I also check for status using

ContentResolver.isSyncActive();

The Android APIs for this are pretty basic, and you have to respect rules about what is done on the UI thread and what is not, but if anyone want to see my implementation just post a question and point me to it and I will answer with pleasure.


I had this same problem and ended up implementing it with a combination of 1) a broadcast from the SyncAdapter, and 2) using SharedPreferences to indicate status.

In the SyncAdapter, something like this this:

public static final String START_SYNC = "com.whatever.sync.start";
public static final String STOP_SYNC = "com.whatever.sync.stop";
public static final String SYNC_PROGRESS = "syncProgress";


public void onPerformSync(Account account, Bundle extras, String authority,
    ContentProviderClient provider, SyncResult syncResult) {

        // Add an integer to the shared settings to indicate the status
        SharedPreferences settings = mContext.getSharedPreferences(Constants.PREFS, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(SyncAdapter.SYNC_PROGRESS, 0);
        editor.commit();

        Intent intent = new Intent();
        intent.setAction(START_SYNC);
        mContext.sendBroadcast(intent);


        //... do some stuff, setting SYNC_PROGRESS to other values and
        // sending more broadcasts as the state changes

        // When we are done, remove the "in progress" setting and store some
        // other data
        editor.putString(SyncAdapter.LAST_UPDATED, new Date().toString());
        editor.remove(SyncAdapter.SYNC_PROGRESS);
        editor.commit();

        Intent stopIntent = new Intent();
        stopIntent.setAction(STOP_SYNC);
        mContext.sendBroadcast(stopIntent); 
      }

In the activity we do two things at resume 1) check the shared preference for whether a sync is currently in progress, 2) register to listen for broadcasts with a receiver.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// .. do some UI stuff

    mReceiver = new SyncReceiver(this);
}

@Override
public void onResume() {
    super.onResume();

    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(SyncAdapter.START_SYNC);
    intentFilter.addAction(SyncAdapter.STOP_SYNC);
    registerReceiver(mReceiver, intentFilter);  

    showProgress();
}

public void showProgress() {
    SharedPreferences settings = getSharedPreferences(Constants.PREFS, 0);
    if (settings.contains(SyncAdapter.SYNC_PROGRESS)) {
        // ... set the UI to show that a sync is in progress
    } else {
        // ... set the UI to show that a sync is NOT in progress
    }
}

private class SyncReceiver extends BroadcastReceiver {

    private MyActivity mActivity;

    public SyncReceiver(MyActivity activity) {
        mActivity = activity;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(SyncAdapter.START_SYNC)) {
            Log.i("@string/app_name", "Started sync");
            mActivity.showProgress();
        }
        else if (intent.getAction().equals(SyncAdapter.STOP_SYNC)) {
            Log.i("@string/app_name", "Started sync");
            mActivity.showProgress();
        }
    }
}

This seems to work for me. I must admit I have a feeling that there are some potential issues with this due to the asynchronous nature of the broadcasts. Any input on improving my approach would be appreciated!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜