Как узнать, когда синхронизация закончена? - PullRequest
31 голосов
/ 08 июля 2011

Я реализовал адаптер синхронизации и хочу получить обратный вызов, когда он завершится в моей деятельности. Я попытался использовать ContentResolver.addStatusChangeListener, но я получаю обратные вызовы только тогда, когда синхронизация ожидает / активна. Вот некоторый соответствующий код из моей деятельности:

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

Однако if в методе onStatusChanged недопустим. Я взял этот пример из демонстрации JumpNote , где он работает, вероятно, потому что он также вызывается вручную в onResume(), поэтому система, вероятно, никогда не вызовет системой , когда синхронизация завершится. Или это так, и я что-то не так делаю? Вот что я получаю в 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

Итак, похоже, что я мог бы полагаться на второе SYNC_OBSERVER_TYPE_ACTIVE (4) изменение статуса, чтобы обновить свои данные, но это кажется действительно уродливым. Есть идеи?

Ответы [ 3 ]

41 голосов
/ 08 июля 2011

Одно решение, которое я нашел, - полностью отказаться от ContentResolver и реализовать собственную трансляцию.В основном, добавьте это в адаптер синхронизации в конце onPerformSync:

Intent i = new Intent(SYNC_FINISHED);
sendBroadcast(i);

И это в упражнении:

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

Кажется, это работает очень хорошо, однаконадеялся найти в SDK что-то, что напрямую сообщит мне о завершении синхронизации.

17 голосов
/ 25 июля 2012

Странно, у меня все работает.

По моему Activity У меня есть:

  @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);
        }
      }
    });
  }
6 голосов
/ 29 декабря 2012

Я работал над чем-то похожим, и у меня есть еще один Log.d в конце функции onStatusChanged, но он не выполнялся!

Таким образом, после 15 минут отладки и пробного использования, я понимаю, что мне нужно добавить разрешение READ_SYNC_STATS, хотя у меня уже есть разрешение GET_ACCOUNTS.Поэтому, пожалуйста, проверьте, что вы получите правильное разрешение, это не значит, что «если» не становится правдой, это то, что оно все время освобождается от ответственности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...