Example usage for android.content ContentProviderClient insert

List of usage examples for android.content ContentProviderClient insert

Introduction

In this page you can find the example usage for android.content ContentProviderClient insert.

Prototype

public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues) throws RemoteException 

Source Link

Document

See ContentProvider#insert ContentProvider.insert

Usage

From source file:com.granita.icloudcalsync.resource.LocalCalendar.java

@SuppressLint("InlinedApi")
public static Uri create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info)
        throws LocalStorageException {
    final ContentProviderClient client = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY);
    if (client == null)
        throw new LocalStorageException("No Calendar Provider found (Calendar app disabled?)");

    ContentValues values = new ContentValues();
    values.put(Calendars.ACCOUNT_NAME, account.name);
    values.put(Calendars.ACCOUNT_TYPE, account.type);
    values.put(Calendars.NAME, info.getURL());
    values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle());
    values.put(Calendars.CALENDAR_COLOR, DAVUtils.CalDAVtoARGBColor(info.getColor()));
    values.put(Calendars.OWNER_ACCOUNT, account.name);
    values.put(Calendars.SYNC_EVENTS, 1);
    values.put(Calendars.VISIBLE, 1);// w  w w. j a v a  2  s. c  o m
    values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);

    if (info.isReadOnly())
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ);
    else {
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
        values.put(Calendars.CAN_ORGANIZER_RESPOND, 1);
        values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1);
    }

    if (android.os.Build.VERSION.SDK_INT >= 15) {
        values.put(Calendars.ALLOWED_AVAILABILITY, Events.AVAILABILITY_BUSY + "," + Events.AVAILABILITY_FREE
                + "," + Events.AVAILABILITY_TENTATIVE);
        values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Attendees.TYPE_NONE + "," + Attendees.TYPE_OPTIONAL + ","
                + Attendees.TYPE_REQUIRED + "," + Attendees.TYPE_RESOURCE);
    }

    if (info.getTimezone() != null)
        values.put(Calendars.CALENDAR_TIME_ZONE, info.getTimezone());

    Log.i(TAG, "Inserting calendar: " + values.toString());
    try {
        return client.insert(calendarsURI(account), values);
    } catch (RemoteException e) {
        throw new LocalStorageException(e);
    }
}

From source file:at.bitfire.davdroid.resource.LocalCalendar.java

@SuppressLint("InlinedApi")
public static Uri create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info)
        throws LocalStorageException {
    @Cleanup("release")
    final ContentProviderClient client = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY);
    if (client == null)
        throw new LocalStorageException("No Calendar Provider found (Calendar app disabled?)");

    ContentValues values = new ContentValues();
    values.put(Calendars.ACCOUNT_NAME, account.name);
    values.put(Calendars.ACCOUNT_TYPE, account.type);
    values.put(Calendars.NAME, info.getURL());
    values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle());
    values.put(Calendars.CALENDAR_COLOR, info.getColor() != null ? info.getColor() : DAVUtils.calendarGreen);
    values.put(Calendars.OWNER_ACCOUNT, account.name);
    values.put(Calendars.SYNC_EVENTS, 1);
    values.put(Calendars.VISIBLE, 1);/*from   w w w.  java2 s  .  c  o  m*/
    values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);

    if (info.isReadOnly())
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ);
    else {
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
        values.put(Calendars.CAN_ORGANIZER_RESPOND, 1);
        values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1);
    }

    if (android.os.Build.VERSION.SDK_INT >= 15) {
        values.put(Calendars.ALLOWED_AVAILABILITY, Events.AVAILABILITY_BUSY + "," + Events.AVAILABILITY_FREE
                + "," + Events.AVAILABILITY_TENTATIVE);
        values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Attendees.TYPE_NONE + "," + Attendees.TYPE_OPTIONAL + ","
                + Attendees.TYPE_REQUIRED + "," + Attendees.TYPE_RESOURCE);
    }

    if (info.getTimezone() != null)
        values.put(Calendars.CALENDAR_TIME_ZONE, DateUtils.findAndroidTimezoneID(info.getTimezone()));

    Log.i(TAG, "Inserting calendar: " + values.toString());
    try {
        return client.insert(calendarsURI(account), values);
    } catch (RemoteException e) {
        throw new LocalStorageException(e);
    }
}

