package com.talk.demo.sync; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; import android.content.Context; import android.content.SyncResult; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import com.talk.demo.account.AccountConstants; import com.talk.demo.persistence.DBManager; import com.talk.demo.types.Friend; import com.talk.demo.types.Group; import com.talk.demo.types.Record; import com.talk.demo.util.HttpRequest.HttpRequestException; import com.talk.demo.util.NetworkUtilities; import org.apache.http.ParseException; import org.json.JSONException; import java.io.IOException; import java.util.List; public class SyncAdapter extends AbstractThreadedSyncAdapter { private static final String TAG = "SyncAdapter"; private static final String SYNC_MARKER_KEY = "com.talk.demo.sync.marker"; private static final boolean NOTIFY_AUTH_FAILURE = true; private final AccountManager mAccountManager; private final Context mContext; public SyncAdapter(Context context, boolean autoInitialize) { super(context, autoInitialize); mContext = context; mAccountManager = AccountManager.get(context); } public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) { super(context, autoInitialize, allowParallelSyncs); mContext = context; mAccountManager = AccountManager.get(context); } @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { Log.d(TAG, "onPerformSync"); try { List<Record> dirtyRecords; Group<Record> updatedRecords; // see if we already have a sync-state attached to this account. By handing // This value to the server, we can just get the contacts that have // been updated on the server-side since our last sync-up long lastSyncMarker = getServerSyncMarker(account); // Use the account manager to request the AuthToken we'll need // to talk to our sample server. If we don't have an AuthToken // yet, this could involve a round-trip to the server to request // and AuthToken. String authtoken = mAccountManager.blockingGetAuthToken(account, AccountConstants.AUTHTOKEN_TYPE, NOTIFY_AUTH_FAILURE); DBManager db = new DBManager(mContext); dirtyRecords = SyncCompaign.getDirtyRecords(db); Log.d(TAG, "sync record start"); updatedRecords = NetworkUtilities.syncRecords_v2(account, authtoken, lastSyncMarker, dirtyRecords); long newSyncState = SyncCompaign.updateRecords(db, updatedRecords, lastSyncMarker); Log.d(TAG, "sync friend start"); List<Friend> dirtyFriends; Group<Friend> updatedFriends; dirtyFriends = SyncCompaign2.getDirtyFriends(db); updatedFriends = NetworkUtilities.syncFriends_v2(account, authtoken, lastSyncMarker, dirtyFriends); SyncCompaign2.updateFriends(db, updatedFriends); setServerSyncMarker(account, newSyncState); } catch (final AuthenticatorException e) { Log.e(TAG, "AuthenticatorException", e); syncResult.stats.numParseExceptions++; } catch (final OperationCanceledException e) { Log.e(TAG, "OperationCanceledExcetpion", e); } catch (final IOException e) { Log.e(TAG, "IOException", e); syncResult.stats.numIoExceptions++; } catch (final ParseException e) { Log.e(TAG, "ParseException", e); syncResult.stats.numParseExceptions++; } catch (HttpRequestException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (JSONException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } /** * This helper function fetches the last known high-water-mark * we received from the server - or 0 if we've never synced. * @param account the account we're syncing * @return the change high-water-mark */ private long getServerSyncMarker(Account account) { String markerString = mAccountManager.getUserData(account, SYNC_MARKER_KEY); if (!TextUtils.isEmpty(markerString)) { return Long.parseLong(markerString); } return 0; } /** * Save off the high-water-mark we receive back from the server. * @param account The account we're syncing * @param marker The high-water-mark we want to save. */ private void setServerSyncMarker(Account account, long marker) { mAccountManager.setUserData(account, SYNC_MARKER_KEY, Long.toString(marker)); } }