2011-07-08 23 views
28

Tôi đã triển khai bộ điều hợp đồng bộ hóa và tôi muốn nhận lại cuộc gọi khi hoàn thành hoạt động của mình. Tôi đã thử sử dụng ContentResolver.addStatusChangeListener, nhưng tôi chỉ nhận được cuộc gọi lại khi đồng bộ hóa đang chờ/đang hoạt động. Dưới đây là một số mã có liên quan từ hoạt động của tôi:Làm thế nào để biết khi nào đồng bộ kết thúc?

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

Tuy nhiên, if trong phương pháp onStatusChanged là không bao giờ hợp lệ. Tôi đã lấy ví dụ này từ JumpNote demo nơi nó hoạt động có thể vì nó cũng được gọi theo cách thủ công trong onResume(), vì vậy nó có thể không bao giờ được gọi là bởi hệ thống khi đồng bộ hóa kết thúc. Hoặc là nó, và tôi đang làm điều gì đó sai? Đây là những gì tôi nhận được trong 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 

Vì vậy, có vẻ như tôi thể dựa vào SYNC_OBSERVER_TYPE_ACTIVE (4) thay đổi trạng thái thứ hai để làm mới dữ liệu của tôi, nhưng điều đó dường thực sự xấu xí. Bất kỳ ý tưởng?

Trả lời

36

Một giải pháp mà tôi đã tìm thấy là bỏ hoàn toàn ContentResolver hoàn toàn và triển khai chương trình phát sóng của riêng tôi. Về cơ bản, thêm này trong sync adapter, ở phần cuối của onPerformSync:

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

Và điều này trong hoạt động:

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

Điều này dường như chỉ làm việc tốt, tuy nhiên tôi đã hy vọng để tìm thấy một cái gì đó trong SDK thông báo trực tiếp cho tôi khi đồng bộ hóa hoàn tất.

+1

+1 Tôi đã mất một giờ với 'ContentResolver.isSyncActive'. Tự làm nó thực sự dễ dàng hơn nhiều. – rds

+0

Khi bạn nói: '" thêm điều này trong dịch vụ đồng bộ hóa "' bạn có thực sự có nghĩa là bộ điều hợp đồng bộ hóa không? '" ... ở cuối "' làm cho tôi nghĩ rằng: khi đồng bộ hoàn thành vào cuối 'onPerformSync'. – HGPB

+2

Tôi không hiểu điều này, những gì sendBroadcast và SYNC_FINISHED? –

15

Lạ, nó có hiệu quả với tôi.

Trong Activity của tôi, tôi có:

@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

làm việc này cho tôi, mặc dù tôi phải thêm 2 quyền: GET_ACCOUNTS, READ_SYNC_STATS –

+0

'@Override public void onStatusChanged' >>" Phương thức không ghi đè phương thức từ siêu lớp của nó ". ?? – Eftekhari

+0

tuyệt vời. hoạt động như nét duyên dáng :) –

6

tôi đã làm việc trên một cái gì đó tương tự, và tôi có một Log.d hơn vào cuối của hàm onStatusChanged, và nó đã không được thực hiện!

Vì vậy, sau 15 phút gỡ lỗi và dùng thử về lỗi, tôi nhận thấy rằng tôi cần thêm quyền READ_SYNC_STATS, mặc dù tôi đã có quyền GET_ACCOUNTS. Vì vậy, hãy kiểm tra xem bạn có được sự cho phép phù hợp hay không, nó không phải là "nếu" không trở thành sự thật, nó sẽ luôn luôn được chấp nhận.

Các vấn đề liên quan