Android SyncAdapter始终处于挂起状态

Android SyncAdapter始终处于挂起状态,android,synchronization,android-contentresolver,android-syncadapter,swiperefreshlayout,Android,Synchronization,Android Contentresolver,Android Syncadapter,Swiperefreshlayout,我目前正在开发一款android应用程序,它依靠SyncAdapter从服务器刷新内容。我基本上遵循了这些指示: 直到最近,这种方法才发挥了完美的作用。我知道这听起来很愚蠢,但我真的不知道我是怎么搞砸的:( 设置 我有一个ContentProvider,因此有一个SyncAdapter和一个帐户用于我要同步的所有项目。我使用整数标志确定必须同步的项目: public static final int EVENTS = 0x1; public static final int NEWS = 0x

我目前正在开发一款android应用程序,它依靠
SyncAdapter
从服务器刷新内容。我基本上遵循了这些指示:

直到最近,这种方法才发挥了完美的作用。我知道这听起来很愚蠢,但我真的不知道我是怎么搞砸的:(


设置 我有一个
ContentProvider
,因此有一个
SyncAdapter
和一个帐户用于我要同步的所有项目。我使用整数标志确定必须同步的项目:

public static final int EVENTS = 0x1;
public static final int NEWS = 0x2;
public static final int SUBSTITUTIONS = 0x4;
public static final int TEACHERS = 0x8;
public static final int ALL = 0xF;
因此,在我的
onPerformSync
中,我有如下内容:

ArrayList<ContentProviderOperation> batchList = new ArrayList<>();

int which = extras.getInt(SYNC.ARG, SYNC.ALL);
if((which & SYNC.NEWS) == SYNC.NEWS) { syncNews(provider, batchList, syncResult, 0, 1); }
if((which & SYNC.EVENTS) == SYNC.EVENTS) { syncEvents(provider, batchList, syncResult); }
if((which & SYNC.TEACHERS) == SYNC.TEACHERS) { syncTeachers(provider, batchList, syncResult); }
if((which & SYNC.SUBSTITUTIONS) == SYNC.SUBSTITUTIONS) { syncSubstitutions(provider, batchList, syncResult); }

Log.i(TAG, "Merge solution ready. Applying batch update to database...");
provider.applyBatch(batchList);
我还想监视同步状态,因此我在片段的
onResume
/
onPause
中注册/取消注册一个
SyncStatusObserver

private final SyncStatusObserver syncStatusObserver = new SyncStatusObserver() {
    @Override
    public void onStatusChanged(int which) {
        Account account = AuthenticatorService.getAccount(SyncUtils.ACCOUNT_TYPE);
        boolean syncActive = ContentResolver.isSyncActive(account, DataProvider.AUTHORITY);
        boolean syncPending = ContentResolver.isSyncPending(account, DataProvider.AUTHORITY);

        final boolean refresh = syncActive || syncPending;
        Log.d(TAG, "Status change detected. Active: %b, pending: %b, refreshing: %b", syncActive, syncPending, refresh);

        swipeRefreshLayout.post(new Runnable() {
            @Override
            public void run() {
               swipeRefreshLayout.setRefreshing(refresh);
            }
        });
    }
};

问题 每当我启动应用程序时,
刷新布局
指示同步处于活动状态。我记录了几乎所有内容,发现同步处于挂起状态。每当我尝试强制刷新时,同步将

  • 变得活跃起来,做所有的事情,然后回到挂起或关闭状态
  • 简单地说,不要变得活跃,永远处于挂起模式
下面是一个日志示例:

D/HomeFragment﹕ Status change detected. Active: false, pending: true, refreshing: true
D/HomeFragment﹕ Status change detected. Active: false, pending: true, refreshing: true
D/HomeFragment﹕ Status change detected. Active: true, pending: true, refreshing: true
D/HomeFragment﹕ Status change detected. Active: false, pending: true, refreshing: true
如您所见,它将永远不会是
活动:false,挂起:false
来指示同步完成。这真的让我很恼火


还有代码吗 我在我的应用程序类中进行存根帐户的初始设置(以及定期同步):

public static void createSyncAccount(Context context) {
    boolean newAccount = false;
    boolean setupComplete = PreferenceManager
               .getDefaultSharedPreferences(context).getBoolean(PREF_SETUP_COMPLETE, false);

    // Create account, if it's missing. (Either first run, or user has deleted account.)
    Account account = AuthenticatorService.getAccount(ACCOUNT_TYPE);
    AccountManager accountManager =
                (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);

    if (accountManager.addAccountExplicitly(account, null, null)) {    
        // Inform the system that this account supports sync
        ContentResolver.setIsSyncable(account, DataProvider.AUTHORITY, 1);

        // Inform the system that this account is eligible for auto sync when the network is up
        ContentResolver.setSyncAutomatically(account, DataProvider.AUTHORITY, true);

        // Recommend a schedule for automatic synchronization. The system may modify this based
        // on other scheduled syncs and network utilization.
        requestPeriodic(account, SYNC.EVENTS, 172800);
        requestPeriodic(account, SYNC.NEWS, 604800);
        requestPeriodic(account, SYNC.SUBSTITUTIONS, 1800);
        requestPeriodic(account, SYNC.TEACHERS, 2419200);

        newAccount = true;
    }

    // Schedule an initial sync if we detect problems with either our account or our local
    // data has been deleted. (Note that it's possible to clear app data WITHOUT affecting
    // the account list, so wee need to check both.)
    if (newAccount || !setupComplete) {
        triggerRefresh(SYNC.ALL);
        PreferenceManager.getDefaultSharedPreferences(context).edit()
                    .putBoolean(PREF_SETUP_COMPLETE, true).commit();
    }
}
其中
requestPeriodic()
如下所示:

public static void requestPeriodic(Account account, int which, long seconds) {
    Bundle options = new Bundle();
    options.putInt(SYNC.ARG, which);

    ContentResolver.addPeriodicSync(account,
        DataProvider.AUTHORITY, options, seconds);
}
我的
triggerRefresh()
看起来像:

public static void triggerRefresh(int which) {
    Log.d(TAG, "Force refresh triggered for id: %d", which);

    Bundle options = new Bundle();
    options.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
    options.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
    options.putInt(SYNC.ARG, which);

    ContentResolver.requestSync(
            AuthenticatorService.getAccount(ACCOUNT_TYPE),
            DataProvider.AUTHORITY,
            options
    );
}
有没有人遇到过类似的问题,或者知道我做错了什么


更新1 我尝试更改使用
SyncStatusObserver
的方式。现在,我从
哪个
标志参数获取信息,如下所示:

private final SyncStatusObserver syncStatusObserver = new SyncStatusObserver() {
    @Override
    public void onStatusChanged(int which) {
        boolean syncActive = (which & ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE) == ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE;
        boolean syncPending = (which & ContentResolver.SYNC_OBSERVER_TYPE_PENDING) == ContentResolver.SYNC_OBSERVER_TYPE_PENDING;

        boolean refreshing = syncActive || syncPending;
        // update UI...
    }
};

当我这样做时,
pending
状态似乎是正确的,因此它会在适配器开始同步过程时返回
false
但是现在适配器一直处于活动状态,我的
布尔刷新像往常一样有相同的错误结果。:/

我的系统也遇到了类似的问题syncAdapter…我所做的是关闭自动同步…由于您明确触发了同步过程,您可以删除现有帐户将内容解析程序的setSyncAutomatically设置为false,然后再次运行适配器

ContentResolver.setSyncAutomatically(account, CONTENT_AUTHORITY, false);
我还发布了SyncAdapter的状态更改回调,其中记录了同步过程的状态

private SyncStatusObserver mSyncStatusObserver = new SyncStatusObserver() {

    @Override
    public void onStatusChanged(int which) {
        Log.e("TAG", "Sync Status " + which);
         runOnUiThread(new Runnable() {
            @Override
            public void run() {

                Account account = GenericAccountService.getAccount(SyncUtils.ACCOUNT_TYPE);
                if (account == null) {
                    // GetAccount() returned an invalid value. This shouldn't happen, but
                    // we'll set the status to "not refreshing".
                    //setRefreshActionButtonState(false);
                    return;
                }

                // Test the ContentResolver to see if the sync adapter is active or pending.
                // Set the state of the refresh button accordingly.
                boolean syncActive = ContentResolver.isSyncActive(
                        account, PlacesProvider.PROVIDER_NAME);
                boolean syncPending = ContentResolver.isSyncPending(
                        account, PlacesProvider.PROVIDER_NAME);


                Log.e("TAG", "SYNC PENDING " + syncPending);
                if (!syncActive && !syncPending){
                    Log.e("TAG", "Sync is finished");
                    //if (syncProgressDialog != null) syncProgressDialog.dismiss();
                   // progressDialog.hide();
                }
                else {

                }
                //setRefreshActionButtonState(syncActive || syncPending);
            }
        });
    }
};
在onResume中,我注册了SyncStatusObserver

  mSyncStatusObserver.onStatusChanged(0);

    final int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING |
            ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE;
    mSyncObserverHandle = ContentResolver.addStatusChangeListener(mask, mSyncStatusObserver);
在onStop中,我删除了侦听器

  if (mSyncObserverHandle != null) {
        ContentResolver.removeStatusChangeListener(mSyncObserverHandle);
        mSyncObserverHandle = null;
        mSyncStatusObserver = null;
    }

非常感谢您的回答。我会尽快尝试一下!这可能是一种解决方法,但这不会阻止定期同步吗?当然……在我的例子中,我使用它来阻止定期同步并触发进程。这些ID是整数标志。这样我就可以触发多个同步,比如
triggerRefresh(同步新闻|同步事件)<代码> > 不是逻辑<代码>和<代码>,它是按位操作。考虑:<代码>事件<代码>等于<代码> 0001 /代码>和<代码>新闻>代码>等于<代码> 0010代码> > <代码> > 0011 < /代码>和<代码> 0011和0001=0001 < /代码>和<代码> 0011和0010=0010 < /代码>。因此两者都有条件。ns是真的,新闻和事件都是同步的,好吧,我从没想过。你能告诉我问题出在哪里吗?
  if (mSyncObserverHandle != null) {
        ContentResolver.removeStatusChangeListener(mSyncObserverHandle);
        mSyncObserverHandle = null;
        mSyncStatusObserver = null;
    }