2012-10-16 24 views
11

Chcę pokazać pasek postępu w pasku akcji, podczas gdy mój SyncAdapter aktywnie synchronizuje zawartość do iz sieci.Animacja działająca SyncAdapter - jak sprawdzić, czy SyncAdapter aktywnie synchronizuje

Próbowałem korzystać z SyncStatusObserver wraz z ContentProvider.addStatusChangeListener. Jednak nie mogę sprawdzić, czy SyncAdapter działa aktywnie. Mogę tylko sprawdzić:

  1. SyncAdapter czeka użyciu ContentResolver.isSyncPending
  2. SyncAdapter czeka lub aktywnie pracuje używając ContentResolver.isSyncActive

Flagi te można łączyć ze sobą: !isSyncPending && isSyncActive tak, że możliwe jest, aby sprawdzić, czy SyncAdapter aktywnie działa i nie ma żadnych oczekujących prac. Jednak w niektórych przypadkach SyncAdapter aktywnie działa ORAZ czeka na niego druga oczekująca prośba.

Wydaje się to takie proste, ale nie mogę znaleźć sposobu na obejście tego problemu. Posiadanie paska postępu widocznego, gdy narzędzie SyncAdapter nie jest uruchomione, daje użytkownikom wrażenie, że synchronizacja przebiega bardzo wolno. Nie pokazanie ProgressBar sprawia, że ​​użytkownik myśli, że nic się nie dzieje.

Powyższe rozwiązanie w kodzie pokazano poniżej. Rejestrujemy obserwatora w activity.onResume:

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

syncObserver jest tu definiowany jako:

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(); 
    } 
} 

Odpowiedz

16

końcu znalazłem rozwiązanie problemu. Chodzi o to, aby użyć metod ContentResolver, takich jak getCurrentSyncs() lub getCurrentSync(), w zależności od tego, która z nich jest dostępna. Poniższe metody sprawdzą, czy operacja synchronizacji działa obecnie dla konta i uprawnienia. Wymaga poziomu 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; 
} 

Activity następnie rejestruje aktualizacji w onResume() i wyrejestrowuje w onDestroy(). Ponadto, należy zaktualizować stan ręcznie w onResume(), aby nadążyć za bieżącym stanem.

Oto implementacja, która właśnie to robi. Podklasy powinny same określić

  • co konto w użyciu (wdrożenie getAccount())
  • co authoritity używać (pole CONTENT_AUTHORITY)
  • jak wyświetlić stan sychronization (wykonawczy updateState(boolean isSynchronizing))

mam nadzieję to pomoże komuś w przyszłości.

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); 
} 
+1

Dla Eclair, Froyo, pierniki, rozwiązania powyżej działają tylko wtedy, gdy urządzenie ma tylko jedno konto. Jeśli na urządzeniu istnieje więcej niż jedno konto, pierwsze konto będzie zsynchronizowane; reszta jest ignorowana. – ChuongPham