Contacts.java revision b798689749c64baba81f02e10cf2157c747d6b46
1/* 2 * Copyright (C) 2006 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 android.provider; 18 19import com.android.internal.R; 20 21import android.content.ContentResolver; 22import android.content.ContentUris; 23import android.content.ContentValues; 24import android.content.Context; 25import android.content.Intent; 26import android.database.Cursor; 27import android.graphics.Bitmap; 28import android.graphics.BitmapFactory; 29import android.net.Uri; 30import android.text.TextUtils; 31import android.util.Log; 32import android.widget.ImageView; 33 34import java.io.ByteArrayInputStream; 35import java.io.InputStream; 36 37/** 38 * The Contacts provider stores all information about contacts. 39 */ 40public class Contacts { 41 private static final String TAG = "Contacts"; 42 43 public static final String AUTHORITY = "contacts"; 44 45 /** 46 * The content:// style URL for this provider 47 */ 48 public static final Uri CONTENT_URI = 49 Uri.parse("content://" + AUTHORITY); 50 51 /** Signifies an email address row that is stored in the ContactMethods table */ 52 public static final int KIND_EMAIL = 1; 53 /** Signifies a postal address row that is stored in the ContactMethods table */ 54 public static final int KIND_POSTAL = 2; 55 /** Signifies an IM address row that is stored in the ContactMethods table */ 56 public static final int KIND_IM = 3; 57 /** Signifies an Organization row that is stored in the Organizations table */ 58 public static final int KIND_ORGANIZATION = 4; 59 /** Signifies an Phone row that is stored in the Phones table */ 60 public static final int KIND_PHONE = 5; 61 62 /** 63 * no public constructor since this is a utility class 64 */ 65 private Contacts() {} 66 67 /** 68 * Columns from the Settings table that other columns join into themselves. 69 */ 70 public interface SettingsColumns { 71 /** 72 * The _SYNC_ACCOUNT to which this setting corresponds. This may be null. 73 * <P>Type: TEXT</P> 74 */ 75 public static final String _SYNC_ACCOUNT = "_sync_account"; 76 77 /** 78 * The key of this setting. 79 * <P>Type: TEXT</P> 80 */ 81 public static final String KEY = "key"; 82 83 /** 84 * The value of this setting. 85 * <P>Type: TEXT</P> 86 */ 87 public static final String VALUE = "value"; 88 } 89 90 /** 91 * The settings over all of the people 92 */ 93 public static final class Settings implements BaseColumns, SettingsColumns { 94 /** 95 * no public constructor since this is a utility class 96 */ 97 private Settings() {} 98 99 /** 100 * The content:// style URL for this table 101 */ 102 public static final Uri CONTENT_URI = 103 Uri.parse("content://contacts/settings"); 104 105 /** 106 * The directory twig for this sub-table 107 */ 108 public static final String CONTENT_DIRECTORY = "settings"; 109 110 /** 111 * The default sort order for this table 112 */ 113 public static final String DEFAULT_SORT_ORDER = "key ASC"; 114 115 /** 116 * A setting that is used to indicate if we should sync down all groups for the 117 * specified account. For this setting the _SYNC_ACCOUNT column must be set. 118 * If this isn't set then we will only sync the groups whose SHOULD_SYNC column 119 * is set to true. 120 * <p> 121 * This is a boolean setting. It is true if it is set and it is anything other than the 122 * emptry string or "0". 123 */ 124 public static final String SYNC_EVERYTHING = "syncEverything"; 125 126 public static String getSetting(ContentResolver cr, String account, String key) { 127 // For now we only support a single account and the UI doesn't know what 128 // the account name is, so we're using a global setting for SYNC_EVERYTHING. 129 // Some day when we add multiple accounts to the UI this should honor the account 130 // that was asked for. 131 String selectString; 132 String[] selectArgs; 133 if (false) { 134 selectString = (account == null) 135 ? "_sync_account is null AND key=?" 136 : "_sync_account=? AND key=?"; 137 selectArgs = (account == null) 138 ? new String[]{key} 139 : new String[]{account, key}; 140 } else { 141 selectString = "key=?"; 142 selectArgs = new String[] {key}; 143 } 144 Cursor cursor = cr.query(Settings.CONTENT_URI, new String[]{VALUE}, 145 selectString, selectArgs, null); 146 try { 147 if (!cursor.moveToNext()) return null; 148 return cursor.getString(0); 149 } finally { 150 cursor.close(); 151 } 152 } 153 154 public static void setSetting(ContentResolver cr, String account, String key, 155 String value) { 156 ContentValues values = new ContentValues(); 157 // For now we only support a single account and the UI doesn't know what 158 // the account name is, so we're using a global setting for SYNC_EVERYTHING. 159 // Some day when we add multiple accounts to the UI this should honor the account 160 // that was asked for. 161 //values.put(_SYNC_ACCOUNT, account); 162 values.put(KEY, key); 163 values.put(VALUE, value); 164 cr.update(Settings.CONTENT_URI, values, null, null); 165 } 166 } 167 168 /** 169 * Columns from the People table that other tables join into themselves. 170 */ 171 public interface PeopleColumns { 172 /** 173 * The person's name. 174 * <P>Type: TEXT</P> 175 */ 176 public static final String NAME = "name"; 177 178 /** 179 * Phonetic equivalent of the person's name, in a locale-dependent 180 * character set (e.g. hiragana for Japanese). 181 * Used for pronunciation and/or collation in some languages. 182 * <p>Type: TEXT</P> 183 */ 184 public static final String PHONETIC_NAME = "phonetic_name"; 185 186 /** 187 * The display name. If name is not null name, else if number is not null number, 188 * else if email is not null email. 189 * <P>Type: TEXT</P> 190 */ 191 public static final String DISPLAY_NAME = "display_name"; 192 193 /** 194 * Notes about the person. 195 * <P>Type: TEXT</P> 196 */ 197 public static final String NOTES = "notes"; 198 199 /** 200 * The number of times a person has been contacted 201 * <P>Type: INTEGER</P> 202 */ 203 public static final String TIMES_CONTACTED = "times_contacted"; 204 205 /** 206 * The last time a person was contacted. 207 * <P>Type: INTEGER</P> 208 */ 209 public static final String LAST_TIME_CONTACTED = "last_time_contacted"; 210 211 /** 212 * A custom ringtone associated with a person. Not always present. 213 * <P>Type: TEXT (URI to the ringtone)</P> 214 */ 215 public static final String CUSTOM_RINGTONE = "custom_ringtone"; 216 217 /** 218 * Whether the person should always be sent to voicemail. Not always 219 * present. 220 * <P>Type: INTEGER (0 for false, 1 for true)</P> 221 */ 222 public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; 223 224 /** 225 * Is the contact starred? 226 * <P>Type: INTEGER (boolean)</P> 227 */ 228 public static final String STARRED = "starred"; 229 230 /** 231 * The server version of the photo 232 * <P>Type: TEXT (the version number portion of the photo URI)</P> 233 */ 234 public static final String PHOTO_VERSION = "photo_version"; 235 } 236 237 /** 238 * This table contains people. 239 */ 240 public static final class People implements BaseColumns, SyncConstValue, PeopleColumns, 241 PhonesColumns, PresenceColumns { 242 /** 243 * no public constructor since this is a utility class 244 */ 245 private People() {} 246 247 /** 248 * The content:// style URL for this table 249 */ 250 public static final Uri CONTENT_URI = 251 Uri.parse("content://contacts/people"); 252 253 /** 254 * The content:// style URL for filtering people by name. The filter 255 * argument should be passed as an additional path segment after this URI. 256 */ 257 public static final Uri CONTENT_FILTER_URI = 258 Uri.parse("content://contacts/people/filter"); 259 260 /** 261 * The content:// style URL for the table that holds the deleted 262 * contacts. 263 */ 264 public static final Uri DELETED_CONTENT_URI = 265 Uri.parse("content://contacts/deleted_people"); 266 267 /** 268 * The MIME type of {@link #CONTENT_URI} providing a directory of 269 * people. 270 */ 271 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person"; 272 273 /** 274 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 275 * person. 276 */ 277 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person"; 278 279 /** 280 * The default sort order for this table 281 */ 282 public static final String DEFAULT_SORT_ORDER = People.NAME + " ASC"; 283 284 /** 285 * The ID of the persons preferred phone number. 286 * <P>Type: INTEGER (foreign key to phones table on the _ID field)</P> 287 */ 288 public static final String PRIMARY_PHONE_ID = "primary_phone"; 289 290 /** 291 * The ID of the persons preferred email. 292 * <P>Type: INTEGER (foreign key to contact_methods table on the 293 * _ID field)</P> 294 */ 295 public static final String PRIMARY_EMAIL_ID = "primary_email"; 296 297 /** 298 * The ID of the persons preferred organization. 299 * <P>Type: INTEGER (foreign key to organizations table on the 300 * _ID field)</P> 301 */ 302 public static final String PRIMARY_ORGANIZATION_ID = "primary_organization"; 303 304 /** 305 * Mark a person as having been contacted. 306 * 307 * @param resolver the ContentResolver to use 308 * @param personId the person who was contacted 309 */ 310 public static void markAsContacted(ContentResolver resolver, long personId) { 311 Uri uri = ContentUris.withAppendedId(CONTENT_URI, personId); 312 uri = Uri.withAppendedPath(uri, "update_contact_time"); 313 ContentValues values = new ContentValues(); 314 // There is a trigger in place that will update TIMES_CONTACTED when 315 // LAST_TIME_CONTACTED is modified. 316 values.put(LAST_TIME_CONTACTED, System.currentTimeMillis()); 317 resolver.update(uri, values, null, null); 318 } 319 320 /** 321 * Adds a person to the My Contacts group. 322 * 323 * @param resolver the resolver to use 324 * @param personId the person to add to the group 325 * @return the URI of the group membership row 326 * @throws IllegalStateException if the My Contacts group can't be found 327 */ 328 public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) { 329 long groupId = 0; 330 Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION, 331 Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null); 332 if (groupsCursor != null) { 333 try { 334 if (groupsCursor.moveToFirst()) { 335 groupId = groupsCursor.getLong(0); 336 } 337 } finally { 338 groupsCursor.close(); 339 } 340 } 341 342 if (groupId == 0) { 343 throw new IllegalStateException("Failed to find the My Contacts group"); 344 } 345 346 return addToGroup(resolver, personId, groupId); 347 } 348 349 /** 350 * Adds a person to a group referred to by name. 351 * 352 * @param resolver the resolver to use 353 * @param personId the person to add to the group 354 * @param groupName the name of the group to add the contact to 355 * @return the URI of the group membership row 356 * @throws IllegalStateException if the group can't be found 357 */ 358 public static Uri addToGroup(ContentResolver resolver, long personId, String groupName) { 359 long groupId = 0; 360 Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION, 361 Groups.NAME + "=?", new String[] { groupName }, null); 362 if (groupsCursor != null) { 363 try { 364 if (groupsCursor.moveToFirst()) { 365 groupId = groupsCursor.getLong(0); 366 } 367 } finally { 368 groupsCursor.close(); 369 } 370 } 371 372 if (groupId == 0) { 373 throw new IllegalStateException("Failed to find the My Contacts group"); 374 } 375 376 return addToGroup(resolver, personId, groupId); 377 } 378 379 /** 380 * Adds a person to a group. 381 * 382 * @param resolver the resolver to use 383 * @param personId the person to add to the group 384 * @param groupId the group to add the person to 385 * @return the URI of the group membership row 386 */ 387 public static Uri addToGroup(ContentResolver resolver, long personId, long groupId) { 388 ContentValues values = new ContentValues(); 389 values.put(GroupMembership.PERSON_ID, personId); 390 values.put(GroupMembership.GROUP_ID, groupId); 391 return resolver.insert(GroupMembership.CONTENT_URI, values); 392 } 393 394 private static final String[] GROUPS_PROJECTION = new String[] { 395 Groups._ID, 396 }; 397 398 /** 399 * Creates a new contacts and adds it to the "My Contacts" group. 400 * 401 * @param resolver the ContentResolver to use 402 * @param values the values to use when creating the contact 403 * @return the URI of the contact, or null if the operation fails 404 */ 405 public static Uri createPersonInMyContactsGroup(ContentResolver resolver, 406 ContentValues values) { 407 408 Uri contactUri = resolver.insert(People.CONTENT_URI, values); 409 if (contactUri == null) { 410 Log.e(TAG, "Failed to create the contact"); 411 return null; 412 } 413 414 if (addToMyContactsGroup(resolver, ContentUris.parseId(contactUri)) == null) { 415 resolver.delete(contactUri, null, null); 416 return null; 417 } 418 return contactUri; 419 } 420 421 public static Cursor queryGroups(ContentResolver resolver, long person) { 422 return resolver.query(GroupMembership.CONTENT_URI, null, "person=?", 423 new String[]{String.valueOf(person)}, Groups.DEFAULT_SORT_ORDER); 424 } 425 426 /** 427 * Set the photo for this person. data may be null 428 * @param cr the ContentResolver to use 429 * @param person the Uri of the person whose photo is to be updated 430 * @param data the byte[] that represents the photo 431 */ 432 public static void setPhotoData(ContentResolver cr, Uri person, byte[] data) { 433 Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY); 434 ContentValues values = new ContentValues(); 435 values.put(Photos.DATA, data); 436 cr.update(photoUri, values, null, null); 437 } 438 439 /** 440 * Opens an InputStream for the person's photo and returns the photo as a Bitmap. 441 * If the person's photo isn't present returns the placeholderImageResource instead. 442 * @param person the person whose photo should be used 443 */ 444 public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri person) { 445 Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY); 446 Cursor cursor = cr.query(photoUri, new String[]{Photos.DATA}, null, null, null); 447 try { 448 if (!cursor.moveToNext()) { 449 return null; 450 } 451 byte[] data = cursor.getBlob(0); 452 if (data == null) { 453 return null; 454 } 455 return new ByteArrayInputStream(data); 456 } finally { 457 cursor.close(); 458 } 459 } 460 461 /** 462 * Opens an InputStream for the person's photo and returns the photo as a Bitmap. 463 * If the person's photo isn't present returns the placeholderImageResource instead. 464 * @param context the Context 465 * @param person the person whose photo should be used 466 * @param placeholderImageResource the image resource to use if the person doesn't 467 * have a photo 468 * @param options the decoding options, can be set to null 469 */ 470 public static Bitmap loadContactPhoto(Context context, Uri person, 471 int placeholderImageResource, BitmapFactory.Options options) { 472 if (person == null) { 473 return loadPlaceholderPhoto(placeholderImageResource, context, options); 474 } 475 476 InputStream stream = openContactPhotoInputStream(context.getContentResolver(), person); 477 Bitmap bm = stream != null ? BitmapFactory.decodeStream(stream, null, options) : null; 478 if (bm == null) { 479 bm = loadPlaceholderPhoto(placeholderImageResource, context, options); 480 } 481 return bm; 482 } 483 484 private static Bitmap loadPlaceholderPhoto(int placeholderImageResource, Context context, 485 BitmapFactory.Options options) { 486 if (placeholderImageResource == 0) { 487 return null; 488 } 489 return BitmapFactory.decodeResource(context.getResources(), 490 placeholderImageResource, options); 491 } 492 493 /** 494 * A sub directory of a single person that contains all of their Phones. 495 */ 496 public static final class Phones implements BaseColumns, PhonesColumns, 497 PeopleColumns { 498 /** 499 * no public constructor since this is a utility class 500 */ 501 private Phones() {} 502 503 /** 504 * The directory twig for this sub-table 505 */ 506 public static final String CONTENT_DIRECTORY = "phones"; 507 508 /** 509 * The default sort order for this table 510 */ 511 public static final String DEFAULT_SORT_ORDER = "number ASC"; 512 } 513 514 /** 515 * A subdirectory of a single person that contains all of their 516 * ContactMethods. 517 */ 518 public static final class ContactMethods 519 implements BaseColumns, ContactMethodsColumns, PeopleColumns { 520 /** 521 * no public constructor since this is a utility class 522 */ 523 private ContactMethods() {} 524 525 /** 526 * The directory twig for this sub-table 527 */ 528 public static final String CONTENT_DIRECTORY = "contact_methods"; 529 530 /** 531 * The default sort order for this table 532 */ 533 public static final String DEFAULT_SORT_ORDER = "data ASC"; 534 } 535 536 /** 537 * The extensions for a person 538 */ 539 public static class Extensions implements BaseColumns, ExtensionsColumns { 540 /** 541 * no public constructor since this is a utility class 542 */ 543 private Extensions() {} 544 545 /** 546 * The directory twig for this sub-table 547 */ 548 public static final String CONTENT_DIRECTORY = "extensions"; 549 550 /** 551 * The default sort order for this table 552 */ 553 public static final String DEFAULT_SORT_ORDER = "name ASC"; 554 555 /** 556 * The ID of the person this phone number is assigned to. 557 * <P>Type: INTEGER (long)</P> 558 */ 559 public static final String PERSON_ID = "person"; 560 } 561 } 562 563 /** 564 * Columns from the groups table. 565 */ 566 public interface GroupsColumns { 567 /** 568 * The group name. 569 * <P>Type: TEXT</P> 570 */ 571 public static final String NAME = "name"; 572 573 /** 574 * Notes about the group. 575 * <P>Type: TEXT</P> 576 */ 577 public static final String NOTES = "notes"; 578 579 /** 580 * Whether this group should be synced if the SYNC_EVERYTHING settings is false 581 * for this group's account. 582 * <P>Type: INTEGER (boolean)</P> 583 */ 584 public static final String SHOULD_SYNC = "should_sync"; 585 586 /** 587 * The ID of this group if it is a System Group, null otherwise. 588 * <P>Type: TEXT</P> 589 */ 590 public static final String SYSTEM_ID = "system_id"; 591 } 592 593 /** 594 * This table contains the groups for an account. 595 */ 596 public static final class Groups 597 implements BaseColumns, SyncConstValue, GroupsColumns { 598 /** 599 * no public constructor since this is a utility class 600 */ 601 private Groups() {} 602 603 /** 604 * The content:// style URL for this table 605 */ 606 public static final Uri CONTENT_URI = 607 Uri.parse("content://contacts/groups"); 608 609 /** 610 * The content:// style URL for the table that holds the deleted 611 * groups. 612 */ 613 public static final Uri DELETED_CONTENT_URI = 614 Uri.parse("content://contacts/deleted_groups"); 615 616 /** 617 * The MIME type of {@link #CONTENT_URI} providing a directory of 618 * groups. 619 */ 620 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroup"; 621 622 /** 623 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 624 * group. 625 */ 626 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroup"; 627 628 /** 629 * The default sort order for this table 630 */ 631 public static final String DEFAULT_SORT_ORDER = NAME + " ASC"; 632 633 /** 634 * 635 */ 636 public static final String GROUP_ANDROID_STARRED = "Starred in Android"; 637 638 /** 639 * The "My Contacts" system group. 640 */ 641 public static final String GROUP_MY_CONTACTS = "Contacts"; 642 } 643 644 /** 645 * Columns from the Phones table that other columns join into themselves. 646 */ 647 public interface PhonesColumns { 648 /** 649 * The type of the the phone number. 650 * <P>Type: INTEGER (one of the constants below)</P> 651 */ 652 public static final String TYPE = "type"; 653 654 public static final int TYPE_CUSTOM = 0; 655 public static final int TYPE_HOME = 1; 656 public static final int TYPE_MOBILE = 2; 657 public static final int TYPE_WORK = 3; 658 public static final int TYPE_FAX_WORK = 4; 659 public static final int TYPE_FAX_HOME = 5; 660 public static final int TYPE_PAGER = 6; 661 public static final int TYPE_OTHER = 7; 662 663 /** 664 * The user provided label for the phone number, only used if TYPE is TYPE_CUSTOM. 665 * <P>Type: TEXT</P> 666 */ 667 public static final String LABEL = "label"; 668 669 /** 670 * The phone number as the user entered it. 671 * <P>Type: TEXT</P> 672 */ 673 public static final String NUMBER = "number"; 674 675 /** 676 * The normalized phone number 677 * <P>Type: TEXT</P> 678 */ 679 public static final String NUMBER_KEY = "number_key"; 680 681 /** 682 * Whether this is the primary phone number 683 * <P>Type: INTEGER (if set, non-0 means true)</P> 684 */ 685 public static final String ISPRIMARY = "isprimary"; 686 } 687 688 /** 689 * This table stores phone numbers and a reference to the person that the 690 * contact method belongs to. Phone numbers are stored separately from 691 * other contact methods to make caller ID lookup more efficient. 692 */ 693 public static final class Phones 694 implements BaseColumns, PhonesColumns, PeopleColumns { 695 /** 696 * no public constructor since this is a utility class 697 */ 698 private Phones() {} 699 700 public static final CharSequence getDisplayLabel(Context context, int type, 701 CharSequence label, CharSequence[] labelArray) { 702 CharSequence display = ""; 703 704 if (type != People.Phones.TYPE_CUSTOM) { 705 CharSequence[] labels = labelArray != null? labelArray 706 : context.getResources().getTextArray( 707 com.android.internal.R.array.phoneTypes); 708 try { 709 display = labels[type - 1]; 710 } catch (ArrayIndexOutOfBoundsException e) { 711 display = labels[People.Phones.TYPE_HOME - 1]; 712 } 713 } else { 714 if (!TextUtils.isEmpty(label)) { 715 display = label; 716 } 717 } 718 return display; 719 } 720 721 public static final CharSequence getDisplayLabel(Context context, int type, 722 CharSequence label) { 723 return getDisplayLabel(context, type, label, null); 724 } 725 726 /** 727 * The content:// style URL for this table 728 */ 729 public static final Uri CONTENT_URI = 730 Uri.parse("content://contacts/phones"); 731 732 /** 733 * The content:// style URL for filtering phone numbers 734 */ 735 public static final Uri CONTENT_FILTER_URL = 736 Uri.parse("content://contacts/phones/filter"); 737 738 /** 739 * The MIME type of {@link #CONTENT_URI} providing a directory of 740 * phones. 741 */ 742 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone"; 743 744 /** 745 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 746 * phone. 747 */ 748 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone"; 749 750 /** 751 * The default sort order for this table 752 */ 753 public static final String DEFAULT_SORT_ORDER = "name ASC"; 754 755 /** 756 * The ID of the person this phone number is assigned to. 757 * <P>Type: INTEGER (long)</P> 758 */ 759 public static final String PERSON_ID = "person"; 760 } 761 762 public static final class GroupMembership implements BaseColumns, GroupsColumns { 763 /** 764 * no public constructor since this is a utility class 765 */ 766 private GroupMembership() {} 767 768 /** 769 * The content:// style URL for this table 770 */ 771 public static final Uri CONTENT_URI = 772 Uri.parse("content://contacts/groupmembership"); 773 774 /** 775 * The content:// style URL for this table 776 */ 777 public static final Uri RAW_CONTENT_URI = 778 Uri.parse("content://contacts/groupmembershipraw"); 779 780 /** 781 * The directory twig for this sub-table 782 */ 783 public static final String CONTENT_DIRECTORY = "groupmembership"; 784 /** 785 * The MIME type of {@link #CONTENT_URI} providing a directory of all 786 * person groups. 787 */ 788 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroupmembership"; 789 790 /** 791 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 792 * person group. 793 */ 794 public static final String CONTENT_ITEM_TYPE = 795 "vnd.android.cursor.item/contactsgroupmembership"; 796 797 /** 798 * The default sort order for this table 799 */ 800 public static final String DEFAULT_SORT_ORDER = "group_id ASC"; 801 802 /** 803 * The row id of the accounts group. 804 * <P>Type: TEXT</P> 805 */ 806 public static final String GROUP_ID = "group_id"; 807 808 /** 809 * The sync id of the group. 810 * <P>Type: TEXT</P> 811 */ 812 public static final String GROUP_SYNC_ID = "group_sync_id"; 813 814 /** 815 * The account of the group. 816 * <P>Type: TEXT</P> 817 */ 818 public static final String GROUP_SYNC_ACCOUNT = "group_sync_account"; 819 820 /** 821 * The row id of the person. 822 * <P>Type: TEXT</P> 823 */ 824 public static final String PERSON_ID = "person"; 825 } 826 827 /** 828 * Columns from the ContactMethods table that other tables join into 829 * themseleves. 830 */ 831 public interface ContactMethodsColumns { 832 /** 833 * The kind of the the contact method. For example, email address, 834 * postal address, etc. 835 * <P>Type: INTEGER (one of the values below)</P> 836 */ 837 public static final String KIND = "kind"; 838 839 /** 840 * The type of the contact method, must be one of the types below. 841 * <P>Type: INTEGER (one of the values below)</P> 842 */ 843 public static final String TYPE = "type"; 844 public static final int TYPE_CUSTOM = 0; 845 public static final int TYPE_HOME = 1; 846 public static final int TYPE_WORK = 2; 847 public static final int TYPE_OTHER = 3; 848 849 /** 850 * The user defined label for the the contact method. 851 * <P>Type: TEXT</P> 852 */ 853 public static final String LABEL = "label"; 854 855 /** 856 * The data for the contact method. 857 * <P>Type: TEXT</P> 858 */ 859 public static final String DATA = "data"; 860 861 /** 862 * Auxiliary data for the contact method. 863 * <P>Type: TEXT</P> 864 */ 865 public static final String AUX_DATA = "aux_data"; 866 867 /** 868 * Whether this is the primary organization 869 * <P>Type: INTEGER (if set, non-0 means true)</P> 870 */ 871 public static final String ISPRIMARY = "isprimary"; 872 } 873 874 /** 875 * This table stores all non-phone contact methods and a reference to the 876 * person that the contact method belongs to. 877 */ 878 public static final class ContactMethods 879 implements BaseColumns, ContactMethodsColumns, PeopleColumns { 880 /** 881 * The column with latitude data for postal locations 882 * <P>Type: REAL</P> 883 */ 884 public static final String POSTAL_LOCATION_LATITUDE = DATA; 885 886 /** 887 * The column with longitude data for postal locations 888 * <P>Type: REAL</P> 889 */ 890 public static final String POSTAL_LOCATION_LONGITUDE = AUX_DATA; 891 892 /** 893 * The predefined IM protocol types. The protocol can either be non-present, one 894 * of these types, or a free-form string. These cases are encoded in the AUX_DATA 895 * column as: 896 * - null 897 * - pre:<an integer, one of the protocols below> 898 * - custom:<a string> 899 */ 900 public static final int PROTOCOL_AIM = 0; 901 public static final int PROTOCOL_MSN = 1; 902 public static final int PROTOCOL_YAHOO = 2; 903 public static final int PROTOCOL_SKYPE = 3; 904 public static final int PROTOCOL_QQ = 4; 905 public static final int PROTOCOL_GOOGLE_TALK = 5; 906 public static final int PROTOCOL_ICQ = 6; 907 public static final int PROTOCOL_JABBER = 7; 908 909 public static String encodePredefinedImProtocol(int protocol) { 910 return "pre:" + protocol; 911 } 912 913 public static String encodeCustomImProtocol(String protocolString) { 914 return "custom:" + protocolString; 915 } 916 917 public static Object decodeImProtocol(String encodedString) { 918 if (encodedString == null) { 919 return null; 920 } 921 922 if (encodedString.startsWith("pre:")) { 923 return Integer.parseInt(encodedString.substring(4)); 924 } 925 926 if (encodedString.startsWith("custom:")) { 927 return encodedString.substring(7); 928 } 929 930 throw new IllegalArgumentException( 931 "the value is not a valid encoded protocol, " + encodedString); 932 } 933 934 /** 935 * This looks up the provider category defined in 936 * {@link android.provider.Im.ProviderCategories} from the predefined IM protocol id. 937 * This is used for interacting with the IM application. 938 * 939 * @param protocol the protocol ID 940 * @return the provider category the IM app uses for the given protocol, or null if no 941 * provider is defined for the given protocol 942 * @hide 943 */ 944 public static String lookupProviderCategoryFromId(int protocol) { 945 switch (protocol) { 946 case PROTOCOL_GOOGLE_TALK: 947 return Im.ProviderCategories.GTALK; 948 case PROTOCOL_AIM: 949 return Im.ProviderCategories.AIM; 950 case PROTOCOL_MSN: 951 return Im.ProviderCategories.MSN; 952 case PROTOCOL_YAHOO: 953 return Im.ProviderCategories.YAHOO; 954 case PROTOCOL_ICQ: 955 return Im.ProviderCategories.ICQ; 956 } 957 return null; 958 } 959 960 /** 961 * no public constructor since this is a utility class 962 */ 963 private ContactMethods() {} 964 965 public static final CharSequence getDisplayLabel(Context context, int kind, 966 int type, CharSequence label) { 967 CharSequence display = ""; 968 switch (kind) { 969 case KIND_EMAIL: { 970 if (type != People.ContactMethods.TYPE_CUSTOM) { 971 CharSequence[] labels = context.getResources().getTextArray( 972 com.android.internal.R.array.emailAddressTypes); 973 try { 974 display = labels[type - 1]; 975 } catch (ArrayIndexOutOfBoundsException e) { 976 display = labels[ContactMethods.TYPE_HOME - 1]; 977 } 978 } else { 979 if (!TextUtils.isEmpty(label)) { 980 display = label; 981 } 982 } 983 break; 984 } 985 986 case KIND_POSTAL: { 987 if (type != People.ContactMethods.TYPE_CUSTOM) { 988 CharSequence[] labels = context.getResources().getTextArray( 989 com.android.internal.R.array.postalAddressTypes); 990 try { 991 display = labels[type - 1]; 992 } catch (ArrayIndexOutOfBoundsException e) { 993 display = labels[ContactMethods.TYPE_HOME - 1]; 994 } 995 } else { 996 if (!TextUtils.isEmpty(label)) { 997 display = label; 998 } 999 } 1000 break; 1001 } 1002 1003 default: 1004 display = context.getString(R.string.untitled); 1005 } 1006 return display; 1007 } 1008 1009 /** 1010 * Add a longitude and latitude location to a postal address. 1011 * 1012 * @param context the context to use when updating the database 1013 * @param postalId the address to update 1014 * @param latitude the latitude for the address 1015 * @param longitude the longitude for the address 1016 */ 1017 public void addPostalLocation(Context context, long postalId, 1018 double latitude, double longitude) { 1019 final ContentResolver resolver = context.getContentResolver(); 1020 // Insert the location 1021 ContentValues values = new ContentValues(2); 1022 values.put(POSTAL_LOCATION_LATITUDE, latitude); 1023 values.put(POSTAL_LOCATION_LONGITUDE, longitude); 1024 Uri loc = resolver.insert(CONTENT_URI, values); 1025 long locId = ContentUris.parseId(loc); 1026 1027 // Update the postal address 1028 values.clear(); 1029 values.put(AUX_DATA, locId); 1030 resolver.update(ContentUris.withAppendedId(CONTENT_URI, postalId), values, null, null); 1031 } 1032 1033 /** 1034 * The content:// style URL for this table 1035 */ 1036 public static final Uri CONTENT_URI = 1037 Uri.parse("content://contacts/contact_methods"); 1038 1039 /** 1040 * The content:// style URL for sub-directory of e-mail addresses. 1041 */ 1042 public static final Uri CONTENT_EMAIL_URI = 1043 Uri.parse("content://contacts/contact_methods/email"); 1044 1045 /** 1046 * The MIME type of {@link #CONTENT_URI} providing a directory of 1047 * phones. 1048 */ 1049 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact-methods"; 1050 1051 /** 1052 * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\ 1053 * multiple {@link Contacts#KIND_EMAIL} entries. 1054 */ 1055 public static final String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email"; 1056 1057 /** 1058 * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\ 1059 * multiple {@link Contacts#KIND_POSTAL} entries. 1060 */ 1061 public static final String CONTENT_POSTAL_TYPE = "vnd.android.cursor.dir/postal-address"; 1062 1063 /** 1064 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single 1065 * {@link Contacts#KIND_EMAIL} entry. 1066 */ 1067 public static final String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email"; 1068 1069 /** 1070 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single 1071 * {@link Contacts#KIND_POSTAL} entry. 1072 */ 1073 public static final String CONTENT_POSTAL_ITEM_TYPE 1074 = "vnd.android.cursor.item/postal-address"; 1075 1076 /** 1077 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single 1078 * {@link Contacts#KIND_IM} entry. 1079 */ 1080 public static final String CONTENT_IM_ITEM_TYPE = "vnd.android.cursor.item/jabber-im"; 1081 1082 /** 1083 * The default sort order for this table 1084 */ 1085 public static final String DEFAULT_SORT_ORDER = "name ASC"; 1086 1087 /** 1088 * The ID of the person this contact method is assigned to. 1089 * <P>Type: INTEGER (long)</P> 1090 */ 1091 public static final String PERSON_ID = "person"; 1092 } 1093 1094 /** 1095 * The IM presence columns with some contacts specific columns mixed in. 1096 */ 1097 public interface PresenceColumns extends Im.CommonPresenceColumns { 1098 /** 1099 * The IM service the presence is coming from. Formatted using either 1100 * {@link Contacts.ContactMethods#encodePredefinedImProtocol} or 1101 * {@link Contacts.ContactMethods#encodeCustomImProtocol}. 1102 * <P>Type: STRING</P> 1103 */ 1104 public static final String IM_PROTOCOL = "im_protocol"; 1105 1106 /** 1107 * The IM handle the presence item is for. The handle is scoped to 1108 * the {@link #IM_PROTOCOL}. 1109 * <P>Type: STRING</P> 1110 */ 1111 public static final String IM_HANDLE = "im_handle"; 1112 1113 /** 1114 * The IM account for the local user that the presence data came from. 1115 * <P>Type: STRING</P> 1116 */ 1117 public static final String IM_ACCOUNT = "im_account"; 1118 } 1119 1120 /** 1121 * Contains presence information about contacts. 1122 * @hide 1123 */ 1124 public static final class Presence 1125 implements BaseColumns, PresenceColumns, PeopleColumns { 1126 /** 1127 * The content:// style URL for this table 1128 */ 1129 public static final Uri CONTENT_URI = 1130 Uri.parse("content://contacts/presence"); 1131 1132 /** 1133 * The ID of the person this presence item is assigned to. 1134 * <P>Type: INTEGER (long)</P> 1135 */ 1136 public static final String PERSON_ID = "person"; 1137 1138 /** 1139 * Gets the resource ID for the proper presence icon. 1140 * 1141 * @param status the status to get the icon for 1142 * @return the resource ID for the proper presence icon 1143 */ 1144 public static final int getPresenceIconResourceId(int status) { 1145 switch (status) { 1146 case Contacts.People.AVAILABLE: 1147 return com.android.internal.R.drawable.presence_online; 1148 1149 case Contacts.People.IDLE: 1150 case Contacts.People.AWAY: 1151 return com.android.internal.R.drawable.presence_away; 1152 1153 case Contacts.People.DO_NOT_DISTURB: 1154 return com.android.internal.R.drawable.presence_busy; 1155 1156 case Contacts.People.INVISIBLE: 1157 return com.android.internal.R.drawable.presence_invisible; 1158 1159 case Contacts.People.OFFLINE: 1160 default: 1161 return com.android.internal.R.drawable.presence_offline; 1162 } 1163 } 1164 1165 /** 1166 * Sets a presence icon to the proper graphic 1167 * 1168 * @param icon the icon to to set 1169 * @param serverStatus that status 1170 */ 1171 public static final void setPresenceIcon(ImageView icon, int serverStatus) { 1172 icon.setImageResource(getPresenceIconResourceId(serverStatus)); 1173 } 1174 } 1175 1176 /** 1177 * Columns from the Organizations table that other columns join into themselves. 1178 */ 1179 public interface OrganizationColumns { 1180 /** 1181 * The type of the the phone number. 1182 * <P>Type: INTEGER (one of the constants below)</P> 1183 */ 1184 public static final String TYPE = "type"; 1185 1186 public static final int TYPE_CUSTOM = 0; 1187 public static final int TYPE_WORK = 1; 1188 public static final int TYPE_OTHER = 2; 1189 1190 /** 1191 * The user provided label, only used if TYPE is TYPE_CUSTOM. 1192 * <P>Type: TEXT</P> 1193 */ 1194 public static final String LABEL = "label"; 1195 1196 /** 1197 * The name of the company for this organization. 1198 * <P>Type: TEXT</P> 1199 */ 1200 public static final String COMPANY = "company"; 1201 1202 /** 1203 * The title within this organization. 1204 * <P>Type: TEXT</P> 1205 */ 1206 public static final String TITLE = "title"; 1207 1208 /** 1209 * The person this organization is tied to. 1210 * <P>Type: TEXT</P> 1211 */ 1212 public static final String PERSON_ID = "person"; 1213 1214 /** 1215 * Whether this is the primary organization 1216 * <P>Type: INTEGER (if set, non-0 means true)</P> 1217 */ 1218 public static final String ISPRIMARY = "isprimary"; 1219 } 1220 1221 /** 1222 * A sub directory of a single person that contains all of their Phones. 1223 */ 1224 public static final class Organizations implements BaseColumns, OrganizationColumns { 1225 /** 1226 * no public constructor since this is a utility class 1227 */ 1228 private Organizations() {} 1229 1230 public static final CharSequence getDisplayLabel(Context context, int type, 1231 CharSequence label) { 1232 CharSequence display = ""; 1233 1234 if (type != TYPE_CUSTOM) { 1235 CharSequence[] labels = context.getResources().getTextArray( 1236 com.android.internal.R.array.organizationTypes); 1237 try { 1238 display = labels[type - 1]; 1239 } catch (ArrayIndexOutOfBoundsException e) { 1240 display = labels[Organizations.TYPE_WORK - 1]; 1241 } 1242 } else { 1243 if (!TextUtils.isEmpty(label)) { 1244 display = label; 1245 } 1246 } 1247 return display; 1248 } 1249 1250 /** 1251 * The content:// style URL for this table 1252 */ 1253 public static final Uri CONTENT_URI = 1254 Uri.parse("content://contacts/organizations"); 1255 1256 /** 1257 * The directory twig for this sub-table 1258 */ 1259 public static final String CONTENT_DIRECTORY = "organizations"; 1260 1261 /** 1262 * The default sort order for this table 1263 */ 1264 public static final String DEFAULT_SORT_ORDER = "company, title, isprimary ASC"; 1265 } 1266 1267 /** 1268 * Columns from the Photos table that other columns join into themselves. 1269 */ 1270 public interface PhotosColumns { 1271 /** 1272 * The _SYNC_VERSION of the photo that was last downloaded 1273 * <P>Type: TEXT</P> 1274 */ 1275 public static final String LOCAL_VERSION = "local_version"; 1276 1277 /** 1278 * The person this photo is associated with. 1279 * <P>Type: TEXT</P> 1280 */ 1281 public static final String PERSON_ID = "person"; 1282 1283 /** 1284 * non-zero if a download is required and the photo isn't marked as a bad resource. 1285 * You must specify this in the columns in order to use it in the where clause. 1286 * <P>Type: INTEGER(boolean)</P> 1287 */ 1288 public static final String DOWNLOAD_REQUIRED = "download_required"; 1289 1290 /** 1291 * non-zero if this photo is known to exist on the server 1292 * <P>Type: INTEGER(boolean)</P> 1293 */ 1294 public static final String EXISTS_ON_SERVER = "exists_on_server"; 1295 1296 /** 1297 * Contains the description of the upload or download error from 1298 * the previous attempt. If null then the previous attempt succeeded. 1299 * <P>Type: TEXT</P> 1300 */ 1301 public static final String SYNC_ERROR = "sync_error"; 1302 1303 /** 1304 * The image data, or null if there is no image. 1305 * <P>Type: BLOB</P> 1306 */ 1307 public static final String DATA = "data"; 1308 1309 } 1310 1311 /** 1312 * The photos over all of the people 1313 */ 1314 public static final class Photos implements BaseColumns, PhotosColumns, SyncConstValue { 1315 /** 1316 * no public constructor since this is a utility class 1317 */ 1318 private Photos() {} 1319 1320 /** 1321 * The content:// style URL for this table 1322 */ 1323 public static final Uri CONTENT_URI = 1324 Uri.parse("content://contacts/photos"); 1325 1326 /** 1327 * The directory twig for this sub-table 1328 */ 1329 public static final String CONTENT_DIRECTORY = "photo"; 1330 1331 /** 1332 * The default sort order for this table 1333 */ 1334 public static final String DEFAULT_SORT_ORDER = "person ASC"; 1335 } 1336 1337 public interface ExtensionsColumns { 1338 /** 1339 * The name of this extension. May not be null. There may be at most one row for each name. 1340 * <P>Type: TEXT</P> 1341 */ 1342 public static final String NAME = "name"; 1343 1344 /** 1345 * The value of this extension. May not be null. 1346 * <P>Type: TEXT</P> 1347 */ 1348 public static final String VALUE = "value"; 1349 } 1350 1351 /** 1352 * The extensions for a person 1353 */ 1354 public static final class Extensions implements BaseColumns, ExtensionsColumns { 1355 /** 1356 * no public constructor since this is a utility class 1357 */ 1358 private Extensions() {} 1359 1360 /** 1361 * The content:// style URL for this table 1362 */ 1363 public static final Uri CONTENT_URI = 1364 Uri.parse("content://contacts/extensions"); 1365 1366 /** 1367 * The MIME type of {@link #CONTENT_URI} providing a directory of 1368 * phones. 1369 */ 1370 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_extensions"; 1371 1372 /** 1373 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 1374 * phone. 1375 */ 1376 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_extensions"; 1377 /** 1378 * The default sort order for this table 1379 */ 1380 public static final String DEFAULT_SORT_ORDER = "person, name ASC"; 1381 1382 /** 1383 * The ID of the person this phone number is assigned to. 1384 * <P>Type: INTEGER (long)</P> 1385 */ 1386 public static final String PERSON_ID = "person"; 1387 } 1388 1389 /** 1390 * Contains helper classes used to create or manage {@link android.content.Intent Intents} 1391 * that involve contacts. 1392 */ 1393 public static final class Intents { 1394 /** 1395 * This is the intent that is fired when a search suggestion is clicked on. 1396 */ 1397 public static final String SEARCH_SUGGESTION_CLICKED = 1398 "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED"; 1399 1400 /** 1401 * This is the intent that is fired when a search suggestion for dialing a number 1402 * is clicked on. 1403 */ 1404 public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = 1405 "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED"; 1406 1407 /** 1408 * This is the intent that is fired when a search suggestion for creating a contact 1409 * is clicked on. 1410 */ 1411 public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = 1412 "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED"; 1413 1414 /** 1415 * Starts an Activity that lets the user pick a contact to attach an image to. 1416 * After picking the contact it launches the image cropper in face detection mode. 1417 */ 1418 public static final String ATTACH_IMAGE = 1419 "com.android.contacts.action.ATTACH_IMAGE"; 1420 1421 /** 1422 * Intents related to the Contacts app UI. 1423 */ 1424 public static final class UI { 1425 /** 1426 * The action for the default contacts list tab. 1427 */ 1428 public static final String LIST_DEFAULT = 1429 "com.android.contacts.action.LIST_DEFAULT"; 1430 1431 /** 1432 * The action for the contacts list tab. 1433 */ 1434 public static final String LIST_GROUP_ACTION = 1435 "com.android.contacts.action.LIST_GROUP"; 1436 1437 /** 1438 * When in LIST_GROUP_ACTION mode, this is the group to display. 1439 */ 1440 public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP"; 1441 1442 /** 1443 * The action for the all contacts list tab. 1444 */ 1445 public static final String LIST_ALL_CONTACTS_ACTION = 1446 "com.android.contacts.action.LIST_ALL_CONTACTS"; 1447 1448 /** 1449 * The action for the contacts with phone numbers list tab. 1450 */ 1451 public static final String LIST_CONTACTS_WITH_PHONES_ACTION = 1452 "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES"; 1453 1454 /** 1455 * The action for the starred contacts list tab. 1456 */ 1457 public static final String LIST_STARRED_ACTION = 1458 "com.android.contacts.action.LIST_STARRED"; 1459 1460 /** 1461 * The action for the frequent contacts list tab. 1462 */ 1463 public static final String LIST_FREQUENT_ACTION = 1464 "com.android.contacts.action.LIST_FREQUENT"; 1465 1466 /** 1467 * The action for the "strequent" contacts list tab. It first lists the starred 1468 * contacts in alphabetical order and then the frequent contacts in descending 1469 * order of the number of times they have been contacted. 1470 */ 1471 public static final String LIST_STREQUENT_ACTION = 1472 "com.android.contacts.action.LIST_STREQUENT"; 1473 1474 /** 1475 * A key for to be used as an intent extra to set the activity 1476 * title to a custom String value. 1477 */ 1478 public static final String TITLE_EXTRA_KEY = 1479 "com.android.contacts.extra.TITLE_EXTRA"; 1480 1481 /** 1482 * Activity Action: Display a filtered list of contacts 1483 * <p> 1484 * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for 1485 * filtering 1486 * <p> 1487 * Output: Nothing. 1488 */ 1489 public static final String FILTER_CONTACTS_ACTION = 1490 "com.android.contacts.action.FILTER_CONTACTS"; 1491 1492 /** 1493 * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION} 1494 * intents to supply the text on which to filter. 1495 */ 1496 public static final String FILTER_TEXT_EXTRA_KEY = 1497 "com.android.contacts.extra.FILTER_TEXT"; 1498 } 1499 1500 /** 1501 * Convenience class that contains string constants used 1502 * to create contact {@link android.content.Intent Intents}. 1503 */ 1504 public static final class Insert { 1505 /** The action code to use when adding a contact */ 1506 public static final String ACTION = Intent.ACTION_INSERT; 1507 1508 /** 1509 * If present, forces a bypass of quick insert mode. 1510 */ 1511 public static final String FULL_MODE = "full_mode"; 1512 1513 /** 1514 * The extra field for the contact name. 1515 * <P>Type: String</P> 1516 */ 1517 public static final String NAME = "name"; 1518 1519 /** 1520 * The extra field for the contact phonetic name. 1521 * <P>Type: String</P> 1522 */ 1523 public static final String PHONETIC_NAME = "phonetic_name"; 1524 1525 /** 1526 * The extra field for the contact company. 1527 * <P>Type: String</P> 1528 */ 1529 public static final String COMPANY = "company"; 1530 1531 /** 1532 * The extra field for the contact job title. 1533 * <P>Type: String</P> 1534 */ 1535 public static final String JOB_TITLE = "job_title"; 1536 1537 /** 1538 * The extra field for the contact notes. 1539 * <P>Type: String</P> 1540 */ 1541 public static final String NOTES = "notes"; 1542 1543 /** 1544 * The extra field for the contact phone number. 1545 * <P>Type: String</P> 1546 */ 1547 public static final String PHONE = "phone"; 1548 1549 /** 1550 * The extra field for the contact phone number type. 1551 * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns}, 1552 * or a string specifying a custom label.</P> 1553 */ 1554 public static final String PHONE_TYPE = "phone_type"; 1555 1556 /** 1557 * The extra field for the phone isprimary flag. 1558 * <P>Type: boolean</P> 1559 */ 1560 public static final String PHONE_ISPRIMARY = "phone_isprimary"; 1561 1562 /** 1563 * The extra field for an optional second contact phone number. 1564 * <P>Type: String</P> 1565 */ 1566 public static final String SECONDARY_PHONE = "secondary_phone"; 1567 1568 /** 1569 * The extra field for an optional second contact phone number type. 1570 * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns}, 1571 * or a string specifying a custom label.</P> 1572 */ 1573 public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type"; 1574 1575 /** 1576 * The extra field for an optional third contact phone number. 1577 * <P>Type: String</P> 1578 */ 1579 public static final String TERTIARY_PHONE = "tertiary_phone"; 1580 1581 /** 1582 * The extra field for an optional third contact phone number type. 1583 * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns}, 1584 * or a string specifying a custom label.</P> 1585 */ 1586 public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type"; 1587 1588 /** 1589 * The extra field for the contact email address. 1590 * <P>Type: String</P> 1591 */ 1592 public static final String EMAIL = "email"; 1593 1594 /** 1595 * The extra field for the contact email type. 1596 * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} 1597 * or a string specifying a custom label.</P> 1598 */ 1599 public static final String EMAIL_TYPE = "email_type"; 1600 1601 /** 1602 * The extra field for the email isprimary flag. 1603 * <P>Type: boolean</P> 1604 */ 1605 public static final String EMAIL_ISPRIMARY = "email_isprimary"; 1606 1607 /** 1608 * The extra field for an optional second contact email address. 1609 * <P>Type: String</P> 1610 */ 1611 public static final String SECONDARY_EMAIL = "secondary_email"; 1612 1613 /** 1614 * The extra field for an optional second contact email type. 1615 * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} 1616 * or a string specifying a custom label.</P> 1617 */ 1618 public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type"; 1619 1620 /** 1621 * The extra field for an optional third contact email address. 1622 * <P>Type: String</P> 1623 */ 1624 public static final String TERTIARY_EMAIL = "tertiary_email"; 1625 1626 /** 1627 * The extra field for an optional third contact email type. 1628 * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} 1629 * or a string specifying a custom label.</P> 1630 */ 1631 public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type"; 1632 1633 /** 1634 * The extra field for the contact postal address. 1635 * <P>Type: String</P> 1636 */ 1637 public static final String POSTAL = "postal"; 1638 1639 /** 1640 * The extra field for the contact postal address type. 1641 * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} 1642 * or a string specifying a custom label.</P> 1643 */ 1644 public static final String POSTAL_TYPE = "postal_type"; 1645 1646 /** 1647 * The extra field for the postal isprimary flag. 1648 * <P>Type: boolean</P> 1649 */ 1650 public static final String POSTAL_ISPRIMARY = "postal_isprimary"; 1651 1652 /** 1653 * The extra field for an IM handle. 1654 * <P>Type: String</P> 1655 */ 1656 public static final String IM_HANDLE = "im_handle"; 1657 1658 /** 1659 * The extra field for the IM protocol 1660 * <P>Type: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol} 1661 * or {@link Contacts.ContactMethods#encodeCustomImProtocol}.</P> 1662 */ 1663 public static final String IM_PROTOCOL = "im_protocol"; 1664 1665 /** 1666 * The extra field for the IM isprimary flag. 1667 * <P>Type: boolean</P> 1668 */ 1669 public static final String IM_ISPRIMARY = "im_isprimary"; 1670 } 1671 } 1672} 1673