我有自己的ContentProvider
和SyncAdapter
,它们都工作得很好。
我将它们设置为与ContentResolver.setSyncAutomatically()
和此工作自动同步。我也可以测试与开发工具->同步测试仪的同步。
现在我想从我的应用程序中请求同步(如果我们还没有数据),并在同步完成时得到通知,这样我就可以更新界面(我在同步时会显示一个带有徽标的进度条)。我正在用ContentResolver.requestSync()
做这件事,但是我还没有找到一种在同步完成时得到通知的方法。
有人知道怎么做吗?谢谢。
发布于 2011-11-22 21:27:53
当同步是SYNC_OBSERVER_TYPE_ACTIVE
或SYNC_OBSERVER_TYPE_PENDING
时,使用addStatusChangeListener()
会给你回调。奇怪的是,没有结束的事件。
这是一个由菲利克斯推荐的workaround。他建议你应该抛弃ContentResolver
,转而使用广播。
发布于 2015-06-06 12:39:59
这里有一个完整的javadoc代码片段,供任何想要尝试解决方案的人使用,而不是去猜测如何将所有东西放在一起。它建立在Mark上面的答案之上。支持监控多个账号同步。
import android.accounts.Account;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/**
* Sync status observer that reports back via a callback interface when syncing has begun
* and finished.
*/
public static class MySyncStatusObserver implements SyncStatusObserver {
/**
* Defines the various sync states for an account.
*/
private enum SyncState {
/**
* Indicates a sync is pending.
*/
PENDING,
/**
* Indicates a sync is no longer pending but isn't active yet.
*/
PENDING_ACTIVE,
/**
* Indicates a sync is active.
*/
ACTIVE,
/**
* Indicates syncing is finished.
*/
FINISHED
}
/**
* Lifecycle events.
*/
public interface Callback {
/**
* Indicates syncing of calendars has begun.
*/
void onSyncsStarted();
/**
* Indicates syncing of calendars has finished.
*/
void onSyncsFinished();
}
/**
* The original list of accounts that are being synced.
*/
@NonNull private final List<Account> mAccounts;
/**
* Map of accounts and their current sync states.
*/
private final Map<Account, SyncState> mAccountSyncState =
Collections.synchronizedMap(new HashMap<Account, SyncState>());
/**
* The calendar authority we're listening for syncs on.
*/
@NonNull private final String mCalendarAuthority;
/**
* Callback implementation.
*/
@Nullable private final Callback mCallback;
/**
* {@code true} when a "sync started" callback has been called.
*
* <p>Keeps us from reporting this event more than once.</p>
*/
private boolean mSyncStartedReported;
/**
* Provider handle returned from
* {@link ContentResolver#addStatusChangeListener(int, SyncStatusObserver)} used to
* unregister for sync status changes.
*/
@Nullable private Object mProviderHandle;
/**
* Default constructor.
*
* @param accounts the accounts to monitor syncing for
* @param calendarAuthority the calendar authority for the syncs
* @param callback optional callback interface to receive events
*/
public MySyncStatusObserver(@NonNull final Account[] accounts,
@NonNull final String calendarAuthority, @Nullable final Callback callback) {
mAccounts = Lists.newArrayList(accounts);
mCalendarAuthority = calendarAuthority;
mCallback = callback;
}
/**
* Sets the provider handle to unregister for sync status changes with.
*/
public void setProviderHandle(@Nullable final Object providerHandle) {
mProviderHandle = providerHandle;
}
@Override
public void onStatusChanged(int which) {
for (final Account account : mAccounts) {
if (which == ContentResolver.SYNC_OBSERVER_TYPE_PENDING) {
if (ContentResolver.isSyncPending(account, mCalendarAuthority)) {
// There is now a pending sync.
mAccountSyncState.put(account, SyncState.PENDING);
} else {
// There is no longer a pending sync.
mAccountSyncState.put(account, SyncState.PENDING_ACTIVE);
}
} else if (which == ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE) {
if (ContentResolver.isSyncActive(account, mCalendarAuthority)) {
// There is now an active sync.
mAccountSyncState.put(account, SyncState.ACTIVE);
if (!mSyncStartedReported && mCallback != null) {
mCallback.onSyncsStarted();
mSyncStartedReported = true;
}
} else {
// There is no longer an active sync.
mAccountSyncState.put(account, SyncState.FINISHED);
}
}
}
// We haven't finished processing sync states for all accounts yet
if (mAccounts.size() != mAccountSyncState.size()) return;
// Check if any accounts are not finished syncing yet. If so bail
for (final SyncState syncState : mAccountSyncState.values()) {
if (syncState != SyncState.FINISHED) return;
}
// 1. Unregister for sync status changes
if (mProviderHandle != null) {
ContentResolver.removeStatusChangeListener(mProviderHandle);
}
// 2. Report back that all syncs are finished
if (mCallback != null) {
mCallback.onSyncsFinished();
}
}
}
具体实现如下:
public class MyActivity extends Activity implements MySyncStatusObserver.Callback {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.some_layout);
// Retrieve your accounts
final Account[] accounts = AccountManager.get(this).getAccountsByType("your_account_type");
// Register for sync status changes
final MySyncStatusObserver observer = new MySyncStatusObserver(accounts, "the sync authority", this);
final Object providerHandle = ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE |
ContentResolver.SYNC_OBSERVER_TYPE_PENDING, observer);
// Pass in the handle so the observer can unregister itself from events when finished.
// You could optionally save this handle at the Activity level but I prefer to
// encapsulate everything in the observer and let it handle everything
observer.setProviderHandle(providerHandle);
for (final Account account : accounts) {
// Request the sync
ContentResolver.requestSync(account, "the sync authority", null);
}
}
@Override
public void onSyncsStarted() {
// Show a refresh indicator if you need
}
@Override
public void onSyncsFinished() {
// Hide the refresh indicator if you need
}
}
发布于 2014-12-20 07:09:44
当同步完成时,addStatusChangeListener()会通知你,它只是以一种稍微拐弯抹角的方式来做:调用SyncStatusObserver.onStatusChanged()来通知你状态改变了。然后,您必须调用ContentResolver.isSyncPending()或ContentResolver.isSyncActive()来检查新状态。
...
ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_PENDING
| ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE,
new MySyncStatusObserver());
...
private class MySyncStatusObserver implements SyncStatusObserver {
@Override
public void onStatusChanged(int which) {
if (which == ContentResolver.SYNC_OBSERVER_TYPE_PENDING) {
// 'Pending' state changed.
if (ContentResolver.isSyncPending(mAccount, MY_AUTHORITY)) {
// There is now a pending sync.
} else {
// There is no longer a pending sync.
}
} else if (which == ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE) {
// 'Active' state changed.
if (ContentResolver.isSyncActive(mAccount, MY_AUTHORITY)) {
// There is now an active sync.
} else {
// There is no longer an active sync.
}
}
}
}
另请注意:在我的测试中,当我请求同步时,我的onStatusChanged()方法被调用了四次:
因此,即使活动同步即将开始,在pending和active之间似乎也有一个窗口,其中两者都设置为false。
https://stackoverflow.com/questions/8227429
复制相似问题