2011-07-08 39 views
28

我已經實現了一個同步適配器,並且我想在我的活動中完成回調。我嘗試過使用ContentResolver.addStatusChangeListener,但我只在同步處於待處理/活動狀態時纔會收到回調。下面是我的一些活動相關的代碼:如何知道同步完成的時間?

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

然而,在onStatusChanged方法if永遠無效。我從JumpNote demo中得到了這個例子,它的工作原理可能是因爲它也在onResume()中手動調用,所以當同步完成時,系統可能永遠不會調用。或者是,我做錯了什麼?下面是我在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 

所以,看來我依靠第二SYNC_OBSERVER_TYPE_ACTIVE(4)狀態改變刷新我的數據,但似乎真的。有任何想法嗎?

回答

36

我發現的一個解決方案是徹底拋棄ContentResolver,並實現我自己的廣播。在活動

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

這:基本上,在同步適配器添加此,在onPerformSync年底

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

這似乎工作得很好,但我希望能找到的東西在在同步完成時直接通知我的SDK。

+1

+1我用'ContentResolver.isSyncActive'失去了一個小時。自己做這件事實際上要容易得多。 – rds

+0

當你說:'「在同步服務中添加」'你實際上是否指同步適配器? '「......在最後」'讓我想到:一旦同步在'onPerformSync'結束時完成。 – HGPB

+2

我不明白,sendBroadcast和SYNC_FINISHED是什麼? –

15

奇怪的是,它確實對我有用。

在我Activity我:

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

這對我有效,但我必須添加2個權限:GET_ACCOUNTS,READ_SYNC_STATS –

+0

'@Override public void onStatusChanged' >>「方法不會覆蓋超類的方法」。 ?? – Eftekhari

+0

真棒。作品像魅力:) –

6

我在做類似的東西,我有一個更Log.d在onStatusChanged功能的結束,它沒有執行!

因此經過15分鐘的錯誤調試和試用後,我意識到我需要添加READ_SYNC_STATS權限,但我已擁有GET_ACCOUNTS權限。因此,請檢查您是否獲得了正確的許可,而不是「如果」不成立,而且它始終保留。

相關問題