From source file:at.bitfire.davdroid.mirakel.resource.LocalCalendar.java

@SuppressLint("InlinedApi")
public static void create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info)
        throws LocalStorageException {
    ContentProviderClient client = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY);
    if (client == null)
        throw new LocalStorageException("No Calendar Provider found (Calendar app disabled?)");

    int color = 0xFFC3EA6E; // fallback: "DAVdroid green"
    if (info.getColor() != null) {
        Pattern p = Pattern.compile("#(\\p{XDigit}{6})(\\p{XDigit}{2})?");
        Matcher m = p.matcher(info.getColor());
        if (m.find()) {
            int color_rgb = Integer.parseInt(m.group(1), 16);
            int color_alpha = m.group(2) != null ? (Integer.parseInt(m.group(2), 16) & 0xFF) : 0xFF;
            color = (color_alpha << 24) | color_rgb;
        }/*  w  w  w  . java  2s.c o m*/
    }

    ContentValues values = new ContentValues();
    values.put(Calendars.ACCOUNT_NAME, account.name);
    values.put(Calendars.ACCOUNT_TYPE, account.type);
    values.put(Calendars.NAME, info.getURL());
    values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle());
    values.put(Calendars.CALENDAR_COLOR, color);
    values.put(Calendars.OWNER_ACCOUNT, account.name);
    values.put(Calendars.SYNC_EVENTS, 1);
    values.put(Calendars.VISIBLE, 1);
    values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);

    if (info.isReadOnly())
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ);
    else {
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
        values.put(Calendars.CAN_ORGANIZER_RESPOND, 1);
        values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1);
    }

    if (android.os.Build.VERSION.SDK_INT >= 15) {
        values.put(Calendars.ALLOWED_AVAILABILITY, Events.AVAILABILITY_BUSY + "," + Events.AVAILABILITY_FREE
                + "," + Events.AVAILABILITY_TENTATIVE);
        values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Attendees.TYPE_NONE + "," + Attendees.TYPE_OPTIONAL + ","
                + Attendees.TYPE_REQUIRED + "," + Attendees.TYPE_RESOURCE);
    }

    if (info.getTimezone() != null)
        values.put(Calendars.CALENDAR_TIME_ZONE, info.getTimezone());

    Log.i(TAG, "Inserting calendar: " + values.toString() + " -> " + calendarsURI(account).toString());
    try {
        client.insert(calendarsURI(account), values);
    } catch (RemoteException e) {
        throw new LocalStorageException(e);
    }
}

From source file:net.sf.diningout.content.SyncAdapter.java

/**
 * Download and update the details of Google Places that haven't been refreshed recently.
 *//*  w w w. j a  v  a  2  s.c  om*/
private void refreshRestaurants(Context context, ContentProviderClient cp) throws RemoteException {
    int rows = Content.getCount(context, RESTAURANTS_URI);
    int days = 30; // age when restaurants should be refreshed
    Uri uri = Uris.limit(RESTAURANTS_URI, rows / days + 1);
    String[] proj = { _ID, Restaurants.PLACE_ID };
    String sel = Restaurants.PLACE_ID + " IS NOT NULL AND " + Restaurants.PLACE_ID
            + " NOT LIKE 'NOT_FOUND_%' AND (" + Restaurants.REFRESHED_ON + " IS NULL OR "
            + Restaurants.REFRESHED_ON + " <= datetime('now', '-" + days + " days')) AND "
            + Restaurants.STATUS_ID + " = ?";
    String[] args = { String.valueOf(ACTIVE.id) };
    String order = Restaurants.REFRESHED_ON + " IS NULL DESC, " + Restaurants.REFRESHED_ON + ", " + _ID;
    EasyCursor c = new EasyCursor(cp.query(uri, proj, sel, args, order));
    Result[] results = null;
    try {
        results = RestaurantsRefreshService.refresh(c);
    } catch (IOException e) {
        Log.e(TAG, "refreshing restaurants", e);
        exception(e);
    }
    c.close();
    if (results != null) {
        for (Result result : results) {
            if (result.newReviewTimes != null) {
                int size = result.newReviewTimes.size();
                for (int i = 0; i < size; i++) {
                    cp.insert(SYNCS_URI,
                            Syncs.values(result.newReviewTimes.keyAt(i), result.newReviewTimes.valueAt(i)));
                }
            }
        }
    }
}

