Jak sprawdzić, kiedy synchronizacja jest zakończona?

Zaimplementowałem adapter synchronizacji i chcę uzyskać oddzwonienie, gdy zakończy się Moja aktywność. Próbowałem użyć ContentResolver.addStatusChangeListener, ale dostaję tylko połączenia zwrotne, gdy synchronizacja jest oczekująca / aktywna. Oto odpowiedni kod z mojej aktywności:

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

Jednak if w metodzie onStatusChanged nigdy nie jest poprawna. Wziąłem ten przykład z jumpnote demo gdzie działa prawdopodobnie dlatego, że jest również wywoływany ręcznie w onResume(), więc prawdopodobnie nigdy wywołane przez system po zakończeniu synchronizacji. A może i robię coś nie tak? Oto co dostaję w 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

Wydaje się więc, że ja mógłbym polegać na drugiej SYNC_OBSERVER_TYPE_ACTIVE (4) zmianie statusu, aby odświeżyć moje dane, ale to wydaje się naprawdę brzydkie. Jakieś pomysły?

Author: Felix, 2011-07-08

3 answers

Jednym z rozwiązań, które znalazłem, jest całkowite porzucenie ContentResolver i wdrożenie własnej transmisji. Zasadniczo, dodaj to w adapterze synchronizacji, na końcu onPerformSync:

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

I to w działaniu:

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

To wydaje się działać dobrze, jednak miałem nadzieję znaleźć coś w SDK, które bezpośrednio powiadomi mnie po zakończeniu synchronizacji.

 42
Author: Felix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-10 15:16:06

Dziwne, u mnie działa.

W moim Activity mam:

  @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);
        }
      }
    });
  }
 17
Author: Macarse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-25 19:40:07

Pracowałem nad czymś podobnym i mam jeszcze jeden dziennik.d na końcu funkcji onStatusChanged i nie była wykonywana!

Tak więc po 15 minutach debugowania i próbnych prób, zdaję sobie sprawę, że muszę dodać uprawnienia READ_SYNC_STATS, Mam już jednak uprawnienia GET_ACCOUNTS. Więc, proszę sprawdzić, czy masz odpowiednie pozwolenie, to nie to, że "jeśli" nie staje się prawdą, to to, że się wycofuje cały czas.

 6
Author: Phuah Yee Keat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-27 06:48:27