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