Android ContentResolver.requestSync() does not always trigger SyncAdapter immediately after it is canceled

320
July 13, 2017, at 07:10 AM

I have an Android app with a SyncAdapter which works most of the time. It is possible for the user to change what data set they would like to look at, which requires a resync. The user can also change the data set while the app is in the process of syncing which can cause a race condition if the user starts a sync, changes data set, and then the sync completes which leaves them looking at the wrong data.

To fix this, when the user changes data set I would like to cancel any existing sync and then trigger a new sync for the selected data set. I did this like so:

public class MainActivity extends Activity {
    ... // Some members omitted for clarity
    // Called whenever the user changes the data set
    private void onDataSetChanged() {
        final Account account = getSelectedAccount();
        final boolean isSyncActive = ContentResolver.isSyncActive(account, AUTHORITY);
        // Cancel sync for the old data set
        Log.e(TAG, "onDataSetChanged: " + account.name + " - " + isSyncActive);
        if (isSyncActive) {
            ContentResolver.cancelSync(account, AUTHORITY);
        }
        // Request a sync for the new data set
        ContentResolver.requestSync(account, AUTHORITY, new Bundle());
    }
}

Elsewhere I have a SyncAdapter defined:

public class SyncAdapter extends AbstractThreadedSyncAdapter {
    ... // Some members omitted for clarity
    @Override
    public synchronized void onPerformSync(final Account account, final Bundle extras,
            final String authority, final ContentProviderClient provider, final SyncResult syncResult) {
       Log.e(TAG, "onPerformSync: " + account.name);
       ... // Sync logic
   }
}

The SyncAdapter appears to be set up correctly as it is usually called successfully and the #onPerformSync() log statement appears. Only when ContentResolver.cancelSync() is called immediately before ContentResolver.requestSync(), will it sometimes (not always) fail. In those instances SyncAdapter#onPerformSync() is never called and its log statement is not displayed.

I have tried setting ContentResolver.SYNC_EXTRAS_EXPEDITED and ContentResolver.SYNC_EXTRAS_MANUAL as true on the extras bundle, but that has no effect. I've also verified through my own logging that the account and AUTHORITY are correct. I also see the onPerformSync: ... log when it does sync successfully, so I know I am not mis-using Logcat as many people working with SyncAdapters do.

I know requesting a sync is quite a complicated process, but is there at least some way for me to know why the sync was rejected? Other logs don't seem to indicate why it decided to ignore my request.

Rent Charter Buses Company
READ ALSO
Error during apk recompilation

Error during apk recompilation

I'm trying to recompile apk source which was decompiled by APKToolI'm using APKTool version 2

478
How can I run a shell script on Android Things device at boot with root permissions?

How can I run a shell script on Android Things device at boot with root permissions?

I've installed Android Things DP4 on a Raspberry Pi 3Now I need to execute a ifconfig as root in order to set a static IP

353
Go back to first of loop

Go back to first of loop

I want to create an activity with (20 random images+4 buttons under each image) separately in the same activitySo, i use a "for loop" to create 20 random images that each image have 4 buttons

273