有没有人在Android SyncObserver上实现(或获得更多信息)

时间:2011-03-31 19:28:04

标签: android user-interface synchronization sync android-syncadapter

我正在Android中开发一个应用程序,它与服务器执行后台同步(使用SyncAdapter和身份验证等)。

当启动前台应用程序(使用UI)时,可能正在进行后台同步,或者可选择通过UI按钮启动后台同步。

我想要一种方法来“插入”正在进行的后台同步(无论是由系统启动,还是定期同步设置或用户界面),并在前台活动中显示它的进度。

ContentResolver文档(http://developer.android.com/reference/android/content/ContentResolver.html)提到了一个神秘的“SyncObserver”,它没有与javadoc的链接,也没有记录(我可以找到)。

还有一些其他页面提到它(http://www.chinaup.org/docs/migrating/m5-0.9/changes/android.content.ContentResolver.html)但我找不到更多关于它

有没有人实施过这种野兽?

如果没有,是否有人有关于跟踪前台活动中后台同步进度的示例代码或建议?

2 个答案:

答案 0 :(得分:5)

感谢您的回答。

由于后台同步的异步特性,您的应用程序(活动)可以通过已经进行的后台同步启动,您可以使用首选项中存储的状态进行检测。

我所做的是实现一个SyncObserver类,它实现SyncStatusObserver接口并在suspend / resume上创建/销毁。

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

通知任何与同步相关的事件(待定,启动等),我也会使用

检查状态
ContentResolver.isSyncActive();

这方面的Android API非常基础,你必须尊重关于在UI线程上做了什么以及什么不做的规则,但是如果有人想看到我的实现只是发布一个问题并指出我和它我会高兴地回答。

答案 1 :(得分:3)

我遇到了同样的问题,最后结合使用1)来自SyncAdapter的广播,以及2)使用SharedPreferences来指示状态。

在SyncAdapter中,类似这样:

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); 
      }

在活动中,我们在恢复时做两件事1)检查共享偏好是否正在进行同步,2)注册以监听接收器的广播。

@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();
        }
    }
}

这似乎对我有用。我必须承认,由于广播的异步特性,我觉得这有一些潜在的问题。关于改进我的方法的任何意见将不胜感激!