2012-10-16 1 views
11

SyncAdapter가 웹과 콘텐츠를 적극적으로 동기화하는 동안 ActionBar에 ProgressBar를 표시하려고합니다.SyncAdapter running animation - SyncAdapter가 활발하게 동기화되는지 확인하는 방법

ContentProvider.addStatusChangeListener과 함께 SyncStatusObserver을 사용해 보았습니다. 그러나 SyncAdapter가 실제로 실행 중인지 확인할 수 없습니다. 난 단지 확인할 수 있습니다

  1. SyncAdapter는 ContentResolver.isSyncPending
  2. 를 사용하여 보류중인 SyncAdapter이 보류 또는 적극적으로 결합 될 수있다 ContentResolver.isSyncActive

이 플래그를 사용하여 작업하십시오 SyncAdapter 확인하기 때문에 가능하다는 것을 !isSyncPending && isSyncActive을 적극적으로 작업 중이며 대기중인 작업이 없습니다. 그러나 경우에 따라 SyncAdapter가 실제로 작동하고 대기중인 두 번째 보류중인 요청이 있습니다.

너무 단순 해 보이지만이 문제를 해결할 방법을 찾을 수 없습니다. SyncAdapter가 실행되고 있지 않을 때 ProgressBar를 표시하면 사용자에게 동기화가 매우 느립니다. ProgressBar를 표시하지 않으면 사용자가 아무 것도 일어나지 않는다고 생각하게됩니다.

위의 코드 코드는 다음과 같습니다. 우리는 activity.onResume에 관찰자를 등록 : 드디어 문제에 대한 해결책을 발견

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

답변

16

:로

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

syncObserver가 정의된다. ContentResolver의 getCurrentSyncs() 또는 getCurrentSync() 메서드 중 사용할 수있는 메서드를 사용하는 것이 좋습니다. 아래의 메소드는 동기화 작업이 현재 계정과 권한에 대해 작동하는지 확인합니다. 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; 
} 

활동은 onDestroy()에서 onResume()에서 업데이트 및 등록 취소에 대한 등록합니다. 또한 현재 상태를 따라 잡기 위해 onResume()에서 상태를 수동으로 업데이트해야합니다.

여기에 바로 그런 구현이 있습니다. 서브 클래스 자체는 어떤 계정

  • 은 무엇 authoritity (현장 CONTENT_AUTHORITY)
  • 유지해, 동기 상태를 표시하는 방법을
  • 사용 (getAccount() 구현)를 사용하여 정의해야합니다 (구현을 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); 
} 
+1

Eclair, Froyo, Gingerbread의 경우 위의 해결 방법은 기기에 계정이 하나 뿐인 경우에만 사용할 수 있습니다. 기기에 둘 이상의 계정이있는 경우 첫 번째 계정은 동기화 만됩니다. 나머지는 무시됩니다. – ChuongPham