info.dc585.hpt.sa.SyncAdapter.java Source code

Java tutorial

Introduction

Here is the source code for info.dc585.hpt.sa.SyncAdapter.java

Source

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package info.dc585.hpt.sa;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.*;
import android.database.Cursor;
import android.os.Bundle;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import info.dc585.hpt.NetworkUtilities;
import info.dc585.hpt.cp.HackerPointsContentProvider;
import info.dc585.hpt.cp.TopHackerTable;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.http.ParseException;
import org.apache.http.auth.AuthenticationException;
import org.json.*;

/**
 * SyncAdapter implementation for syncing sample SyncAdapter contacts to the platform ContactOperations provider. This sample shows a basic 2-way sync between the client and a sample server. It also
 * contains an example of how to update the contacts' status messages, which would be useful for a messaging or social networking client.
 */
public class SyncAdapter extends AbstractThreadedSyncAdapter {

    private static final String TAG = "HPT:SyncAdapter";
    //
    private static final String SYNC_MARKER_KEY = "info.dc585.hpt.sa.marker";
    private static final boolean NOTIFY_AUTH_FAILURE = true;
    private final AccountManager accountManager;
    private final Context mContext;

    public SyncAdapter(Context context, boolean autoInitialize) {

        super(context, autoInitialize);

        mContext = context;
        accountManager = AccountManager.get(context);

    }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
            SyncResult syncResult) {

        syncTopHackers(provider, syncResult);
        syncMe(provider, syncResult);
        syncFriends(provider, syncResult);

    }

    private void syncMe(ContentProviderClient provider, SyncResult syncResult) {
    }

    private void syncFriends(ContentProviderClient provider, SyncResult syncResult) {
    }

    private void syncTopHackers(ContentProviderClient provider, SyncResult syncResult) {

        try {

            Log.d(TAG, "Calling something to sync up hackerpoint db");

            JSONArray hackers = NetworkUtilities.getTopHackers();
            if (hackers == null) {
                Log.e(TAG, "somehow got null hackers, explode please");
                syncResult.stats.numParseExceptions++;
            }
            if (hackers.length() == 0) {
                return;
            }

            Log.i(TAG, "Updateing content provider");
            Log.i(TAG, "hackers.length():" + hackers.length());
            for (int i = 0; i < hackers.length(); i++) {
                JSONObject jo = hackers.getJSONObject(i);
                String name = jo.getString("name");

                String selection = TopHackerTable.COLUMN_NAME + " like ?";
                String[] selectionArgs = { name };

                String[] projection = { TopHackerTable.COLUMN_ID, TopHackerTable.COLUMN_NAME };

                ContentValues values = new ContentValues();

                // FIXME:  Dear self, WTF would i trust network returned data without verifying limits ;)
                // TODO: See FIXME above.
                Cursor c = provider.query(HackerPointsContentProvider.HACKERS_URI, projection, selection,
                        selectionArgs, null);
                if (c.getCount() == 0) {
                    Log.d(TAG, "performing insert for new name:" + name);

                    int points = jo.getInt("points");
                    values.put(TopHackerTable.COLUMN_POINTS, points);

                    int pool = jo.getInt("pool");
                    values.put(TopHackerTable.COLUMN_POOL, pool);

                    int internets = jo.getInt("internets");
                    values.put(TopHackerTable.COLUMN_INTERNETS, internets);

                    String pictureURL = jo.getString("pictureURL");
                    values.put(TopHackerTable.COLUMN_PICTUREURL, pictureURL);

                    values.put(TopHackerTable.COLUMN_NAME, name);
                    values.put(TopHackerTable.COLUMN_UPDATE, System.currentTimeMillis());
                    provider.insert(HackerPointsContentProvider.HACKERS_URI, values);
                    syncResult.stats.numInserts++;

                } else if (c.getCount() == 1) {
                    Log.d(TAG, "performing update for name:" + name);
                    if (name == null || name.isEmpty()) {
                        Log.e(TAG, "null or empty name");
                        continue;
                    }

                    int points = jo.getInt("points");
                    values.put(TopHackerTable.COLUMN_POINTS, points);

                    int pool = jo.getInt("pool");
                    values.put(TopHackerTable.COLUMN_POOL, pool);

                    int internets = jo.getInt("internets");
                    values.put(TopHackerTable.COLUMN_INTERNETS, internets);

                    String pictureURL = jo.getString("pictureURL");
                    values.put(TopHackerTable.COLUMN_PICTUREURL, pictureURL);

                    int rows = provider.update(HackerPointsContentProvider.HACKERS_URI, values, selection,
                            selectionArgs);

                    Log.d(TAG, "Updated:" + rows + ": rows");
                    syncResult.stats.numUpdates += rows;

                } else {
                    Log.e(TAG, "Cursor count was not 0 or 1 was:" + c.getCount());
                    continue;
                }
            }

            // Now run through both lists and figure out which one to delete.
            String[] projection = { TopHackerTable.COLUMN_NAME };
            Cursor c = provider.query(HackerPointsContentProvider.HACKERS_URI, projection, null, null, null);
            if (c.getCount() == 0) {
                return;
            }

            ArrayList<String> goodNames = new ArrayList<String>();
            ArrayList<String> rmNames = new ArrayList<String>();

            for (int i = 0; i < hackers.length(); i++) {
                JSONObject jo = hackers.getJSONObject(i);
                String name = jo.getString("name");
                goodNames.add(name);
            }

            while (c.moveToNext()) {
                int namec = c.getColumnIndex(TopHackerTable.COLUMN_NAME);
                String dbName = c.getString(namec);

                if (goodNames.contains(dbName) == false) {
                    Log.d(TAG, "Adding name:" + dbName + ": to the delete list");
                    rmNames.add(dbName);
                }
            }

            for (String nextName : rmNames) {
                Log.d(TAG, "deleting name:" + nextName + ":");
                // FIXME: use column name from Table class
                String where = " name = ? ";
                String[] whereArgs = { nextName };
                int rows = provider.delete(HackerPointsContentProvider.HACKERS_URI, where, whereArgs);
                syncResult.stats.numDeletes += rows;
            }

        } catch (final AuthenticationException e) {
            Log.e(TAG, "AuthenticationException", e);
        } catch (final JSONException e) {
            Log.e(TAG, "JSONException", e);
        } catch (final IOException e) {
            Log.e(TAG, "IOException", e);
        } catch (final ParseException e) {
            Log.e(TAG, "ParseException", e);
            syncResult.stats.numParseExceptions++;
        } catch (final RemoteException e) {
            Log.e(TAG, "RemoteException", e);
        }
    }

    /**
     * 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 = accountManager.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) {
        accountManager.setUserData(account, SYNC_MARKER_KEY, Long.toString(marker));
    }
}