Синхронизированная анимация SyncAdapter – как узнать, активно ли SyncAdapter синхронизация

Я хочу показать ProgressBar в ActionBar, в то время как мой SyncAdapter активно синхронизирует контент с Интернетом и из Интернета.

Я попытался использовать SyncStatusObserver вместе с ContentProvider.addStatusChangeListener . Однако я не могу проверить, активно ли активный SyncAdapter. Я могу только проверить:

  1. SyncAdapter ожидает использования ContentResolver.isSyncPending
  2. SyncAdapter ожидает или активно работает с использованием ContentResolver.isSyncActive

Эти флаги можно комбинировать !isSyncPending && isSyncActive чтобы можно было проверить, что SyncAdapter активно работает и не имеет ожидающей работы. Однако в некоторых случаях SyncAdapter активно работает и ожидает второго ожидающего запроса.

Это кажется таким простым, но я не могу найти пути решения этой проблемы. Наличие ProgressBar, видимого, когда SyncAdapter не работает, дает пользователям впечатление, что синхронизация выполняется очень медленно. Если он не показывает, ProgressBar заставляет пользователя думать, что ничего не происходит.

Вышеприведенное решение в коде показано ниже. Мы регистрируем наблюдателя в activity.onResume:

  int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING | ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE; syncHandle = ContentResolver.addStatusChangeListener(mask, syncObserver); 

Здесь SyncObserver определяется как:

 syncObserver = new SyncStatusObserver() { @Override public void onStatusChanged(int which) { Account account = getSomeAccount(); boolean syncActive = ContentResolver.isSyncActive(account, CONTENT_AUTHORITY); boolean syncPending = ContentResolver.isSyncPending(account, CONTENT_AUTHORITY); boolean isSynchronizing = syncActive && !syncPending; updateRefreshButtonState(); } } 

Solutions Collecting From Web of "Синхронизированная анимация SyncAdapter – как узнать, активно ли SyncAdapter синхронизация"

Я, наконец, нашел решение проблемы. Идея заключается в использовании методов getCurrentSyncs () или GetCurrentSync () ContentResolver , в зависимости от того, что доступно. Нижеприведенные методы будут проверять, работает ли в настоящее время операция синхронизации для учетной записи и полномочий. Для этого требуется уровень API 8 (Froyo = Android 2.2).

 private static boolean isSyncActive(Account account, String authority) { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { return isSyncActiveHoneycomb(account, authority); } else { SyncInfo currentSync = ContentResolver.getCurrentSync(); return currentSync != null && currentSync.account.equals(account) && currentSync.authority.equals(authority); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private static boolean isSyncActiveHoneycomb(Account account, String authority) { for(SyncInfo syncInfo : ContentResolver.getCurrentSyncs()) { if(syncInfo.account.equals(account) && syncInfo.authority.equals(authority)) { return true; } } return false; } 

Затем активность регистрируется для обновлений в onResume() и onDestroy() в onDestroy() . Кроме того, нужно обновить состояние вручную в onResume() чтобы догнать текущий статус.

Вот реализация, которая делает именно это. Подклассы должны сами определять

  • getAccount() учетную запись использовать (внедрение getAccount() )
  • Какое полномочие использовать (поле CONTENT_AUTHORITY )
  • Как отображать состояние синхронизации (внедрение updateState(boolean isSynchronizing) )

Надеюсь, это поможет кому-то в будущем.

 import android.accounts.Account; import android.annotation.TargetApi; import android.app.Activity; import android.content.ContentResolver; import android.content.SyncInfo; import android.content.SyncStatusObserver; import android.os.Build; import android.os.Bundle; public abstract class SyncActivity extends Activity { private static final String CONTENT_AUTHORITY = "com.example.authority"; private Object syncHandle; private SyncStatusObserver observer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); observer = new SyncStatusObserver() { @Override public void onStatusChanged(int which) { runOnUiThread(new Runnable() { @Override public void run() { Account account = getAccount(); boolean isSynchronizing = isSyncActive(account, CONTENT_AUTHORITY); updateState(isSynchronizing); } }); } }; } @Override protected void onResume() { super.onResume(); // Refresh synchronization status observer.onStatusChanged(0); // Watch for synchronization status changes final int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING | ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE; syncHandle = ContentResolver.addStatusChangeListener(mask, observer); } @Override protected void onPause() { super.onPause(); // Remove our synchronization listener if registered if (syncHandle != null) { ContentResolver.removeStatusChangeListener(syncHandle); syncHandle = null; } } private static boolean isSyncActive(Account account, String authority) { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { return isSyncActiveHoneycomb(account, authority); } else { SyncInfo currentSync = ContentResolver.getCurrentSync(); return currentSync != null && currentSync.account.equals(account) && currentSync.authority.equals(authority); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private static boolean isSyncActiveHoneycomb(Account account, String authority) { for(SyncInfo syncInfo : ContentResolver.getCurrentSyncs()) { if(syncInfo.account.equals(account) && syncInfo.authority.equals(authority)) { return true; } } return false; } protected abstract Account getAccount(); protected abstract void updateState(boolean isSynchronizing); }