From source file:org.exfio.csyncdroid.resource.LocalCalendar.java

@SuppressLint("InlinedApi")
public static void create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info)
        throws RemoteException {
    ContentProviderClient client = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY);

    //FIXME - change default colour
    int color = 0xFFC3EA6E; // fallback: "DAVdroid green"
    if (info.getColor() != null) {
        Pattern p = Pattern.compile("#(\\p{XDigit}{6})(\\p{XDigit}{2})?");
        Matcher m = p.matcher(info.getColor());
        if (m.find()) {
            int color_rgb = Integer.parseInt(m.group(1), 16);
            int color_alpha = m.group(2) != null ? (Integer.parseInt(m.group(2), 16) & 0xFF) : 0xFF;
            color = (color_alpha << 24) | color_rgb;
        }// ww w.j av a2  s.  c  o m
    }

    ContentValues values = new ContentValues();
    values.put(Calendars.ACCOUNT_NAME, account.name);
    values.put(Calendars.ACCOUNT_TYPE, account.type);
    values.put(Calendars.NAME, info.getCollection());
    values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle());
    values.put(Calendars.CALENDAR_COLOR, color);
    values.put(Calendars.OWNER_ACCOUNT, account.name);
    values.put(Calendars.SYNC_EVENTS, 1);
    values.put(Calendars.VISIBLE, 1);
    values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);

    if (info.isReadOnly())
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ);
    else {
        values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
        values.put(Calendars.CAN_ORGANIZER_RESPOND, 1);
        values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1);
    }

    if (android.os.Build.VERSION.SDK_INT >= 15) {
        values.put(Calendars.ALLOWED_AVAILABILITY, Events.AVAILABILITY_BUSY + "," + Events.AVAILABILITY_FREE
                + "," + Events.AVAILABILITY_TENTATIVE);
        values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Attendees.TYPE_NONE + "," + Attendees.TYPE_OPTIONAL + ","
                + Attendees.TYPE_REQUIRED + "," + Attendees.TYPE_RESOURCE);
    }

    if (info.getTimezone() != null)
        values.put(Calendars.CALENDAR_TIME_ZONE, info.getTimezone());

    Log.i(TAG, "Inserting calendar: " + values.toString() + " -> " + calendarsURI(account).toString());
    client.insert(calendarsURI(account), values);
}

From source file:com.clearcenter.mobile_demo.mdSyncAdapter.java

