1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.provider.cts.contacts; 18 19 import android.content.ContentResolver; 20 import android.content.ContentUris; 21 import android.content.ContentValues; 22 import android.database.Cursor; 23 import android.net.Uri; 24 import android.provider.ContactsContract; 25 import android.provider.ContactsContract.AggregationExceptions; 26 27 import junit.framework.Assert; 28 29 /** 30 * Convenience methods for operating on the Contacts table. 31 */ 32 public class ContactUtil { 33 34 private static final Uri URI = ContactsContract.Contacts.CONTENT_URI; 35 update(ContentResolver resolver, long contactId, ContentValues values)36 public static int update(ContentResolver resolver, long contactId, 37 ContentValues values) { 38 Uri uri = ContentUris.withAppendedId(URI, contactId); 39 return resolver.update(uri, values, null, null); 40 } 41 delete(ContentResolver resolver, long contactId)42 public static void delete(ContentResolver resolver, long contactId) { 43 Uri uri = ContentUris.withAppendedId(URI, contactId); 44 resolver.delete(uri, null, null); 45 } 46 recordExistsForContactId(ContentResolver resolver, long contactId)47 public static boolean recordExistsForContactId(ContentResolver resolver, long contactId) { 48 String[] projection = new String[]{ 49 ContactsContract.Contacts._ID 50 }; 51 Uri uri = ContentUris.withAppendedId(URI, contactId); 52 Cursor cursor = resolver.query(uri, projection, null, null, null); 53 if (cursor.moveToNext()) { 54 return true; 55 } 56 return false; 57 } 58 queryContactLastUpdatedTimestamp(ContentResolver resolver, long contactId)59 public static long queryContactLastUpdatedTimestamp(ContentResolver resolver, long contactId) { 60 String[] projection = new String[]{ 61 ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP 62 }; 63 64 Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId); 65 Cursor cursor = resolver.query(uri, projection, null, null, null); 66 try { 67 if (cursor.moveToNext()) { 68 return cursor.getLong(0); 69 } 70 } finally { 71 if (cursor != null) { 72 cursor.close(); 73 } 74 } 75 return CommonDatabaseUtils.NOT_FOUND; 76 } 77 78 /** 79 * Verifies that the number of object parameters is either zero or even, inserts them 80 * into a new ContentValues object as a set of name-value pairs, and returns the newly created 81 * ContentValues object. Throws an exception if the number of string parameters is odd, or a 82 * single null parameter was provided. 83 * 84 * @param namesAndValues Zero or even number of object parameters to convert into name-value 85 * pairs 86 * 87 * @return newly created ContentValues containing the provided name-value pairs 88 */ newContentValues(Object... namesAndValues)89 public static ContentValues newContentValues(Object... namesAndValues) { 90 // Checks that the number of provided parameters is zero or even. 91 Assert.assertEquals(0, namesAndValues.length % 2); 92 final ContentValues contentValues = new ContentValues(); 93 for (int i = 0; i < namesAndValues.length - 1; i += 2) { 94 Assert.assertNotNull(namesAndValues[i]); 95 final String name = namesAndValues[i].toString(); 96 final Object value = namesAndValues[i + 1]; 97 if (value == null) { 98 contentValues.putNull(name); 99 } else if (value instanceof String) { 100 contentValues.put(name, (String) value); 101 } else if (value instanceof Integer) { 102 contentValues.put(name, (Integer) value); 103 } else if (value instanceof Long) { 104 contentValues.put(name, (Long) value); 105 } else { 106 Assert.fail("Unsupported value type: " + value.getClass().getSimpleName() + " for " 107 + " name: " + name); 108 } 109 } 110 return contentValues; 111 } 112 113 /** 114 * Updates the content resolver with two given raw contact ids and an aggregation type to 115 * manually trigger the forced aggregation, splitting of two raw contacts or specify that 116 * the provider should automatically decide whether or not to aggregate the two raw contacts. 117 * 118 * @param resolver ContentResolver from a valid context 119 * @param type One of the following aggregation exception types: 120 * {@link AggregationExceptions#TYPE_AUTOMATIC}, 121 * {@link AggregationExceptions#TYPE_KEEP_SEPARATE}, 122 * {@link AggregationExceptions#TYPE_KEEP_TOGETHER} 123 * @param rawContactId1 Id of the first raw contact 124 * @param rawContactId2 Id of the second raw contact 125 */ setAggregationException(ContentResolver resolver, int type, long rawContactId1, long rawContactId2)126 public static void setAggregationException(ContentResolver resolver, int type, 127 long rawContactId1, long rawContactId2) { 128 ContentValues values = new ContentValues(); 129 values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 130 values.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 131 values.put(AggregationExceptions.TYPE, type); 132 // Actually set the aggregation exception in the contacts database, and check that a 133 // single row was updated. 134 Assert.assertEquals(1, resolver.update(AggregationExceptions.CONTENT_URI, values, null, 135 null)); 136 } 137 }