2012-10-16 71 views
11

我想在ActionBar中显示ProgressBar,同时我的SyncAdapter主动将内容同步到网络和从网络同步内容。SyncAdapter运行动画 - 如何知道SyncAdapter是否正在同步

我试过用SyncStatusObserverContentProvider.addStatusChangeListener一起使用。但是,我无法检查SyncAdapter是否正在运行。我只能检查:

  1. SyncAdapter使用ContentResolver.isSyncPending
  2. 未决SyncAdapter挂起或使用ContentResolver.isSyncActive

这些标志可以组合积极开展工作:!isSyncPending && isSyncActive,以便它可以检查一个SyncAdapter正在积极工作,并没有任何待定的工作。但是,在某些情况下,SyncAdapter正在积极工作,并有第二个未决请求等待它。

看起来很简单,但我找不到解决此问题的方法。在SyncAdapter未运行时显示ProgressBar会给用户留下同步非常慢的印象。不显示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(); 
    } 
} 

回答

16

我终于找到了解决问题的办法。这个想法是使用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()以赶上当前状态。

这是一个实现这一点的实现。子类应自行确定

  • 要使用哪个帐户(实施getAccount()
  • 使用什么authoritity(场CONTENT_AUTHORITY
  • 如何显示sychronization状态(实现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