5

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

当前台应用程序(带有 UI)启动时,可能正在进行后台同步,或者可以选择通过 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),但我找不到更多关于它的信息。

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

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

4

2 回答 2

5

感谢你的回答。

由于后台同步的异步性质,您的应用程序(活动)可以在后台同步已经开始的情况下启动,您可以使用存储在首选项中的状态来检测它。

我所做的是实现一个 SyncObserver 类,该类实现 SyncStatusObserver 接口并在挂起/恢复时创建/销毁。

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

这会通知与同步相关的任何事件(待处理、开始等),我还使用检查状态

ContentResolver.isSyncActive();

用于此的 Android API 非常基本,您必须遵守有关在 UI 线程上完成什么以及未完成什么的规则,但是如果有人想查看我的实现,只需发布​​一个问题并指出我,我会回答乐趣。

于 2011-06-06T14:41:43.697 回答
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();
        }
    }
}

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

于 2011-05-25T03:28:43.097 回答