public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
        SyncResult syncResult) {//from w ww .  ja  v  a  2s .  c om
    String authtoken = null;
    Log.i(TAG, "Starting sync operation...");

    try {
        mdSSLUtil.DisableSecurity();

        // 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
        // an AuthToken.
        authtoken = account_manager.blockingGetAuthToken(account, mdConstants.AUTHTOKEN_TYPE,
                NOTIFY_AUTH_FAILURE);

        final String hostname = account_manager.getUserData(account, "hostname");

        long _last_sample = -1;
        if (last_sample.containsKey(account.name))
            _last_sample = last_sample.get(account.name);

        // Get sync data from server...
        final String data = mdRest.GetSystemInfo(hostname, authtoken, _last_sample);

        // Something went wrong :^(
        if (TextUtils.isEmpty(data))
            return;

        if (_last_sample < 0) {
            int count = provider.delete(mdDeviceSamples.CONTENT_URI, mdDeviceSamples.NICKNAME + " = ?",
                    new String[] { account.name });

            Log.d(TAG, "Reset database, purged " + count + " samples.");
        }

        try {
            JSONObject json_data = new JSONObject(data);
            if (json_data.has("time"))
                _last_sample = Long.valueOf(json_data.getString("time"));
            Log.d(TAG, account.name + ": last sample time-stamp: " + _last_sample);
        } catch (JSONException e) {
            Log.e(TAG, "JSONException", e);
            return;
        }

        last_sample.put(account.name, _last_sample);

        ContentValues values = new ContentValues();
        values.put(mdDeviceSamples.NICKNAME, account.name);
        values.put(mdDeviceSamples.DATA, data);

        provider.insert(mdDeviceSamples.CONTENT_URI, values);

        String projection[] = new String[] { mdDeviceSamples.SAMPLE_ID };

        Cursor cursor = provider.query(mdDeviceSamples.CONTENT_URI, projection,
                mdDeviceSamples.NICKNAME + " = ?", new String[] { account.name }, mdDeviceSamples.SAMPLE_ID);

        int rows = cursor.getCount();
        Log.d(TAG, "Rows: " + rows);
        if (rows <= mdConstants.MAX_SAMPLES) {
            cursor.close();
            return;
        }

        Log.d(TAG, "Samples to purge: " + (rows - mdConstants.MAX_SAMPLES));
        cursor.move(rows - mdConstants.MAX_SAMPLES);

        int top_id = cursor.getInt(cursor.getColumnIndex(mdDeviceSamples.SAMPLE_ID));
        Log.d(TAG, "Top ID: " + top_id);

        cursor.close();

        int count = provider.delete(mdDeviceSamples.CONTENT_URI,
                mdDeviceSamples.SAMPLE_ID + " <= ? AND " + mdDeviceSamples.NICKNAME + " = ?",
                new String[] { String.valueOf(top_id), account.name });

        Log.d(TAG, "Purged " + count + " samples.");

    } catch (final RemoteException e) {
        Log.e(TAG, "RemoteException", e);
        syncResult.stats.numParseExceptions++;
    } 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 (final AuthenticationException e) {
        Log.e(TAG, "AuthenticationException", e);
        syncResult.stats.numAuthExceptions++;
        account_manager.invalidateAuthToken(mdConstants.AUTHTOKEN_TYPE, authtoken);
    } catch (GeneralSecurityException e) {
        Log.e(TAG, "GeneralSecurityException", e);
    } catch (final JSONException e) {
        Log.e(TAG, "JSONException", e);
        syncResult.stats.numParseExceptions++;
    }
}

From source file:info.dc585.hpt.sa.SyncAdapter.java

private void syncTopHackers(ContentProviderClient provider, SyncResult syncResult) {

    try {/*w ww. jav a 2  s  .  c  om*/

        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);
    }
}

From source file:net.sf.diningout.content.SyncAdapter.java

/**
 * Insert new system contacts, delete orphaned app contacts, and synchronise any changes to
 * existing./*from w w w  .  jav a2  s  . c  o m*/
 */
