BaseContactsProvider2Test.java revision 7d82ae92714f2132e3a0971d844ae8cdf10d76e7
1/* 2 * Copyright (C) 2009 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 17package com.android.providers.contacts; 18 19import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY; 20 21import com.google.android.collect.Sets; 22 23import android.accounts.Account; 24import android.content.ContentProvider; 25import android.content.ContentResolver; 26import android.content.ContentUris; 27import android.content.ContentValues; 28import android.content.Context; 29import android.content.Entity; 30import android.content.res.Resources; 31import android.database.Cursor; 32import android.net.Uri; 33import android.provider.ContactsContract; 34import android.provider.ContactsContract.AggregationExceptions; 35import android.provider.ContactsContract.CommonDataKinds.Email; 36import android.provider.ContactsContract.CommonDataKinds.Event; 37import android.provider.ContactsContract.CommonDataKinds.GroupMembership; 38import android.provider.ContactsContract.CommonDataKinds.Im; 39import android.provider.ContactsContract.CommonDataKinds.Nickname; 40import android.provider.ContactsContract.CommonDataKinds.Note; 41import android.provider.ContactsContract.CommonDataKinds.Organization; 42import android.provider.ContactsContract.CommonDataKinds.Phone; 43import android.provider.ContactsContract.CommonDataKinds.Photo; 44import android.provider.ContactsContract.CommonDataKinds.StructuredName; 45import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 46import android.provider.ContactsContract.Contacts; 47import android.provider.ContactsContract.Data; 48import android.provider.ContactsContract.Groups; 49import android.provider.ContactsContract.RawContacts; 50import android.provider.ContactsContract.Settings; 51import android.provider.ContactsContract.StatusUpdates; 52import android.test.AndroidTestCase; 53import android.test.MoreAsserts; 54import android.test.mock.MockContentResolver; 55import android.util.Log; 56 57import java.io.ByteArrayOutputStream; 58import java.io.IOException; 59import java.io.InputStream; 60import java.util.ArrayList; 61import java.util.Arrays; 62import java.util.Comparator; 63import java.util.Iterator; 64import java.util.Map; 65import java.util.Map.Entry; 66import java.util.Set; 67 68/** 69 * A common superclass for {@link ContactsProvider2}-related tests. 70 */ 71public abstract class BaseContactsProvider2Test extends AndroidTestCase { 72 73 protected static final String PACKAGE = "ContactsProvider2Test"; 74 public static final String READ_ONLY_ACCOUNT_TYPE = 75 SynchronousContactsProvider2.READ_ONLY_ACCOUNT_TYPE; 76 77 protected ContactsActor mActor; 78 protected MockContentResolver mResolver; 79 protected Account mAccount = new Account("account1", "account type1"); 80 protected Account mAccountTwo = new Account("account2", "account type2"); 81 82 private byte[] mTestPhoto; 83 84 protected final static Long NO_LONG = new Long(0); 85 protected final static String NO_STRING = new String(""); 86 protected final static Account NO_ACCOUNT = new Account("a", "b"); 87 88 protected Class<? extends ContentProvider> getProviderClass() { 89 return SynchronousContactsProvider2.class; 90 } 91 92 protected String getAuthority() { 93 return ContactsContract.AUTHORITY; 94 } 95 96 @Override 97 protected void setUp() throws Exception { 98 super.setUp(); 99 100 mActor = new ContactsActor(getContext(), PACKAGE_GREY, getProviderClass(), getAuthority()); 101 mResolver = mActor.resolver; 102 if (mActor.provider instanceof SynchronousContactsProvider2) { 103 getContactsProvider().wipeData(); 104 } 105 } 106 107 @Override 108 protected void tearDown() throws Exception { 109 if (mActor.provider instanceof SynchronousContactsProvider2) { 110 getContactsProvider().getDatabaseHelper(mActor.context).close(); 111 } 112 super.tearDown(); 113 } 114 115 public SynchronousContactsProvider2 getContactsProvider() { 116 return (SynchronousContactsProvider2) mActor.provider; 117 } 118 119 public Context getMockContext() { 120 return mActor.context; 121 } 122 123 public void addAuthority(String authority) { 124 mActor.addAuthority(authority); 125 } 126 127 public ContentProvider addProvider(Class<? extends ContentProvider> providerClass, 128 String authority) throws Exception { 129 return mActor.addProvider(providerClass, authority); 130 } 131 132 public ContentProvider getProvider() { 133 return mActor.provider; 134 } 135 136 protected Uri maybeAddAccountQueryParameters(Uri uri, Account account) { 137 if (account == null) { 138 return uri; 139 } 140 return uri.buildUpon() 141 .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) 142 .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type) 143 .build(); 144 } 145 146 protected long createRawContact() { 147 return createRawContact(null); 148 } 149 150 protected long createRawContactWithName() { 151 return createRawContactWithName(null); 152 } 153 154 protected long createRawContactWithName(Account account) { 155 return createRawContactWithName("John", "Doe", account); 156 } 157 158 protected long createRawContactWithName(String firstName, String lastName) { 159 return createRawContactWithName(firstName, lastName, null); 160 } 161 162 protected long createRawContactWithName(String firstName, String lastName, Account account) { 163 long rawContactId = createRawContact(account); 164 insertStructuredName(rawContactId, firstName, lastName); 165 return rawContactId; 166 } 167 168 protected Uri setCallerIsSyncAdapter(Uri uri, Account account) { 169 if (account == null) { 170 return uri; 171 } 172 final Uri.Builder builder = uri.buildUpon(); 173 builder.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, account.name); 174 builder.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type); 175 builder.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true"); 176 return builder.build(); 177 } 178 179 protected long createRawContact(Account account, String... extras) { 180 ContentValues values = new ContentValues(); 181 extrasVarArgsToValues(values, extras); 182 final Uri uri = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, account); 183 Uri contactUri = mResolver.insert(uri, values); 184 return ContentUris.parseId(contactUri); 185 } 186 187 protected int updateItem(Uri uri, long id, String... extras) { 188 Uri itemUri = ContentUris.withAppendedId(uri, id); 189 return updateItem(itemUri, extras); 190 } 191 192 protected int updateItem(Uri uri, String... extras) { 193 ContentValues values = new ContentValues(); 194 extrasVarArgsToValues(values, extras); 195 return mResolver.update(uri, values, null, null); 196 } 197 198 private static void extrasVarArgsToValues(ContentValues values, String... extras) { 199 for (int i = 0; i < extras.length; ) { 200 values.put(extras[i], extras[i + 1]); 201 i += 2; 202 } 203 } 204 205 protected long createGroup(Account account, String sourceId, String title) { 206 return createGroup(account, sourceId, title, 1, false, false); 207 } 208 209 protected long createGroup(Account account, String sourceId, String title, int visible) { 210 return createGroup(account, sourceId, title, visible, false, false); 211 } 212 213 protected long createAutoAddGroup(Account account) { 214 return createGroup(account, "auto", "auto", 215 0 /* visible */, true /* auto-add */, false /* fav */); 216 } 217 218 protected long createGroup(Account account, String sourceId, String title, 219 int visible, boolean autoAdd, boolean favorite) { 220 ContentValues values = new ContentValues(); 221 values.put(Groups.SOURCE_ID, sourceId); 222 values.put(Groups.TITLE, title); 223 values.put(Groups.GROUP_VISIBLE, visible); 224 values.put(Groups.AUTO_ADD, autoAdd ? 1 : 0); 225 values.put(Groups.FAVORITES, favorite ? 1 : 0); 226 final Uri uri = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account); 227 return ContentUris.parseId(mResolver.insert(uri, values)); 228 } 229 230 protected void createSettings(Account account, String shouldSync, String ungroupedVisible) { 231 ContentValues values = new ContentValues(); 232 values.put(Settings.ACCOUNT_NAME, account.name); 233 values.put(Settings.ACCOUNT_TYPE, account.type); 234 values.put(Settings.SHOULD_SYNC, shouldSync); 235 values.put(Settings.UNGROUPED_VISIBLE, ungroupedVisible); 236 mResolver.insert(Settings.CONTENT_URI, values); 237 } 238 239 protected Uri insertStructuredName(long rawContactId, String givenName, String familyName) { 240 ContentValues values = new ContentValues(); 241 StringBuilder sb = new StringBuilder(); 242 if (givenName != null) { 243 sb.append(givenName); 244 } 245 if (givenName != null && familyName != null) { 246 sb.append(" "); 247 } 248 if (familyName != null) { 249 sb.append(familyName); 250 } 251 values.put(StructuredName.DISPLAY_NAME, sb.toString()); 252 values.put(StructuredName.GIVEN_NAME, givenName); 253 values.put(StructuredName.FAMILY_NAME, familyName); 254 255 return insertStructuredName(rawContactId, values); 256 } 257 258 protected Uri insertStructuredName(long rawContactId, ContentValues values) { 259 values.put(Data.RAW_CONTACT_ID, rawContactId); 260 values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 261 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 262 return resultUri; 263 } 264 265 protected Uri insertOrganization(long rawContactId, ContentValues values) { 266 return insertOrganization(rawContactId, values, false); 267 } 268 269 protected Uri insertOrganization(long rawContactId, ContentValues values, boolean primary) { 270 values.put(Data.RAW_CONTACT_ID, rawContactId); 271 values.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); 272 values.put(Organization.TYPE, Organization.TYPE_WORK); 273 if (primary) { 274 values.put(Data.IS_PRIMARY, 1); 275 } 276 277 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 278 return resultUri; 279 } 280 281 protected Uri insertPhoneNumber(long rawContactId, String phoneNumber) { 282 return insertPhoneNumber(rawContactId, phoneNumber, false); 283 } 284 285 protected Uri insertPhoneNumber(long rawContactId, String phoneNumber, boolean primary) { 286 ContentValues values = new ContentValues(); 287 values.put(Data.RAW_CONTACT_ID, rawContactId); 288 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 289 values.put(Phone.NUMBER, phoneNumber); 290 values.put(Phone.TYPE, Phone.TYPE_HOME); 291 if (primary) { 292 values.put(Data.IS_PRIMARY, 1); 293 } 294 295 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 296 return resultUri; 297 } 298 299 protected Uri insertEmail(long rawContactId, String email) { 300 return insertEmail(rawContactId, email, false); 301 } 302 303 protected Uri insertEmail(long rawContactId, String email, boolean primary) { 304 return insertEmail(rawContactId, email, primary, Email.TYPE_HOME, null); 305 } 306 307 protected Uri insertEmail(long rawContactId, String email, boolean primary, int type, 308 String label) { 309 ContentValues values = new ContentValues(); 310 values.put(Data.RAW_CONTACT_ID, rawContactId); 311 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 312 values.put(Email.DATA, email); 313 values.put(Email.TYPE, type); 314 values.put(Email.LABEL, label); 315 if (primary) { 316 values.put(Data.IS_PRIMARY, 1); 317 } 318 319 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 320 return resultUri; 321 } 322 323 protected Uri insertNickname(long rawContactId, String nickname) { 324 ContentValues values = new ContentValues(); 325 values.put(Data.RAW_CONTACT_ID, rawContactId); 326 values.put(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE); 327 values.put(Nickname.NAME, nickname); 328 values.put(Nickname.TYPE, Nickname.TYPE_OTHER_NAME); 329 330 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 331 return resultUri; 332 } 333 334 protected Uri insertPostalAddress(long rawContactId, String formattedAddress) { 335 ContentValues values = new ContentValues(); 336 values.put(Data.RAW_CONTACT_ID, rawContactId); 337 values.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); 338 values.put(StructuredPostal.FORMATTED_ADDRESS, formattedAddress); 339 340 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 341 return resultUri; 342 } 343 344 protected Uri insertPostalAddress(long rawContactId, ContentValues values) { 345 values.put(Data.RAW_CONTACT_ID, rawContactId); 346 values.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); 347 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 348 return resultUri; 349 } 350 351 protected Uri insertPhoto(long rawContactId) { 352 ContentValues values = new ContentValues(); 353 values.put(Data.RAW_CONTACT_ID, rawContactId); 354 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 355 values.put(Photo.PHOTO, loadTestPhoto()); 356 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 357 return resultUri; 358 } 359 360 protected Uri insertGroupMembership(long rawContactId, String sourceId) { 361 ContentValues values = new ContentValues(); 362 values.put(Data.RAW_CONTACT_ID, rawContactId); 363 values.put(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); 364 values.put(GroupMembership.GROUP_SOURCE_ID, sourceId); 365 return mResolver.insert(Data.CONTENT_URI, values); 366 } 367 368 protected Uri insertGroupMembership(long rawContactId, Long groupId) { 369 ContentValues values = new ContentValues(); 370 values.put(Data.RAW_CONTACT_ID, rawContactId); 371 values.put(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); 372 values.put(GroupMembership.GROUP_ROW_ID, groupId); 373 return mResolver.insert(Data.CONTENT_URI, values); 374 } 375 376 public void removeGroupMemberships(long rawContactId) { 377 mResolver.delete(Data.CONTENT_URI, 378 Data.MIMETYPE + "=? AND " + GroupMembership.RAW_CONTACT_ID + "=?", 379 new String[] { GroupMembership.CONTENT_ITEM_TYPE, String.valueOf(rawContactId) }); 380 } 381 382 protected Uri insertStatusUpdate(int protocol, String customProtocol, String handle, 383 int presence, String status, int chatMode) { 384 return insertStatusUpdate(protocol, customProtocol, handle, presence, status, 0, chatMode); 385 } 386 387 protected Uri insertStatusUpdate(int protocol, String customProtocol, String handle, 388 int presence, String status, long timestamp, int chatMode) { 389 ContentValues values = new ContentValues(); 390 values.put(StatusUpdates.PROTOCOL, protocol); 391 values.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 392 values.put(StatusUpdates.IM_HANDLE, handle); 393 return insertStatusUpdate(values, presence, status, timestamp, chatMode); 394 } 395 396 protected Uri insertStatusUpdate( 397 long dataId, int presence, String status, long timestamp, int chatMode) { 398 ContentValues values = new ContentValues(); 399 values.put(StatusUpdates.DATA_ID, dataId); 400 return insertStatusUpdate(values, presence, status, timestamp, chatMode); 401 } 402 403 private Uri insertStatusUpdate( 404 ContentValues values, int presence, String status, long timestamp, int chatMode) { 405 if (presence != 0) { 406 values.put(StatusUpdates.PRESENCE, presence); 407 values.put(StatusUpdates.CHAT_CAPABILITY, chatMode); 408 } 409 if (status != null) { 410 values.put(StatusUpdates.STATUS, status); 411 } 412 if (timestamp != 0) { 413 values.put(StatusUpdates.STATUS_TIMESTAMP, timestamp); 414 } 415 416 Uri resultUri = mResolver.insert(StatusUpdates.CONTENT_URI, values); 417 return resultUri; 418 } 419 420 protected Uri insertImHandle(long rawContactId, int protocol, String customProtocol, 421 String handle) { 422 ContentValues values = new ContentValues(); 423 values.put(Data.RAW_CONTACT_ID, rawContactId); 424 values.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); 425 values.put(Im.PROTOCOL, protocol); 426 values.put(Im.CUSTOM_PROTOCOL, customProtocol); 427 values.put(Im.DATA, handle); 428 values.put(Im.TYPE, Im.TYPE_HOME); 429 430 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 431 return resultUri; 432 } 433 434 protected Uri insertEvent(long rawContactId, int type, String date) { 435 ContentValues values = new ContentValues(); 436 values.put(Data.RAW_CONTACT_ID, rawContactId); 437 values.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE); 438 values.put(Event.TYPE, type); 439 values.put(Event.START_DATE, date); 440 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 441 return resultUri; 442 } 443 444 protected Uri insertNote(long rawContactId, String note) { 445 ContentValues values = new ContentValues(); 446 values.put(Data.RAW_CONTACT_ID, rawContactId); 447 values.put(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE); 448 values.put(Note.NOTE, note); 449 Uri resultUri = mResolver.insert(Data.CONTENT_URI, values); 450 return resultUri; 451 } 452 453 protected void setContactAccount(long rawContactId, String accountType, String accountName) { 454 ContentValues values = new ContentValues(); 455 values.put(RawContacts.ACCOUNT_TYPE, accountType); 456 values.put(RawContacts.ACCOUNT_NAME, accountName); 457 458 mResolver.update(ContentUris.withAppendedId( 459 RawContacts.CONTENT_URI, rawContactId), values, null, null); 460 } 461 462 protected void setAggregationException(int type, long rawContactId1, long rawContactId2) { 463 ContentValues values = new ContentValues(); 464 values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 465 values.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 466 values.put(AggregationExceptions.TYPE, type); 467 assertEquals(1, mResolver.update(AggregationExceptions.CONTENT_URI, values, null, null)); 468 } 469 470 protected Cursor queryRawContact(long rawContactId) { 471 return mResolver.query(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 472 null, null, null, null); 473 } 474 475 protected Cursor queryContact(long contactId) { 476 return mResolver.query(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 477 null, null, null, null); 478 } 479 480 protected Cursor queryContact(long contactId, String[] projection) { 481 return mResolver.query(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 482 projection, null, null, null); 483 } 484 485 protected Uri getContactUriForRawContact(long rawContactId) { 486 return ContentUris.withAppendedId(Contacts.CONTENT_URI, queryContactId(rawContactId)); 487 } 488 489 protected long queryContactId(long rawContactId) { 490 Cursor c = queryRawContact(rawContactId); 491 assertTrue(c.moveToFirst()); 492 long contactId = c.getLong(c.getColumnIndex(RawContacts.CONTACT_ID)); 493 c.close(); 494 return contactId; 495 } 496 497 protected long queryPhotoId(long contactId) { 498 Cursor c = queryContact(contactId); 499 assertTrue(c.moveToFirst()); 500 long photoId = c.getInt(c.getColumnIndex(Contacts.PHOTO_ID)); 501 c.close(); 502 return photoId; 503 } 504 505 protected boolean queryRawContactIsStarred(long rawContactId) { 506 Cursor c = queryRawContact(rawContactId); 507 try { 508 assertTrue(c.moveToFirst()); 509 return c.getLong(c.getColumnIndex(RawContacts.STARRED)) != 0; 510 } finally { 511 c.close(); 512 } 513 } 514 515 protected String queryDisplayName(long contactId) { 516 Cursor c = queryContact(contactId); 517 assertTrue(c.moveToFirst()); 518 String displayName = c.getString(c.getColumnIndex(Contacts.DISPLAY_NAME)); 519 c.close(); 520 return displayName; 521 } 522 523 protected String queryLookupKey(long contactId) { 524 Cursor c = queryContact(contactId); 525 assertTrue(c.moveToFirst()); 526 String lookupKey = c.getString(c.getColumnIndex(Contacts.LOOKUP_KEY)); 527 c.close(); 528 return lookupKey; 529 } 530 531 protected void assertAggregated(long rawContactId1, long rawContactId2) { 532 long contactId1 = queryContactId(rawContactId1); 533 long contactId2 = queryContactId(rawContactId2); 534 assertTrue(contactId1 == contactId2); 535 } 536 537 protected void assertAggregated(long rawContactId1, long rawContactId2, 538 String expectedDisplayName) { 539 long contactId1 = queryContactId(rawContactId1); 540 long contactId2 = queryContactId(rawContactId2); 541 assertTrue(contactId1 == contactId2); 542 543 String displayName = queryDisplayName(contactId1); 544 assertEquals(expectedDisplayName, displayName); 545 } 546 547 protected void assertNotAggregated(long rawContactId1, long rawContactId2) { 548 long contactId1 = queryContactId(rawContactId1); 549 long contactId2 = queryContactId(rawContactId2); 550 assertTrue(contactId1 != contactId2); 551 } 552 553 protected void assertStructuredName(long rawContactId, String prefix, String givenName, 554 String middleName, String familyName, String suffix) { 555 Uri uri = Uri.withAppendedPath( 556 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 557 RawContacts.Data.CONTENT_DIRECTORY); 558 559 final String[] projection = new String[] { 560 StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 561 StructuredName.FAMILY_NAME, StructuredName.SUFFIX 562 }; 563 564 Cursor c = mResolver.query(uri, projection, Data.MIMETYPE + "='" 565 + StructuredName.CONTENT_ITEM_TYPE + "'", null, null); 566 567 assertTrue(c.moveToFirst()); 568 assertEquals(prefix, c.getString(0)); 569 assertEquals(givenName, c.getString(1)); 570 assertEquals(middleName, c.getString(2)); 571 assertEquals(familyName, c.getString(3)); 572 assertEquals(suffix, c.getString(4)); 573 c.close(); 574 } 575 576 protected long assertSingleGroup(Long rowId, Account account, String sourceId, String title) { 577 Cursor c = mResolver.query(Groups.CONTENT_URI, null, null, null, null); 578 try { 579 assertTrue(c.moveToNext()); 580 long actualRowId = assertGroup(c, rowId, account, sourceId, title); 581 assertFalse(c.moveToNext()); 582 return actualRowId; 583 } finally { 584 c.close(); 585 } 586 } 587 588 protected long assertSingleGroupMembership(Long rowId, Long rawContactId, Long groupRowId, 589 String sourceId) { 590 Cursor c = mResolver.query(ContactsContract.Data.CONTENT_URI, null, null, null, null); 591 try { 592 assertTrue(c.moveToNext()); 593 long actualRowId = assertGroupMembership(c, rowId, rawContactId, groupRowId, sourceId); 594 assertFalse(c.moveToNext()); 595 return actualRowId; 596 } finally { 597 c.close(); 598 } 599 } 600 601 protected long assertGroupMembership(Cursor c, Long rowId, Long rawContactId, Long groupRowId, 602 String sourceId) { 603 assertNullOrEquals(c, rowId, Data._ID); 604 assertNullOrEquals(c, rawContactId, GroupMembership.RAW_CONTACT_ID); 605 assertNullOrEquals(c, groupRowId, GroupMembership.GROUP_ROW_ID); 606 assertNullOrEquals(c, sourceId, GroupMembership.GROUP_SOURCE_ID); 607 return c.getLong(c.getColumnIndexOrThrow("_id")); 608 } 609 610 protected long assertGroup(Cursor c, Long rowId, Account account, String sourceId, String title) { 611 assertNullOrEquals(c, rowId, Groups._ID); 612 assertNullOrEquals(c, account); 613 assertNullOrEquals(c, sourceId, Groups.SOURCE_ID); 614 assertNullOrEquals(c, title, Groups.TITLE); 615 return c.getLong(c.getColumnIndexOrThrow("_id")); 616 } 617 618 private void assertNullOrEquals(Cursor c, Account account) { 619 if (account == NO_ACCOUNT) { 620 return; 621 } 622 if (account == null) { 623 assertTrue(c.isNull(c.getColumnIndexOrThrow(Groups.ACCOUNT_NAME))); 624 assertTrue(c.isNull(c.getColumnIndexOrThrow(Groups.ACCOUNT_TYPE))); 625 } else { 626 assertEquals(account.name, c.getString(c.getColumnIndexOrThrow(Groups.ACCOUNT_NAME))); 627 assertEquals(account.type, c.getString(c.getColumnIndexOrThrow(Groups.ACCOUNT_TYPE))); 628 } 629 } 630 631 private void assertNullOrEquals(Cursor c, Long value, String columnName) { 632 if (value != NO_LONG) { 633 if (value == null) assertTrue(c.isNull(c.getColumnIndexOrThrow(columnName))); 634 else assertEquals((long) value, c.getLong(c.getColumnIndexOrThrow(columnName))); 635 } 636 } 637 638 private void assertNullOrEquals(Cursor c, String value, String columnName) { 639 if (value != NO_STRING) { 640 if (value == null) assertTrue(c.isNull(c.getColumnIndexOrThrow(columnName))); 641 else assertEquals(value, c.getString(c.getColumnIndexOrThrow(columnName))); 642 } 643 } 644 645 protected void assertDataRow(ContentValues actual, String expectedMimetype, 646 Object... expectedArguments) { 647 assertEquals(actual.toString(), expectedMimetype, actual.getAsString(Data.MIMETYPE)); 648 for (int i = 0; i < expectedArguments.length; i += 2) { 649 String columnName = (String) expectedArguments[i]; 650 Object expectedValue = expectedArguments[i + 1]; 651 if (expectedValue instanceof Uri) { 652 expectedValue = ContentUris.parseId((Uri) expectedValue); 653 } 654 if (expectedValue == null) { 655 assertNull(actual.toString(), actual.get(columnName)); 656 } 657 if (expectedValue instanceof Long) { 658 assertEquals("mismatch at " + columnName + " from " + actual.toString(), 659 expectedValue, actual.getAsLong(columnName)); 660 } else if (expectedValue instanceof Integer) { 661 assertEquals("mismatch at " + columnName + " from " + actual.toString(), 662 expectedValue, actual.getAsInteger(columnName)); 663 } else if (expectedValue instanceof String) { 664 assertEquals("mismatch at " + columnName + " from " + actual.toString(), 665 expectedValue, actual.getAsString(columnName)); 666 } else { 667 assertEquals("mismatch at " + columnName + " from " + actual.toString(), 668 expectedValue, actual.get(columnName)); 669 } 670 } 671 } 672 673 protected void assertNoRowsAndClose(Cursor c) { 674 try { 675 assertFalse(c.moveToNext()); 676 } finally { 677 c.close(); 678 } 679 } 680 681 protected static class IdComparator implements Comparator<ContentValues> { 682 public int compare(ContentValues o1, ContentValues o2) { 683 long id1 = o1.getAsLong(ContactsContract.Data._ID); 684 long id2 = o2.getAsLong(ContactsContract.Data._ID); 685 if (id1 == id2) return 0; 686 return (id1 < id2) ? -1 : 1; 687 } 688 } 689 690 protected ContentValues[] asSortedContentValuesArray( 691 ArrayList<Entity.NamedContentValues> subValues) { 692 ContentValues[] result = new ContentValues[subValues.size()]; 693 int i = 0; 694 for (Entity.NamedContentValues subValue : subValues) { 695 result[i] = subValue.values; 696 i++; 697 } 698 Arrays.sort(result, new IdComparator()); 699 return result; 700 } 701 702 protected void assertDirty(Uri uri, boolean state) { 703 Cursor c = mResolver.query(uri, new String[]{"dirty"}, null, null, null); 704 assertTrue(c.moveToNext()); 705 assertEquals(state, c.getLong(0) != 0); 706 assertFalse(c.moveToNext()); 707 c.close(); 708 } 709 710 protected long getVersion(Uri uri) { 711 Cursor c = mResolver.query(uri, new String[]{"version"}, null, null, null); 712 assertTrue(c.moveToNext()); 713 long version = c.getLong(0); 714 assertFalse(c.moveToNext()); 715 c.close(); 716 return version; 717 } 718 719 protected void clearDirty(Uri uri) { 720 ContentValues values = new ContentValues(); 721 values.put("dirty", 0); 722 mResolver.update(uri, values, null, null); 723 } 724 725 protected void storeValue(Uri contentUri, long id, String column, String value) { 726 storeValue(ContentUris.withAppendedId(contentUri, id), column, value); 727 } 728 729 protected void storeValue(Uri contentUri, String column, String value) { 730 ContentValues values = new ContentValues(); 731 values.put(column, value); 732 733 mResolver.update(contentUri, values, null, null); 734 } 735 736 protected void storeValue(Uri contentUri, long id, String column, long value) { 737 storeValue(ContentUris.withAppendedId(contentUri, id), column, value); 738 } 739 740 protected void storeValue(Uri contentUri, String column, long value) { 741 ContentValues values = new ContentValues(); 742 values.put(column, value); 743 744 mResolver.update(contentUri, values, null, null); 745 } 746 747 protected void assertStoredValue(Uri contentUri, long id, String column, Object expectedValue) { 748 assertStoredValue(ContentUris.withAppendedId(contentUri, id), column, expectedValue); 749 } 750 751 protected void assertStoredValue(Uri rowUri, String column, Object expectedValue) { 752 String value = getStoredValue(rowUri, column); 753 if (expectedValue == null) { 754 assertNull("Column value " + column, value); 755 } else { 756 assertEquals("Column value " + column, String.valueOf(expectedValue), value); 757 } 758 } 759 760 protected void assertStoredValue(Uri rowUri, String selection, String[] selectionArgs, 761 String column, Object expectedValue) { 762 String value = getStoredValue(rowUri, selection, selectionArgs, column); 763 if (expectedValue == null) { 764 assertNull("Column value " + column, value); 765 } else { 766 assertEquals("Column value " + column, String.valueOf(expectedValue), value); 767 } 768 } 769 770 protected String getStoredValue(Uri rowUri, String column) { 771 return getStoredValue(rowUri, null, null, column); 772 } 773 774 protected String getStoredValue(Uri uri, String selection, String[] selectionArgs, 775 String column) { 776 String value = null; 777 Cursor c = mResolver.query(uri, new String[] { column }, selection, selectionArgs, null); 778 try { 779 assertEquals("Record count", 1, c.getCount()); 780 781 if (c.moveToFirst()) { 782 value = c.getString(c.getColumnIndex(column)); 783 } 784 } finally { 785 c.close(); 786 } 787 return value; 788 } 789 790 protected void assertStoredValues(Uri rowUri, ContentValues expectedValues) { 791 assertStoredValues(rowUri, null, null, expectedValues); 792 } 793 794 protected void assertStoredValues(Uri rowUri, ContentValues[] expectedValues) { 795 assertStoredValues(rowUri, null, null, expectedValues); 796 } 797 798 protected void assertStoredValues(Uri rowUri, String selection, String[] selectionArgs, 799 ContentValues expectedValues) { 800 Cursor c = mResolver.query(rowUri, null, selection, selectionArgs, null); 801 try { 802 assertEquals("Record count", 1, c.getCount()); 803 c.moveToFirst(); 804 assertCursorValues(c, expectedValues); 805 } finally { 806 c.close(); 807 } 808 } 809 810 protected void assertStoredValuesWithProjection(Uri rowUri, ContentValues expectedValues) { 811 Cursor c = mResolver.query(rowUri, buildProjection(expectedValues), null, null, null); 812 try { 813 assertEquals("Record count", 1, c.getCount()); 814 c.moveToFirst(); 815 assertCursorValues(c, expectedValues); 816 } finally { 817 c.close(); 818 } 819 } 820 821 protected void assertStoredValues( 822 Uri rowUri, String selection, String[] selectionArgs, ContentValues[] expectedValues) { 823 Cursor c = mResolver.query(rowUri, null, selection, selectionArgs, null); 824 try { 825 assertEquals("Record count", expectedValues.length, c.getCount()); 826 assertCursorValues(c, expectedValues); 827 } finally { 828 c.close(); 829 } 830 } 831 832 protected void assertStoredValuesOrderly(Uri rowUri, ContentValues[] expectedValues) { 833 assertStoredValuesOrderly(rowUri, null, null, expectedValues); 834 } 835 836 protected void assertStoredValuesOrderly(Uri rowUri, String selection, 837 String[] selectionArgs, ContentValues[] expectedValues) { 838 Cursor c = mResolver.query(rowUri, null, selection, selectionArgs, null); 839 try { 840 assertEquals("Record count", expectedValues.length, c.getCount()); 841 assertCursorValuesOrderly(c, expectedValues); 842 } finally { 843 c.close(); 844 } 845 } 846 847 /** 848 * Constructs a selection (where clause) out of all supplied values, uses it 849 * to query the provider and verifies that a single row is returned and it 850 * has the same values as requested. 851 */ 852 protected void assertSelection(Uri uri, ContentValues values, String idColumn, long id) { 853 assertSelection(uri, values, idColumn, id, null); 854 } 855 856 public void assertSelectionWithProjection(Uri uri, ContentValues values, String idColumn, 857 long id) { 858 assertSelection(uri, values, idColumn, id, buildProjection(values)); 859 } 860 861 private void assertSelection(Uri uri, ContentValues values, String idColumn, long id, 862 String[] projection) { 863 StringBuilder sb = new StringBuilder(); 864 ArrayList<String> selectionArgs = new ArrayList<String>(values.size()); 865 if (idColumn != null) { 866 sb.append(idColumn).append("=").append(id); 867 } 868 Set<Map.Entry<String, Object>> entries = values.valueSet(); 869 for (Map.Entry<String, Object> entry : entries) { 870 String column = entry.getKey(); 871 Object value = entry.getValue(); 872 if (sb.length() != 0) { 873 sb.append(" AND "); 874 } 875 sb.append(column); 876 if (value == null) { 877 sb.append(" IS NULL"); 878 } else { 879 sb.append("=?"); 880 selectionArgs.add(String.valueOf(value)); 881 } 882 } 883 884 Cursor c = mResolver.query(uri, projection, sb.toString(), selectionArgs.toArray(new String[0]), 885 null); 886 try { 887 assertEquals("Record count", 1, c.getCount()); 888 c.moveToFirst(); 889 assertCursorValues(c, values); 890 } finally { 891 c.close(); 892 } 893 } 894 895 protected void assertCursorValue(Cursor cursor, String column, Object expectedValue) { 896 String actualValue = cursor.getString(cursor.getColumnIndex(column)); 897 assertEquals("Column " + column, String.valueOf(expectedValue), 898 String.valueOf(actualValue)); 899 } 900 901 protected void assertCursorValues(Cursor cursor, ContentValues expectedValues) { 902 StringBuilder message = new StringBuilder(); 903 boolean result = equalsWithExpectedValues(cursor, expectedValues, message); 904 assertTrue(message.toString(), result); 905 } 906 907 protected void assertCursorValues(Cursor cursor, ContentValues[] expectedValues) { 908 StringBuilder message = new StringBuilder(); 909 for (ContentValues v : expectedValues) { 910 boolean found = false; 911 cursor.moveToPosition(-1); 912 while (cursor.moveToNext()) { 913 found = equalsWithExpectedValues(cursor, v, message); 914 if (found) { 915 break; 916 } 917 } 918 assertTrue("Expected values can not be found " + v + message.toString(), found); 919 } 920 } 921 922 protected void assertCursorValuesOrderly(Cursor cursor, ContentValues[] expectedValues) { 923 StringBuilder message = new StringBuilder(); 924 cursor.moveToPosition(-1); 925 for (ContentValues v : expectedValues) { 926 assertTrue(cursor.moveToNext()); 927 assertTrue("ContentValues didn't match " + v + message.toString(), 928 equalsWithExpectedValues(cursor, v, message)); 929 } 930 } 931 932 private boolean equalsWithExpectedValues(Cursor cursor, ContentValues expectedValues, 933 StringBuilder msgBuffer) { 934 Set<Map.Entry<String, Object>> entries = expectedValues.valueSet(); 935 for (Map.Entry<String, Object> entry : entries) { 936 String column = entry.getKey(); 937 int index = cursor.getColumnIndex(column); 938 if (index == -1) { 939 msgBuffer.append("No such column: ").append(column); 940 return false; 941 } 942 Object expectedValue = expectedValues.get(column); 943 String value; 944 if (expectedValue instanceof byte[]) { 945 expectedValue = Hex.encodeHex((byte[])expectedValue, false); 946 value = Hex.encodeHex(cursor.getBlob(index), false); 947 } else { 948 expectedValue = expectedValues.getAsString(column); 949 value = cursor.getString(index); 950 } 951 if (expectedValue != null && !expectedValue.equals(value) || value != null 952 && !value.equals(expectedValue)) { 953 msgBuffer 954 .append("Column value ") 955 .append(column) 956 .append(" expected <") 957 .append(expectedValue) 958 .append(">, but was <") 959 .append(value) 960 .append('>'); 961 return false; 962 } 963 } 964 return true; 965 } 966 967 private String[] buildProjection(ContentValues values) { 968 String[] projection = new String[values.size()]; 969 Iterator<Entry<String, Object>> iter = values.valueSet().iterator(); 970 for (int i = 0; i < projection.length; i++) { 971 projection[i] = iter.next().getKey(); 972 } 973 return projection; 974 } 975 976 protected int getCount(Uri uri, String selection, String[] selectionArgs) { 977 Cursor c = mResolver.query(uri, null, selection, selectionArgs, null); 978 try { 979 return c.getCount(); 980 } finally { 981 c.close(); 982 } 983 } 984 985 protected byte[] loadTestPhoto() { 986 if (mTestPhoto == null) { 987 final Resources resources = getContext().getResources(); 988 InputStream is = resources 989 .openRawResource(com.android.internal.R.drawable.ic_contact_picture); 990 ByteArrayOutputStream os = new ByteArrayOutputStream(); 991 byte[] buffer = new byte[1000]; 992 int count; 993 try { 994 while ((count = is.read(buffer)) != -1) { 995 os.write(buffer, 0, count); 996 } 997 } catch (IOException e) { 998 throw new RuntimeException(e); 999 } 1000 mTestPhoto = os.toByteArray(); 1001 } 1002 return mTestPhoto; 1003 } 1004 1005 public static void dump(ContentResolver resolver, boolean aggregatedOnly) { 1006 String[] projection = new String[] { 1007 Contacts._ID, 1008 Contacts.DISPLAY_NAME 1009 }; 1010 String selection = null; 1011 if (aggregatedOnly) { 1012 selection = Contacts._ID 1013 + " IN (SELECT contact_id" + 1014 " FROM raw_contacts GROUP BY contact_id HAVING count(*) > 1)"; 1015 } 1016 1017 Cursor c = resolver.query(Contacts.CONTENT_URI, projection, selection, null, 1018 Contacts.DISPLAY_NAME); 1019 while(c.moveToNext()) { 1020 long contactId = c.getLong(0); 1021 Log.i("Contact ", String.format("%5d %s", contactId, c.getString(1))); 1022 dumpRawContacts(resolver, contactId); 1023 Log.i(" ", "."); 1024 } 1025 c.close(); 1026 } 1027 1028 private static void dumpRawContacts(ContentResolver resolver, long contactId) { 1029 String[] projection = new String[] { 1030 RawContacts._ID, 1031 }; 1032 Cursor c = resolver.query(RawContacts.CONTENT_URI, projection, RawContacts.CONTACT_ID + "=" 1033 + contactId, null, null); 1034 while(c.moveToNext()) { 1035 long rawContactId = c.getLong(0); 1036 Log.i("RawContact", String.format(" %-5d", rawContactId)); 1037 dumpData(resolver, rawContactId); 1038 } 1039 c.close(); 1040 } 1041 1042 private static void dumpData(ContentResolver resolver, long rawContactId) { 1043 String[] projection = new String[] { 1044 Data.MIMETYPE, 1045 Data.DATA1, 1046 Data.DATA2, 1047 Data.DATA3, 1048 }; 1049 Cursor c = resolver.query(Data.CONTENT_URI, projection, Data.RAW_CONTACT_ID + "=" 1050 + rawContactId, null, Data.MIMETYPE); 1051 while(c.moveToNext()) { 1052 String mimetype = c.getString(0); 1053 if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) { 1054 Log.i("Photo ", ""); 1055 } else { 1056 mimetype = mimetype.substring(mimetype.indexOf('/') + 1); 1057 Log.i("Data ", String.format(" %-10s %s,%s,%s", mimetype, 1058 c.getString(1), c.getString(2), c.getString(3))); 1059 } 1060 } 1061 c.close(); 1062 } 1063 1064 protected void assertNetworkNotified(boolean expected) { 1065 assertEquals(expected, (getContactsProvider()).isNetworkNotified()); 1066 } 1067 1068 protected void assertProjection(Uri uri, String[] expectedProjection) { 1069 Cursor cursor = mResolver.query(uri, null, "0", null, null); 1070 String[] actualProjection = cursor.getColumnNames(); 1071 MoreAsserts.assertEquals("Incorrect projection for URI: " + uri, 1072 Sets.newHashSet(expectedProjection), Sets.newHashSet(actualProjection)); 1073 cursor.close(); 1074 } 1075 1076 /** 1077 * A contact in the database, and the attributes used to create it. Construct using 1078 * {@link GoldenContactBuilder#build()}. 1079 */ 1080 public final class GoldenContact { 1081 1082 private final long rawContactId; 1083 1084 private final long contactId; 1085 1086 private final String givenName; 1087 1088 private final String familyName; 1089 1090 private final String nickname; 1091 1092 private final byte[] photo; 1093 1094 private final String company; 1095 1096 private final String title; 1097 1098 private final String phone; 1099 1100 private final String email; 1101 1102 private GoldenContact(GoldenContactBuilder builder, long rawContactId, long contactId) { 1103 1104 this.rawContactId = rawContactId; 1105 this.contactId = contactId; 1106 givenName = builder.givenName; 1107 familyName = builder.familyName; 1108 nickname = builder.nickname; 1109 photo = builder.photo; 1110 company = builder.company; 1111 title = builder.title; 1112 phone = builder.phone; 1113 email = builder.email; 1114 } 1115 1116 public void delete() { 1117 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1118 mResolver.delete(rawContactUri, null, null); 1119 } 1120 1121 /** 1122 * Returns the index of the contact in table "raw_contacts" 1123 */ 1124 public long getRawContactId() { 1125 return rawContactId; 1126 } 1127 1128 /** 1129 * Returns the index of the contact in table "contacts" 1130 */ 1131 public long getContactId() { 1132 return contactId; 1133 } 1134 1135 /** 1136 * Returns the lookup key for the contact. 1137 */ 1138 public String getLookupKey() { 1139 return queryLookupKey(contactId); 1140 } 1141 1142 /** 1143 * Returns the contact's given name. 1144 */ 1145 public String getGivenName() { 1146 return givenName; 1147 } 1148 1149 /** 1150 * Returns the contact's family name. 1151 */ 1152 public String getFamilyName() { 1153 return familyName; 1154 } 1155 1156 /** 1157 * Returns the contact's nickname. 1158 */ 1159 public String getNickname() { 1160 return nickname; 1161 } 1162 1163 /** 1164 * Return's the contact's photo 1165 */ 1166 public byte[] getPhoto() { 1167 return photo; 1168 } 1169 1170 /** 1171 * Return's the company at which the contact works. 1172 */ 1173 public String getCompany() { 1174 return company; 1175 } 1176 1177 /** 1178 * Returns the contact's job title. 1179 */ 1180 public String getTitle() { 1181 return title; 1182 } 1183 1184 /** 1185 * Returns the contact's phone number 1186 */ 1187 public String getPhone() { 1188 return phone; 1189 } 1190 1191 /** 1192 * Returns the contact's email address 1193 */ 1194 public String getEmail() { 1195 return email; 1196 } 1197 } 1198 1199 /** 1200 * Builds {@link GoldenContact} objects. Unspecified boolean objects default to false. 1201 * Unspecified String objects default to null. 1202 */ 1203 public final class GoldenContactBuilder { 1204 1205 private String givenName; 1206 1207 private String familyName; 1208 1209 private String nickname; 1210 1211 private byte[] photo; 1212 1213 private String company; 1214 1215 private String title; 1216 1217 private String phone; 1218 1219 private String email; 1220 1221 /** 1222 * The contact's given and family names. 1223 * 1224 * TODO(dplotnikov): inline, or should we require them to set both names if they set either? 1225 */ 1226 public GoldenContactBuilder name(String givenName, String familyName) { 1227 return givenName(givenName).familyName(familyName); 1228 } 1229 1230 /** 1231 * The contact's given name. 1232 */ 1233 public GoldenContactBuilder givenName(String value) { 1234 givenName = value; 1235 return this; 1236 } 1237 1238 /** 1239 * The contact's family name. 1240 */ 1241 public GoldenContactBuilder familyName(String value) { 1242 familyName = value; 1243 return this; 1244 } 1245 1246 /** 1247 * The contact's nickname. 1248 */ 1249 public GoldenContactBuilder nickname(String value) { 1250 nickname = value; 1251 return this; 1252 } 1253 1254 /** 1255 * The contact's photo. 1256 */ 1257 public GoldenContactBuilder photo(byte[] value) { 1258 photo = value; 1259 return this; 1260 } 1261 1262 /** 1263 * The company at which the contact works. 1264 */ 1265 public GoldenContactBuilder company(String value) { 1266 company = value; 1267 return this; 1268 } 1269 1270 /** 1271 * The contact's job title. 1272 */ 1273 public GoldenContactBuilder title(String value) { 1274 title = value; 1275 return this; 1276 } 1277 1278 /** 1279 * The contact's phone number. 1280 */ 1281 public GoldenContactBuilder phone(String value) { 1282 phone = value; 1283 return this; 1284 } 1285 1286 /** 1287 * The contact's email address; also sets their IM status to {@link StatusUpdates#OFFLINE} 1288 * with a presence of "Coding for Android". 1289 */ 1290 public GoldenContactBuilder email(String value) { 1291 email = value; 1292 return this; 1293 } 1294 1295 /** 1296 * Builds the {@link GoldenContact} specified by this builder. 1297 */ 1298 public GoldenContact build() { 1299 1300 final long groupId = createGroup(mAccount, "gsid1", "title1"); 1301 1302 long rawContactId = createRawContact(); 1303 insertGroupMembership(rawContactId, groupId); 1304 1305 if (givenName != null || familyName != null) { 1306 insertStructuredName(rawContactId, givenName, familyName); 1307 } 1308 if (nickname != null) { 1309 insertNickname(rawContactId, nickname); 1310 } 1311 if (photo != null) { 1312 insertPhoto(rawContactId); 1313 } 1314 if (company != null || title != null) { 1315 insertOrganization(rawContactId); 1316 } 1317 if (email != null) { 1318 insertEmail(rawContactId); 1319 } 1320 if (phone != null) { 1321 insertPhone(rawContactId); 1322 } 1323 1324 long contactId = queryContactId(rawContactId); 1325 1326 return new GoldenContact(this, rawContactId, contactId); 1327 } 1328 1329 private void insertPhoto(long rawContactId) { 1330 ContentValues values = new ContentValues(); 1331 values.put(Data.RAW_CONTACT_ID, rawContactId); 1332 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 1333 values.put(Photo.PHOTO, photo); 1334 mResolver.insert(Data.CONTENT_URI, values); 1335 } 1336 1337 private void insertOrganization(long rawContactId) { 1338 1339 ContentValues values = new ContentValues(); 1340 values.put(Data.RAW_CONTACT_ID, rawContactId); 1341 values.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); 1342 values.put(Organization.TYPE, Organization.TYPE_WORK); 1343 if (company != null) { 1344 values.put(Organization.COMPANY, company); 1345 } 1346 if (title != null) { 1347 values.put(Organization.TITLE, title); 1348 } 1349 mResolver.insert(Data.CONTENT_URI, values); 1350 } 1351 1352 private void insertEmail(long rawContactId) { 1353 1354 ContentValues values = new ContentValues(); 1355 values.put(Data.RAW_CONTACT_ID, rawContactId); 1356 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 1357 values.put(Email.TYPE, Email.TYPE_WORK); 1358 values.put(Email.DATA, "foo@acme.com"); 1359 mResolver.insert(Data.CONTENT_URI, values); 1360 1361 int protocol = Im.PROTOCOL_GOOGLE_TALK; 1362 1363 values.clear(); 1364 values.put(StatusUpdates.PROTOCOL, protocol); 1365 values.put(StatusUpdates.IM_HANDLE, email); 1366 values.put(StatusUpdates.IM_ACCOUNT, "foo"); 1367 values.put(StatusUpdates.PRESENCE_STATUS, StatusUpdates.OFFLINE); 1368 values.put(StatusUpdates.CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 1369 values.put(StatusUpdates.PRESENCE_CUSTOM_STATUS, "Coding for Android"); 1370 mResolver.insert(StatusUpdates.CONTENT_URI, values); 1371 } 1372 1373 private void insertPhone(long rawContactId) { 1374 ContentValues values = new ContentValues(); 1375 values.put(Data.RAW_CONTACT_ID, rawContactId); 1376 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 1377 values.put(Data.IS_PRIMARY, 1); 1378 values.put(Phone.TYPE, Phone.TYPE_HOME); 1379 values.put(Phone.NUMBER, phone); 1380 mResolver.insert(Data.CONTENT_URI, values); 1381 } 1382 } 1383} 1384