SyncAdapter not being called depending on order of

2019-02-16 06:49发布

问题:

I've come across some slightly odd behaviour with my SyncAdapter.

The first time I install my app (after uninstalling with adb), it launches and creates an account. Depending on the ordering of some statements (see below), my SyncAdapter's onPerformSync() will never be called; my account under "Accounts and sync" shows the "sync in progress" icon spinning indefinitely. If I then uncheck the sync checkbox next to my app's account, and then recheck it, my onPerformSync() is called immediately.

This causes my SyncAdapter to never be called. "sync in progress" icon spins forever, unless I uncheck, then recheck the sync checkbox:

final Account account = new Account(mUsername, getString(R.string.ACCOUNT_TYPE));
mAccountManager.addAccountExplicitly(account, mPassword, null);
ContentResolver.setSyncAutomatically(account, getString(R.string.CONTENT_AUTHORITY), true);
ContentResolver.setIsSyncable(account, getString(R.string.CONTENT_AUTHORITY), 1);

With this ordering of the same statements, everything works perfectly:

final Account account = new Account(mUsername, getString(R.string.ACCOUNT_TYPE));
ContentResolver.setSyncAutomatically(account, getString(R.string.CONTENT_AUTHORITY), true);
ContentResolver.setIsSyncable(account, getString(R.string.CONTENT_AUTHORITY), 1);
mAccountManager.addAccountExplicitly(account, mPassword, null);

My guess is I'm putting the SyncManager into some inconsistent state due to it firing off a sync request instantly on account creation, and I'm changing its config under its feet. But the (barely coherent) documentation doesn't mention any issues with calling these functions whenever you like.

As an aside for others struggling with SyncAdapters, I found that contentResolver.requestSync() will never trigger your SyncAdapter.onPerformSync() unless you call ContentResolver.setIsSyncable(account, getString(R.string.CONTENT_AUTHORITY), 1);.

Could someone explain this behaviour? The documentation surrounding Accounts and Syncing is somewhat unclear to say the least.

I'm getting this behaviour on the 2.1 Emulator, compiling against the 2.1 SDK.

回答1:

I found that contentResolver.requestSync() will never trigger your SyncAdapter.onPerformSync() unless you call ContentResolver.setIsSyncable(account, getString(R.string.CONTENT_AUTHORITY), 1);.

For a detailed account of the solution I went with using SyncAdapter, see my answer here:

https://stackoverflow.com/a/12015967/988870



回答2:

I just banged my head against a wall for hours trying to figure out why periodic sync wasn't working. It turns out that the poll frequency needs to be in seconds (literal) not milliseconds, and not seconds in milliseconds. So, for example, if you want it to sync every minute and a half, you would need to call:

            ContentResolver.addPeriodicSync(
                    account,
                    authority,
                    Bundle.EMPTY,
                    90
            );

Also, the bundle passed in cannot be null as it is in the documentation, it will throw a NullPointerException.