Подтвердить что ты не робот

Как узнать, когда синхронизация завершена?

Я реализовал адаптер синхронизации, и я хочу получить обратный вызов, когда он закончит в моей деятельности. Я пробовал использовать 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 demo, где он работает, вероятно, потому, что он также называется вручную в 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), чтобы обновить мои данные, но это кажется действительно уродливым. Любые идеи?

4b9b3361

Ответ 1

Одно из решений, которое я нашел, - полностью протолкнуть 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, который напрямую уведомляет меня о завершении синхронизации.

Ответ 2

Странно, это работает для меня.

В моем 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);
        }
      }
    });
  }

Ответ 3

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

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