Search code examples
google-cloud-messagingandroid-syncadapter

Best practice for co-ordinating a SyncAdapter and GCM within the same app


My app uses a SyncAdapter to periodically sync server data with SQLite. It also syncs this data in response to a GCM message that indicates new/updated server data; via. an IntentService.

These components each do their work in different background threads and are created by different system processes (SyncManager/GCM broadcast) and have different lifecycles; unpredictably!

What is the best approach to fault-tolerantly co-ordinate these components: e.g.

  • for an Activity to signal to each that they should do no work
  • to signal to the SyncAdapter to do no work when the GCM IntentService is working, and vice versa.

Solution

  • You should

    1. Put all your syncing code into the SyncAdapter
    2. Remove the IntentService
    3. In the GcmBroadcastReceiver you start the SyncAdapter instead of the IntentService.

    Below is example code copied from the SyncAdapter documentation.

    public class GcmBroadcastReceiver extends BroadcastReceiver {
        ...
        // Constants
        // Content provider authority
        public static final String AUTHORITY = "com.example.android.datasync.provider"
        // Account type
        public static final String ACCOUNT_TYPE = "com.example.android.datasync";
        // Account
        public static final String ACCOUNT = "default_account";
        // Incoming Intent key for extended data
        public static final String KEY_SYNC_REQUEST =
            "com.example.android.datasync.KEY_SYNC_REQUEST";
        ...
        @Override
        public void onReceive(Context context, Intent intent) {
            // Get a GCM object instance
            GoogleCloudMessaging gcm =
                GoogleCloudMessaging.getInstance(context);
                // Get the type of GCM message
            String messageType = gcm.getMessageType(intent);
            /*
             * Test the message type and examine the message contents.
             * Since GCM is a general-purpose messaging system, you
             * may receive normal messages that don't require a sync
             * adapter run.
             * The following code tests for a a boolean flag indicating
             * that the message is requesting a transfer from the device.
             */
            if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)
                &&
                intent.getBooleanExtra(KEY_SYNC_REQUEST)) {
                /*
                 * Signal the framework to run your sync adapter. Assume that
                 * app initialization has already created the account.
                 */
                ContentResolver.requestSync(ACCOUNT, AUTHORITY, null);
                ...
            }
            ...
        }
        ...
    }