private void refreshContacts(Context context, ContentProviderClient cp) throws RemoteException {
    /* get system contacts */
    String[] proj = { Email.ADDRESS, ContactsContract.Contacts.LOOKUP_KEY, RawContacts.CONTACT_ID,
            ContactsContract.Contacts.DISPLAY_NAME };
    String sel = Email.IN_VISIBLE_GROUP + " = 1 AND " + Email.ADDRESS + " <> ?";
    String[] args = { Accounts.selected().name };
    EasyCursor sys = new EasyCursor(cr().query(Email.CONTENT_URI, proj, sel, args, Email.ADDRESS));
    /* get app contacts */
    proj = new String[] { Contacts.EMAIL, Contacts.ANDROID_LOOKUP_KEY, Contacts.ANDROID_ID, Contacts.NAME, _ID,
            Contacts.FOLLOWING, Contacts.STATUS_ID };
    sel = Contacts.EMAIL + " IS NOT NULL";
    EasyCursor app = new EasyCursor(cp.query(CONTACTS_URI, proj, sel, null, Contacts.EMAIL));
    /* compare and sync */
    ContentValues vals = new ContentValues();
    for (CursorJoiner.Result result : new CursorJoiner(sys, new String[] { Email.ADDRESS }, app,
            new String[] { Contacts.EMAIL })) {
        switch (result) {
        case LEFT: // new system contact, insert into app contacts
            String email = sys.getString(Email.ADDRESS);
            String hash = BaseEncoding.base64()
                    .encode(Hashing.sha512().hashString(email.toLowerCase(ENGLISH), UTF_8).asBytes());
            long id = Contacts.idForHash(hash); // do we have this contact and not know it?
            /* insert or update values */
            vals.put(Contacts.ANDROID_LOOKUP_KEY, sys.getString(ContactsContract.Contacts.LOOKUP_KEY));
            vals.put(Contacts.ANDROID_ID, sys.getLong(RawContacts.CONTACT_ID));
            String name = sys.getString(ContactsContract.Contacts.DISPLAY_NAME);
            vals.put(Contacts.NAME, name);
            vals.put(Contacts.NORMALISED_NAME, SQLite.normalise(name));
            vals.put(Contacts.EMAIL, email);
            if (id <= 0) {
                vals.put(Contacts.EMAIL_HASH, hash);
                vals.put(Contacts.COLOR, Contacts.defaultColor());
                id = ContentUris.parseId(cp.insert(CONTACTS_URI, vals));
            } else {
                cp.update(ContentUris.withAppendedId(CONTACTS_URI, id), vals, null, null);
            }
            if (id > 0) {
                context.startService(new Intent(context, FriendColorService.class)
                        .putExtra(FriendColorService.EXTRA_ID, id));
            }
            break;
        case RIGHT: // orphaned app contact, delete unless user is following
            if (app.getInt(Contacts.FOLLOWING) == 0 && app.getInt(Contacts.STATUS_ID) == ACTIVE.id) {
                vals.put(Contacts.STATUS_ID, DELETED.id);
                vals.put(Contacts.DIRTY, 1);
                cp.update(Uris.appendId(CONTACTS_URI, app), vals, null, null);
            }
            break;
        case BOTH: // matching contacts, update details in app if needed
            String s = sys.getString(ContactsContract.Contacts.LOOKUP_KEY);
            if (!s.equals(app.getString(Contacts.ANDROID_LOOKUP_KEY))) {
                vals.put(Contacts.ANDROID_LOOKUP_KEY, s);
            }
            long l = sys.getLong(RawContacts.CONTACT_ID);
            if (l != app.getLong(Contacts.ANDROID_ID)) {
                vals.put(Contacts.ANDROID_ID, l);
            }
            s = sys.getString(ContactsContract.Contacts.DISPLAY_NAME);
            if (!s.equals(app.getString(Contacts.NAME))) {
                vals.put(Contacts.NAME, s);
                vals.put(Contacts.NORMALISED_NAME, SQLite.normalise(s));
            }
            if (app.getInt(Contacts.STATUS_ID) == DELETED.id) {
                vals.put(Contacts.STATUS_ID, ACTIVE.id);
                vals.put(Contacts.DIRTY, 1);
            }
            if (vals.size() > 0) {
                cp.update(Uris.appendId(CONTACTS_URI, app), vals, null, null);
                context.startService(new Intent(context, FriendColorService.class)
                        .putExtra(FriendColorService.EXTRA_ID, app.getLong(_ID)));
            }
            break;
        }
        vals.clear();
    }
    sys.close();
    app.close();
}