ContactsContract.java revision 244327e2097df053b1818c79bcb84ae9e4f3af76
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package android.provider; 18 19import android.accounts.Account; 20import android.content.ContentProviderClient; 21import android.content.ContentProviderOperation; 22import android.content.ContentResolver; 23import android.content.ContentUris; 24import android.content.ContentValues; 25import android.content.Context; 26import android.content.CursorEntityIterator; 27import android.content.Entity; 28import android.content.EntityIterator; 29import android.content.Intent; 30import android.content.res.Resources; 31import android.database.Cursor; 32import android.database.DatabaseUtils; 33import android.database.sqlite.SQLiteException; 34import android.graphics.Rect; 35import android.net.Uri; 36import android.os.RemoteException; 37import android.text.TextUtils; 38import android.util.DisplayMetrics; 39import android.util.Pair; 40import android.view.View; 41 42import java.io.ByteArrayInputStream; 43import java.io.InputStream; 44 45/** 46 * <p> 47 * The contract between the contacts provider and applications. Contains 48 * definitions for the supported URIs and columns. These APIs supersede 49 * {@link Contacts}. 50 * </p> 51 * <h3>Overview</h3> 52 * <p> 53 * ContactsContract defines an extensible database of contact-related 54 * information. Contact information is stored in a three-tier data model: 55 * </p> 56 * <ul> 57 * <li> 58 * The {@link Data} table contains all kinds of personal data: phone numbers, 59 * email addresses etc. The list of data kinds that can be stored in this table 60 * is open-ended. There is a predefined set of common kinds, but any application 61 * can add its own data kinds. 62 * </li> 63 * <li> 64 * A row in the {@link RawContacts} table represents a set of Data describing a 65 * person and associated with a single account (for example, a single Gmail 66 * account). 67 * </li> 68 * <li> 69 * A row in the {@link Contacts} table represents an aggregate of one or more 70 * RawContacts presumably describing the same person. 71 * </li> 72 * </ul> 73 * <p> 74 * Other tables include: 75 * </p> 76 * <ul> 77 * <li> 78 * {@link Groups}, which contains information about raw contact groups - the 79 * current API does not support the notion of groups spanning multiple accounts. 80 * </li> 81 * <li> 82 * {@link StatusUpdates}, which contains social status updates including IM 83 * availability. 84 * </li> 85 * <li> 86 * {@link AggregationExceptions}, which is used for manual aggregation and 87 * disaggregation of raw contacts 88 * </li> 89 * <li> 90 * {@link Settings}, which contains visibility and sync settings for accounts 91 * and groups. 92 * </li> 93 * <li> 94 * {@link SyncState}, which contains free-form data maintained on behalf of sync 95 * adapters 96 * </li> 97 * <li> 98 * {@link PhoneLookup}, which is used for quick caller-ID lookup</li> 99 * </ul> 100 */ 101@SuppressWarnings("unused") 102public final class ContactsContract { 103 /** The authority for the contacts provider */ 104 public static final String AUTHORITY = "com.android.contacts"; 105 /** A content:// style uri to the authority for the contacts provider */ 106 public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); 107 108 /** 109 * An optional insert, update or delete URI parameter that allows the caller 110 * to specify that it is a sync adapter. The default value is false. If true 111 * the dirty flag is not automatically set and the "syncToNetwork" parameter 112 * is set to false when calling 113 * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}. 114 */ 115 public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; 116 117 /** 118 * A query parameter key used to specify the package that is requesting a query. 119 * This is used for restricting data based on package name. 120 * 121 * @hide 122 */ 123 public static final String REQUESTING_PACKAGE_PARAM_KEY = "requesting_package"; 124 125 /** 126 * @hide should be removed when users are updated to refer to SyncState 127 * @deprecated use SyncState instead 128 */ 129 @Deprecated 130 public interface SyncStateColumns extends SyncStateContract.Columns { 131 } 132 133 /** 134 * A table provided for sync adapters to use for storing private sync state data. 135 * 136 * @see SyncStateContract 137 */ 138 public static final class SyncState implements SyncStateContract.Columns { 139 /** 140 * This utility class cannot be instantiated 141 */ 142 private SyncState() {} 143 144 public static final String CONTENT_DIRECTORY = 145 SyncStateContract.Constants.CONTENT_DIRECTORY; 146 147 /** 148 * The content:// style URI for this table 149 */ 150 public static final Uri CONTENT_URI = 151 Uri.withAppendedPath(AUTHORITY_URI, CONTENT_DIRECTORY); 152 153 /** 154 * @see android.provider.SyncStateContract.Helpers#get 155 */ 156 public static byte[] get(ContentProviderClient provider, Account account) 157 throws RemoteException { 158 return SyncStateContract.Helpers.get(provider, CONTENT_URI, account); 159 } 160 161 /** 162 * @see android.provider.SyncStateContract.Helpers#get 163 */ 164 public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account) 165 throws RemoteException { 166 return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account); 167 } 168 169 /** 170 * @see android.provider.SyncStateContract.Helpers#set 171 */ 172 public static void set(ContentProviderClient provider, Account account, byte[] data) 173 throws RemoteException { 174 SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data); 175 } 176 177 /** 178 * @see android.provider.SyncStateContract.Helpers#newSetOperation 179 */ 180 public static ContentProviderOperation newSetOperation(Account account, byte[] data) { 181 return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data); 182 } 183 } 184 185 /** 186 * Generic columns for use by sync adapters. The specific functions of 187 * these columns are private to the sync adapter. Other clients of the API 188 * should not attempt to either read or write this column. 189 * 190 * @see RawContacts 191 * @see Groups 192 */ 193 protected interface BaseSyncColumns { 194 195 /** Generic column for use by sync adapters. */ 196 public static final String SYNC1 = "sync1"; 197 /** Generic column for use by sync adapters. */ 198 public static final String SYNC2 = "sync2"; 199 /** Generic column for use by sync adapters. */ 200 public static final String SYNC3 = "sync3"; 201 /** Generic column for use by sync adapters. */ 202 public static final String SYNC4 = "sync4"; 203 } 204 205 /** 206 * Columns that appear when each row of a table belongs to a specific 207 * account, including sync information that an account may need. 208 * 209 * @see RawContacts 210 * @see Groups 211 */ 212 protected interface SyncColumns extends BaseSyncColumns { 213 /** 214 * The name of the account instance to which this row belongs, which when paired with 215 * {@link #ACCOUNT_TYPE} identifies a specific account. 216 * <P>Type: TEXT</P> 217 */ 218 public static final String ACCOUNT_NAME = "account_name"; 219 220 /** 221 * The type of account to which this row belongs, which when paired with 222 * {@link #ACCOUNT_NAME} identifies a specific account. 223 * <P>Type: TEXT</P> 224 */ 225 public static final String ACCOUNT_TYPE = "account_type"; 226 227 /** 228 * String that uniquely identifies this row to its source account. 229 * <P>Type: TEXT</P> 230 */ 231 public static final String SOURCE_ID = "sourceid"; 232 233 /** 234 * Version number that is updated whenever this row or its related data 235 * changes. 236 * <P>Type: INTEGER</P> 237 */ 238 public static final String VERSION = "version"; 239 240 /** 241 * Flag indicating that {@link #VERSION} has changed, and this row needs 242 * to be synchronized by its owning account. 243 * <P>Type: INTEGER (boolean)</P> 244 */ 245 public static final String DIRTY = "dirty"; 246 } 247 248 /** 249 * Columns of {@link ContactsContract.Contacts} that track the user's 250 * preferences for, or interactions with, the contact. 251 * 252 * @see Contacts 253 * @see RawContacts 254 * @see ContactsContract.Data 255 * @see PhoneLookup 256 * @see ContactsContract.Contacts.AggregationSuggestions 257 */ 258 protected interface ContactOptionsColumns { 259 /** 260 * The number of times a contact has been contacted 261 * <P>Type: INTEGER</P> 262 */ 263 public static final String TIMES_CONTACTED = "times_contacted"; 264 265 /** 266 * The last time a contact was contacted. 267 * <P>Type: INTEGER</P> 268 */ 269 public static final String LAST_TIME_CONTACTED = "last_time_contacted"; 270 271 /** 272 * Is the contact starred? 273 * <P>Type: INTEGER (boolean)</P> 274 */ 275 public static final String STARRED = "starred"; 276 277 /** 278 * URI for a custom ringtone associated with the contact. If null or missing, 279 * the default ringtone is used. 280 * <P>Type: TEXT (URI to the ringtone)</P> 281 */ 282 public static final String CUSTOM_RINGTONE = "custom_ringtone"; 283 284 /** 285 * Whether the contact should always be sent to voicemail. If missing, 286 * defaults to false. 287 * <P>Type: INTEGER (0 for false, 1 for true)</P> 288 */ 289 public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; 290 } 291 292 /** 293 * Columns of {@link ContactsContract.Contacts} that refer to intrinsic 294 * properties of the contact, as opposed to the user-specified options 295 * found in {@link ContactOptionsColumns}. 296 * 297 * @see Contacts 298 * @see ContactsContract.Data 299 * @see PhoneLookup 300 * @see ContactsContract.Contacts.AggregationSuggestions 301 */ 302 protected interface ContactsColumns { 303 /** 304 * The display name for the contact. 305 * <P>Type: TEXT</P> 306 */ 307 public static final String DISPLAY_NAME = ContactNameColumns.DISPLAY_NAME_PRIMARY; 308 309 /** 310 * Reference to the row in the RawContacts table holding the contact name. 311 * <P>Type: INTEGER REFERENCES raw_contacts(_id)</P> 312 * @hide 313 */ 314 public static final String NAME_RAW_CONTACT_ID = "name_raw_contact_id"; 315 316 /** 317 * Reference to the row in the data table holding the photo. 318 * <P>Type: INTEGER REFERENCES data(_id)</P> 319 */ 320 public static final String PHOTO_ID = "photo_id"; 321 322 /** 323 * Lookup value that reflects the {@link Groups#GROUP_VISIBLE} state of 324 * any {@link CommonDataKinds.GroupMembership} for this contact. 325 */ 326 public static final String IN_VISIBLE_GROUP = "in_visible_group"; 327 328 /** 329 * An indicator of whether this contact has at least one phone number. "1" if there is 330 * at least one phone number, "0" otherwise. 331 * <P>Type: INTEGER</P> 332 */ 333 public static final String HAS_PHONE_NUMBER = "has_phone_number"; 334 335 /** 336 * An opaque value that contains hints on how to find the contact if 337 * its row id changed as a result of a sync or aggregation. 338 */ 339 public static final String LOOKUP_KEY = "lookup"; 340 } 341 342 /** 343 * @see Contacts 344 */ 345 protected interface ContactStatusColumns { 346 /** 347 * Contact presence status. See {@link StatusUpdates} for individual status 348 * definitions. 349 * <p>Type: NUMBER</p> 350 */ 351 public static final String CONTACT_PRESENCE = "contact_presence"; 352 353 /** 354 * Contact's latest status update. 355 * <p>Type: TEXT</p> 356 */ 357 public static final String CONTACT_STATUS = "contact_status"; 358 359 /** 360 * The absolute time in milliseconds when the latest status was 361 * inserted/updated. 362 * <p>Type: NUMBER</p> 363 */ 364 public static final String CONTACT_STATUS_TIMESTAMP = "contact_status_ts"; 365 366 /** 367 * The package containing resources for this status: label and icon. 368 * <p>Type: TEXT</p> 369 */ 370 public static final String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package"; 371 372 /** 373 * The resource ID of the label describing the source of contact 374 * status, e.g. "Google Talk". This resource is scoped by the 375 * {@link #CONTACT_STATUS_RES_PACKAGE}. 376 * <p>Type: NUMBER</p> 377 */ 378 public static final String CONTACT_STATUS_LABEL = "contact_status_label"; 379 380 /** 381 * The resource ID of the icon for the source of contact status. This 382 * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}. 383 * <p>Type: NUMBER</p> 384 */ 385 public static final String CONTACT_STATUS_ICON = "contact_status_icon"; 386 } 387 388 /** 389 * Constants for various styles of combining given name, family name etc into 390 * a full name. For example, the western tradition follows the pattern 391 * 'given name' 'middle name' 'family name' with the alternative pattern being 392 * 'family name', 'given name' 'middle name'. The CJK tradition is 393 * 'family name' 'middle name' 'given name', with Japanese favoring a space between 394 * the names and Chinese omitting the space. 395 * @hide 396 */ 397 public interface FullNameStyle { 398 public static final int UNDEFINED = 0; 399 public static final int WESTERN = 1; 400 401 /** 402 * Used if the name is written in Hanzi/Kanji/Hanja and we could not determine 403 * which specific language it belongs to: Chinese, Japanese or Korean. 404 */ 405 public static final int CJK = 2; 406 407 public static final int CHINESE = 3; 408 public static final int JAPANESE = 4; 409 public static final int KOREAN = 5; 410 } 411 412 /** 413 * Constants for various styles of capturing the pronunciation of a person's name. 414 * @hide 415 */ 416 public interface PhoneticNameStyle { 417 public static final int UNDEFINED = 0; 418 419 /** 420 * Pinyin is a phonetic method of entering Chinese characters. Typically not explicitly 421 * shown in UIs, but used for searches and sorting. 422 */ 423 public static final int PINYIN = 3; 424 425 /** 426 * Hiragana and Katakana are two common styles of writing out the pronunciation 427 * of a Japanese names. 428 */ 429 public static final int JAPANESE = 4; 430 431 /** 432 * Hangul is the Korean phonetic alphabet. 433 */ 434 public static final int KOREAN = 5; 435 } 436 437 /** 438 * Types of data used to produce the display name for a contact. Listed in the order 439 * of increasing priority. 440 * 441 * @hide 442 */ 443 public interface DisplayNameSources { 444 public static final int UNDEFINED = 0; 445 public static final int EMAIL = 10; 446 public static final int PHONE = 20; 447 public static final int ORGANIZATION = 30; 448 public static final int NICKNAME = 35; 449 public static final int STRUCTURED_NAME = 40; 450 } 451 452 /** 453 * Contact name and contact name metadata columns in the RawContacts table. 454 * 455 * @see Contacts 456 * @see RawContacts 457 * @hide 458 */ 459 protected interface ContactNameColumns { 460 461 /** 462 * The kind of data that is used as the display name for the contact, see 463 * DisplayNameSources. 464 */ 465 public static final String DISPLAY_NAME_SOURCE = "display_name_source"; 466 467 /** 468 * The default text shown as the contact's display name. It is based on 469 * available data, see {@link #DISPLAY_NAME_SOURCE}. 470 */ 471 public static final String DISPLAY_NAME_PRIMARY = "display_name"; 472 473 /** 474 * Alternative representation of the display name. If display name is 475 * based on the structured name and the structured name follows 476 * the Western full name style, then this field contains the "family name first" 477 * version of the full name. Otherwise, it is the same as DISPLAY_NAME_PRIMARY. 478 */ 479 public static final String DISPLAY_NAME_ALTERNATIVE = "display_name_alt"; 480 481 /** 482 * The type of alphabet used to capture the phonetic name. See 483 * PhoneticNameStyle. 484 */ 485 public static final String PHONETIC_NAME_STYLE = "phonetic_name_style"; 486 487 /** 488 * Pronunciation of the full name. See PhoneticNameStyle. 489 */ 490 public static final String PHONETIC_NAME = "phonetic_name"; 491 492 /** 493 * Sort key that takes into account locale-based traditions for sorting 494 * names in address books. More specifically, for Chinese names 495 * the sort key is the name's Pinyin spelling; for Japanese names 496 * it is the Hiragana version of the phonetic name. 497 */ 498 public static final String SORT_KEY_PRIMARY = "sort_key"; 499 500 /** 501 * Sort key based on the alternative representation of the full name, 502 * specifically the one using the 'family name first' format for 503 * Western names. 504 */ 505 public static final String SORT_KEY_ALTERNATIVE = "sort_key_alt"; 506 } 507 508 /** 509 * Constants for the contacts table, which contains a record per aggregate 510 * of raw contacts representing the same person. 511 * <h3>Operations</h3> 512 * <dl> 513 * <dt><b>Insert</b></dt> 514 * <dd>A Contact cannot be created explicitly. When a raw contact is 515 * inserted, the provider will first try to find a Contact representing the 516 * same person. If one is found, the raw contact's 517 * {@link RawContacts#CONTACT_ID} column gets the _ID of the aggregate 518 * Contact. If no match is found, the provider automatically inserts a new 519 * Contact and puts its _ID into the {@link RawContacts#CONTACT_ID} column 520 * of the newly inserted raw contact.</dd> 521 * <dt><b>Update</b></dt> 522 * <dd>Only certain columns of Contact are modifiable: 523 * {@link #TIMES_CONTACTED}, {@link #LAST_TIME_CONTACTED}, {@link #STARRED}, 524 * {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of 525 * these columns on the Contact also changes them on all constituent raw 526 * contacts.</dd> 527 * <dt><b>Delete</b></dt> 528 * <dd>Be careful with deleting Contacts! Deleting an aggregate contact 529 * deletes all constituent raw contacts. The corresponding sync adapters 530 * will notice the deletions of their respective raw contacts and remove 531 * them from their back end storage.</dd> 532 * <dt><b>Query</b></dt> 533 * <dd> 534 * <ul> 535 * <li>If you need to read an individual contact, consider using 536 * {@link #CONTENT_LOOKUP_URI} instead of {@link #CONTENT_URI}.</li> 537 * <li>If you need to look up a contact by the phone number, use 538 * {@link PhoneLookup#CONTENT_FILTER_URI PhoneLookup.CONTENT_FILTER_URI}, 539 * which is optimized for this purpose.</li> 540 * <li>If you need to look up a contact by partial name, e.g. to produce 541 * filter-as-you-type suggestions, use the {@link #CONTENT_FILTER_URI} URI. 542 * <li>If you need to look up a contact by some data element like email 543 * address, nickname, etc, use a query against the {@link ContactsContract.Data} table. 544 * The result will contain contact ID, name etc. 545 * </ul> 546 * </dd> 547 * </dl> 548 * <h2>Columns</h2> 549 * <table class="jd-sumtable"> 550 * <tr> 551 * <th colspan='4'>Contacts</th> 552 * </tr> 553 * <tr> 554 * <td>long</td> 555 * <td>{@link #_ID}</td> 556 * <td>read-only</td> 557 * <td>Row ID. Consider using {@link #LOOKUP_KEY} instead.</td> 558 * </tr> 559 * <tr> 560 * <td>String</td> 561 * <td>{@link #LOOKUP_KEY}</td> 562 * <td>read-only</td> 563 * <td>An opaque value that contains hints on how to find the contact if its 564 * row id changed as a result of a sync or aggregation.</td> 565 * </tr> 566 * <tr> 567 * <td>long</td> 568 * <td>NAME_RAW_CONTACT_ID</td> 569 * <td>read-only</td> 570 * <td>The ID of the raw contact that contributes the display name 571 * to the aggregate contact. During aggregation one of the constituent 572 * raw contacts is chosen using a heuristic: a longer name or a name 573 * with more diacritic marks or more upper case characters is chosen.</td> 574 * </tr> 575 * <tr> 576 * <td>String</td> 577 * <td>DISPLAY_NAME_PRIMARY</td> 578 * <td>read-only</td> 579 * <td>The display name for the contact. It is the display name 580 * contributed by the raw contact referred to by the NAME_RAW_CONTACT_ID 581 * column.</td> 582 * </tr> 583 * <tr> 584 * <td>long</td> 585 * <td>{@link #PHOTO_ID}</td> 586 * <td>read-only</td> 587 * <td>Reference to the row in the {@link ContactsContract.Data} table holding the photo. 588 * That row has the mime type 589 * {@link CommonDataKinds.Photo#CONTENT_ITEM_TYPE}. The value of this field 590 * is computed automatically based on the 591 * {@link CommonDataKinds.Photo#IS_SUPER_PRIMARY} field of the data rows of 592 * that mime type.</td> 593 * </tr> 594 * <tr> 595 * <td>int</td> 596 * <td>{@link #IN_VISIBLE_GROUP}</td> 597 * <td>read-only</td> 598 * <td>An indicator of whether this contact is supposed to be visible in the 599 * UI. "1" if the contact has at least one raw contact that belongs to a 600 * visible group; "0" otherwise.</td> 601 * </tr> 602 * <tr> 603 * <td>int</td> 604 * <td>{@link #HAS_PHONE_NUMBER}</td> 605 * <td>read-only</td> 606 * <td>An indicator of whether this contact has at least one phone number. 607 * "1" if there is at least one phone number, "0" otherwise.</td> 608 * </tr> 609 * <tr> 610 * <td>int</td> 611 * <td>{@link #TIMES_CONTACTED}</td> 612 * <td>read/write</td> 613 * <td>The number of times the contact has been contacted. See 614 * {@link #markAsContacted}. When raw contacts are aggregated, this field is 615 * computed automatically as the maximum number of times contacted among all 616 * constituent raw contacts. Setting this field automatically changes the 617 * corresponding field on all constituent raw contacts.</td> 618 * </tr> 619 * <tr> 620 * <td>long</td> 621 * <td>{@link #LAST_TIME_CONTACTED}</td> 622 * <td>read/write</td> 623 * <td>The timestamp of the last time the contact was contacted. See 624 * {@link #markAsContacted}. Setting this field also automatically 625 * increments {@link #TIMES_CONTACTED}. When raw contacts are aggregated, 626 * this field is computed automatically as the latest time contacted of all 627 * constituent raw contacts. Setting this field automatically changes the 628 * corresponding field on all constituent raw contacts.</td> 629 * </tr> 630 * <tr> 631 * <td>int</td> 632 * <td>{@link #STARRED}</td> 633 * <td>read/write</td> 634 * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise. 635 * When raw contacts are aggregated, this field is automatically computed: 636 * if any constituent raw contacts are starred, then this field is set to 637 * '1'. Setting this field automatically changes the corresponding field on 638 * all constituent raw contacts.</td> 639 * </tr> 640 * <tr> 641 * <td>String</td> 642 * <td>{@link #CUSTOM_RINGTONE}</td> 643 * <td>read/write</td> 644 * <td>A custom ringtone associated with a contact. Typically this is the 645 * URI returned by an activity launched with the 646 * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent.</td> 647 * </tr> 648 * <tr> 649 * <td>int</td> 650 * <td>{@link #SEND_TO_VOICEMAIL}</td> 651 * <td>read/write</td> 652 * <td>An indicator of whether calls from this contact should be forwarded 653 * directly to voice mail ('1') or not ('0'). When raw contacts are 654 * aggregated, this field is automatically computed: if <i>all</i> 655 * constituent raw contacts have SEND_TO_VOICEMAIL=1, then this field is set 656 * to '1'. Setting this field automatically changes the corresponding field 657 * on all constituent raw contacts.</td> 658 * </tr> 659 * <tr> 660 * <td>int</td> 661 * <td>{@link #CONTACT_PRESENCE}</td> 662 * <td>read-only</td> 663 * <td>Contact IM presence status. See {@link StatusUpdates} for individual 664 * status definitions. Automatically computed as the highest presence of all 665 * constituent raw contacts. The provider may choose not to store this value 666 * in persistent storage. The expectation is that presence status will be 667 * updated on a regular basic.</td> 668 * </tr> 669 * <tr> 670 * <td>String</td> 671 * <td>{@link #CONTACT_STATUS}</td> 672 * <td>read-only</td> 673 * <td>Contact's latest status update. Automatically computed as the latest 674 * of all constituent raw contacts' status updates.</td> 675 * </tr> 676 * <tr> 677 * <td>long</td> 678 * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td> 679 * <td>read-only</td> 680 * <td>The absolute time in milliseconds when the latest status was 681 * inserted/updated.</td> 682 * </tr> 683 * <tr> 684 * <td>String</td> 685 * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td> 686 * <td>read-only</td> 687 * <td> The package containing resources for this status: label and icon.</td> 688 * </tr> 689 * <tr> 690 * <td>long</td> 691 * <td>{@link #CONTACT_STATUS_LABEL}</td> 692 * <td>read-only</td> 693 * <td>The resource ID of the label describing the source of contact status, 694 * e.g. "Google Talk". This resource is scoped by the 695 * {@link #CONTACT_STATUS_RES_PACKAGE}.</td> 696 * </tr> 697 * <tr> 698 * <td>long</td> 699 * <td>{@link #CONTACT_STATUS_ICON}</td> 700 * <td>read-only</td> 701 * <td>The resource ID of the icon for the source of contact status. This 702 * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}.</td> 703 * </tr> 704 * </table> 705 */ 706 public static class Contacts implements BaseColumns, ContactsColumns, 707 ContactOptionsColumns, ContactNameColumns, ContactStatusColumns { 708 /** 709 * This utility class cannot be instantiated 710 */ 711 private Contacts() {} 712 713 /** 714 * The content:// style URI for this table 715 */ 716 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts"); 717 718 /** 719 * A content:// style URI for this table that should be used to create 720 * shortcuts or otherwise create long-term links to contacts. This URI 721 * should always be followed by a "/" and the contact's {@link #LOOKUP_KEY}. 722 * It can optionally also have a "/" and last known contact ID appended after 723 * that. This "complete" format is an important optimization and is highly recommended. 724 * <p> 725 * As long as the contact's row ID remains the same, this URI is 726 * equivalent to {@link #CONTENT_URI}. If the contact's row ID changes 727 * as a result of a sync or aggregation, this URI will look up the 728 * contact using indirect information (sync IDs or constituent raw 729 * contacts). 730 * <p> 731 * Lookup key should be appended unencoded - it is stored in the encoded 732 * form, ready for use in a URI. 733 */ 734 public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, 735 "lookup"); 736 737 /** 738 * Base {@link Uri} for referencing a single {@link Contacts} entry, 739 * created by appending {@link #LOOKUP_KEY} using 740 * {@link Uri#withAppendedPath(Uri, String)}. Provides 741 * {@link OpenableColumns} columns when queried, or returns the 742 * referenced contact formatted as a vCard when opened through 743 * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. 744 */ 745 public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, 746 "as_vcard"); 747 748 /** 749 * Builds a {@link #CONTENT_LOOKUP_URI} style {@link Uri} describing the 750 * requested {@link Contacts} entry. 751 * 752 * @param contactUri A {@link #CONTENT_URI} row, or an existing 753 * {@link #CONTENT_LOOKUP_URI} to attempt refreshing. 754 */ 755 public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) { 756 final Cursor c = resolver.query(contactUri, new String[] { 757 Contacts.LOOKUP_KEY, Contacts._ID 758 }, null, null, null); 759 if (c == null) { 760 return null; 761 } 762 763 try { 764 if (c.moveToFirst()) { 765 final String lookupKey = c.getString(0); 766 final long contactId = c.getLong(1); 767 return getLookupUri(contactId, lookupKey); 768 } 769 } finally { 770 c.close(); 771 } 772 return null; 773 } 774 775 /** 776 * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the 777 * given {@link ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}. 778 */ 779 public static Uri getLookupUri(long contactId, String lookupKey) { 780 return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, 781 lookupKey), contactId); 782 } 783 784 /** 785 * Computes a content URI (see {@link #CONTENT_URI}) given a lookup URI. 786 * <p> 787 * Returns null if the contact cannot be found. 788 */ 789 public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) { 790 if (lookupUri == null) { 791 return null; 792 } 793 794 Cursor c = resolver.query(lookupUri, new String[]{Contacts._ID}, null, null, null); 795 if (c == null) { 796 return null; 797 } 798 799 try { 800 if (c.moveToFirst()) { 801 long contactId = c.getLong(0); 802 return ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 803 } 804 } finally { 805 c.close(); 806 } 807 return null; 808 } 809 810 /** 811 * Mark a contact as having been contacted. 812 * 813 * @param resolver the ContentResolver to use 814 * @param contactId the person who was contacted 815 */ 816 public static void markAsContacted(ContentResolver resolver, long contactId) { 817 Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId); 818 ContentValues values = new ContentValues(); 819 // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified. 820 values.put(LAST_TIME_CONTACTED, System.currentTimeMillis()); 821 resolver.update(uri, values, null, null); 822 } 823 824 /** 825 * The content:// style URI used for "type-to-filter" functionality on the 826 * {@link #CONTENT_URI} URI. The filter string will be used to match 827 * various parts of the contact name. The filter argument should be passed 828 * as an additional path segment after this URI. 829 */ 830 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath( 831 CONTENT_URI, "filter"); 832 833 /** 834 * The content:// style URI for this table joined with useful data from 835 * {@link ContactsContract.Data}, filtered to include only starred contacts 836 * and the most frequently contacted contacts. 837 */ 838 public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath( 839 CONTENT_URI, "strequent"); 840 841 /** 842 * The content:// style URI used for "type-to-filter" functionality on the 843 * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match 844 * various parts of the contact name. The filter argument should be passed 845 * as an additional path segment after this URI. 846 */ 847 public static final Uri CONTENT_STREQUENT_FILTER_URI = Uri.withAppendedPath( 848 CONTENT_STREQUENT_URI, "filter"); 849 850 public static final Uri CONTENT_GROUP_URI = Uri.withAppendedPath( 851 CONTENT_URI, "group"); 852 853 /** 854 * The MIME type of {@link #CONTENT_URI} providing a directory of 855 * people. 856 */ 857 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact"; 858 859 /** 860 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 861 * person. 862 */ 863 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact"; 864 865 /** 866 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 867 * person. 868 */ 869 public static final String CONTENT_VCARD_TYPE = "text/x-vcard"; 870 871 /** 872 * A sub-directory of a single contact that contains all of the constituent raw contact 873 * {@link ContactsContract.Data} rows. 874 */ 875 public static final class Data implements BaseColumns, DataColumns { 876 /** 877 * no public constructor since this is a utility class 878 */ 879 private Data() {} 880 881 /** 882 * The directory twig for this sub-table 883 */ 884 public static final String CONTENT_DIRECTORY = "data"; 885 } 886 887 /** 888 * <p> 889 * A <i>read-only</i> sub-directory of a single contact aggregate that 890 * contains all aggregation suggestions (other contacts). The 891 * aggregation suggestions are computed based on approximate data 892 * matches with this contact. 893 * </p> 894 * <p> 895 * <i>Note: this query may be expensive! If you need to use it in bulk, 896 * make sure the user experience is acceptable when the query runs for a 897 * long time.</i> 898 * <p> 899 * Usage example: 900 * 901 * <pre> 902 * Uri uri = Contacts.CONTENT_URI.buildUpon() 903 * .appendEncodedPath(String.valueOf(contactId)) 904 * .appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY) 905 * .appendQueryParameter("limit", "3") 906 * .build() 907 * Cursor cursor = getContentResolver().query(suggestionsUri, 908 * new String[] {Contacts.DISPLAY_NAME, Contacts._ID, Contacts.LOOKUP_KEY}, 909 * null, null, null); 910 * </pre> 911 * 912 * </p> 913 */ 914 // TODO: add ContactOptionsColumns, ContactStatusColumns 915 public static final class AggregationSuggestions implements BaseColumns, ContactsColumns { 916 /** 917 * No public constructor since this is a utility class 918 */ 919 private AggregationSuggestions() {} 920 921 /** 922 * The directory twig for this sub-table. The URI can be followed by an optional 923 * type-to-filter, similar to 924 * {@link android.provider.ContactsContract.Contacts#CONTENT_FILTER_URI}. 925 */ 926 public static final String CONTENT_DIRECTORY = "suggestions"; 927 } 928 929 /** 930 * A <i>read-only</i> sub-directory of a single contact that contains 931 * the contact's primary photo. 932 * <p> 933 * Usage example: 934 * 935 * <pre> 936 * public InputStream openPhoto(long contactId) { 937 * Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 938 * Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); 939 * Cursor cursor = getContentResolver().query(photoUri, 940 * new String[] {Contacts.Photo.PHOTO}, null, null, null); 941 * if (cursor == null) { 942 * return null; 943 * } 944 * try { 945 * if (cursor.moveToFirst()) { 946 * byte[] data = cursor.getBlob(0); 947 * if (data != null) { 948 * return new ByteArrayInputStream(data); 949 * } 950 * } 951 * } finally { 952 * cursor.close(); 953 * } 954 * return null; 955 * } 956 * </pre> 957 * 958 * </p> 959 * <p>You should also consider using the convenience method 960 * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)} 961 * </p> 962 */ 963 // TODO: change DataColumns to DataColumnsWithJoins 964 public static final class Photo implements BaseColumns, DataColumns { 965 /** 966 * no public constructor since this is a utility class 967 */ 968 private Photo() {} 969 970 /** 971 * The directory twig for this sub-table 972 */ 973 public static final String CONTENT_DIRECTORY = "photo"; 974 975 /** 976 * Thumbnail photo of the raw contact. This is the raw bytes of an image 977 * that could be inflated using {@link android.graphics.BitmapFactory}. 978 * <p> 979 * Type: BLOB 980 * @hide TODO: Unhide in a separate CL 981 */ 982 public static final String PHOTO = DATA15; 983 } 984 985 /** 986 * Opens an InputStream for the contacts's default photo and returns the 987 * photo as a byte stream. If there is not photo null will be returned. 988 * 989 * @param contactUri the contact whose photo should be used 990 * @return an InputStream of the photo, or null if no photo is present 991 */ 992 public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { 993 Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY); 994 if (photoUri == null) { 995 return null; 996 } 997 Cursor cursor = cr.query(photoUri, 998 new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); 999 try { 1000 if (cursor == null || !cursor.moveToNext()) { 1001 return null; 1002 } 1003 byte[] data = cursor.getBlob(0); 1004 if (data == null) { 1005 return null; 1006 } 1007 return new ByteArrayInputStream(data); 1008 } finally { 1009 if (cursor != null) { 1010 cursor.close(); 1011 } 1012 } 1013 } 1014 } 1015 1016 protected interface RawContactsColumns { 1017 /** 1018 * A reference to the {@link ContactsContract.Contacts#_ID} that this 1019 * data belongs to. 1020 * <P>Type: INTEGER</P> 1021 */ 1022 public static final String CONTACT_ID = "contact_id"; 1023 1024 /** 1025 * Flag indicating that this {@link RawContacts} entry and its children have 1026 * been restricted to specific platform apps. 1027 * <P>Type: INTEGER (boolean)</P> 1028 * 1029 * @hide until finalized in future platform release 1030 */ 1031 public static final String IS_RESTRICTED = "is_restricted"; 1032 1033 /** 1034 * The aggregation mode for this contact. 1035 * <P>Type: INTEGER</P> 1036 */ 1037 public static final String AGGREGATION_MODE = "aggregation_mode"; 1038 1039 /** 1040 * The "deleted" flag: "0" by default, "1" if the row has been marked 1041 * for deletion. When {@link android.content.ContentResolver#delete} is 1042 * called on a raw contact, it is marked for deletion and removed from its 1043 * aggregate contact. The sync adaptor deletes the raw contact on the server and 1044 * then calls ContactResolver.delete once more, this time passing the 1045 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 1046 * the data removal. 1047 * <P>Type: INTEGER</P> 1048 */ 1049 public static final String DELETED = "deleted"; 1050 } 1051 1052 /** 1053 * Constants for the raw contacts table, which contains the base contact 1054 * information per sync source. Sync adapters and contact management apps 1055 * are the primary consumers of this API. 1056 * <h3>Operations</h3> 1057 * <dl> 1058 * <dt><b>Insert</b></dt> 1059 * <dd>There are two mechanisms that can be used to insert a raw contact: incremental and 1060 * batch. The incremental method is more traditional but less efficient. It should be used 1061 * only if the constituent data rows are unavailable at the time the raw contact is created: 1062 * <pre> 1063 * ContentValues values = new ContentValues(); 1064 * values.put(RawContacts.ACCOUNT_TYPE, accountType); 1065 * values.put(RawContacts.ACCOUNT_NAME, accountName); 1066 * Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values); 1067 * long rawContactId = ContentUris.parseId(rawContactUri); 1068 * </pre> 1069 * <p> 1070 * Once data rows are available, insert those. For example, here's how you would insert 1071 * a name: 1072 * 1073 * <pre> 1074 * values.clear(); 1075 * values.put(Data.RAW_CONTACT_ID, rawContactId); 1076 * values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 1077 * values.put(StructuredName.DISPLAY_NAME, "Mike Sullivan"); 1078 * getContentResolver().insert(Data.CONTENT_URI, values); 1079 * </pre> 1080 * </p> 1081 * <p> 1082 * The batch method is by far preferred. It inserts the raw contact and its 1083 * constituent data rows in a single database transaction 1084 * and causes at most one aggregation pass. 1085 * <pre> 1086 * ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 1087 * int rawContactInsertIndex = ops.size(); 1088 * ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI) 1089 * .withValue(RawContacts.ACCOUNT_TYPE, accountType) 1090 * .withValue(RawContacts.ACCOUNT_NAME, accountName) 1091 * .build()); 1092 * 1093 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 1094 * .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex) 1095 * .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 1096 * .withValue(StructuredName.DISPLAY_NAME, "Mike Sullivan") 1097 * .build()); 1098 * 1099 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 1100 * </pre> 1101 * </p> 1102 * <p> 1103 * Please note the use of back reference in the construction of the 1104 * {@link ContentProviderOperation}. It allows an operation to use the result of 1105 * a previous operation by referring to it by its index in the batch. 1106 * </p> 1107 * <dt><b>Update</b></dt> 1108 * <dd><p>Just as with insert, the update can be done incrementally or as a batch, the 1109 * batch mode being the preferred method.</p></dd> 1110 * <dt><b>Delete</b></dt> 1111 * <dd><p>When a raw contact is deleted, all of its Data rows as well as StatusUpdates, 1112 * AggregationExceptions, PhoneLookup rows are deleted automatically. When all raw 1113 * contacts in a Contact are deleted, the Contact itself is also deleted automatically. 1114 * </p> 1115 * <p> 1116 * The invocation of {@code resolver.delete(...)}, does not physically delete 1117 * a raw contacts row. It sets the {@link #DELETED} flag on the raw contact and 1118 * removes the raw contact from its aggregate contact. 1119 * The sync adapter then deletes the raw contact from the server and 1120 * finalizes phone-side deletion by calling {@code resolver.delete(...)} 1121 * again and passing the {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter.<p> 1122 * <p>Some sync adapters are read-only, meaning that they only sync server-side 1123 * changes to the phone, but not the reverse. If one of those raw contacts 1124 * is marked for deletion, it will remain on the phone. However it will be 1125 * effectively invisible, because it will not be part of any aggregate contact. 1126 * </dd> 1127 * <dt><b>Query</b></dt> 1128 * <dd> 1129 * <p> 1130 * Finding all raw contacts in a Contact is easy: 1131 * <pre> 1132 * Cursor c = getContentResolver().query(RawContacts.CONTENT_URI, 1133 * new String[]{RawContacts._ID}, 1134 * RawContacts.CONTACT_ID + "=?", 1135 * new String[]{String.valueOf(contactId)}, null); 1136 * </pre> 1137 * </p> 1138 * <p> 1139 * There are two ways to find raw contacts within a specific account, 1140 * you can either put the account name and type in the selection or pass them as query 1141 * parameters. The latter approach is preferable, especially when you can reuse the 1142 * URI: 1143 * <pre> 1144 * Uri rawContactUri = RawContacts.URI.buildUpon() 1145 * .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName) 1146 * .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType) 1147 * .build(); 1148 * Cursor c1 = getContentResolver().query(rawContactUri, 1149 * RawContacts.STARRED + "<>0", null, null, null); 1150 * ... 1151 * Cursor c2 = getContentResolver().query(rawContactUri, 1152 * RawContacts.DELETED + "<>0", null, null, null); 1153 * </pre> 1154 * </p> 1155 * <p>The best way to read a raw contact along with all the data associated with it is 1156 * by using the {@link Entity} directory. If the raw contact has data rows, 1157 * the Entity cursor will contain a row for each data row. If the raw contact has no 1158 * data rows, the cursor will still contain one row with the raw contact-level information. 1159 * <pre> 1160 * Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1161 * Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY); 1162 * Cursor c = getContentResolver().query(entityUri, 1163 * new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1}, 1164 * null, null, null); 1165 * try { 1166 * while (c.moveToNext()) { 1167 * String sourceId = c.getString(0); 1168 * if (!c.isNull(1)) { 1169 * String mimeType = c.getString(2); 1170 * String data = c.getString(3); 1171 * ... 1172 * } 1173 * } 1174 * } finally { 1175 * c.close(); 1176 * } 1177 * </pre> 1178 * </p> 1179 * </dd> 1180 * </dl> 1181 * <h3>Aggregation</h3> 1182 * <p> 1183 * As soon as a raw contact is inserted or whenever its constituent data 1184 * changes, the provider will check if the raw contact matches other 1185 * existing raw contacts and if so will aggregate it with those. From the 1186 * data standpoint, aggregation is reflected in the change of the 1187 * {@link #CONTACT_ID} field, which is the reference to the aggregate contact. 1188 * </p> 1189 * <p> 1190 * See also {@link AggregationExceptions} for a mechanism to control 1191 * aggregation programmatically. 1192 * </p> 1193 * <h2>Columns</h2> 1194 * <table class="jd-sumtable"> 1195 * <tr> 1196 * <th colspan='4'>RawContacts</th> 1197 * </tr> 1198 * <tr> 1199 * <td>long</td> 1200 * <td>{@link #_ID}</td> 1201 * <td>read-only</td> 1202 * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words, 1203 * it would be a really bad idea to delete and reinsert a raw contact. A sync adapter should 1204 * always do an update instead.</td> 1205 * </tr> 1206 * <tr> 1207 * <td>long</td> 1208 * <td>{@link #CONTACT_ID}</td> 1209 * <td>read-only</td> 1210 * <td>A reference to the {@link ContactsContract.Contacts#_ID} that this raw contact belongs 1211 * to. Raw contacts are linked to contacts by the aggregation process, which can be controlled 1212 * by the {@link #AGGREGATION_MODE} field and {@link AggregationExceptions}.</td> 1213 * </tr> 1214 * <tr> 1215 * <td>int</td> 1216 * <td>{@link #AGGREGATION_MODE}</td> 1217 * <td>read/write</td> 1218 * <td>A mechanism that allows programmatic control of the aggregation process. The allowed 1219 * values are {@link #AGGREGATION_MODE_DEFAULT}, {@link #AGGREGATION_MODE_DISABLED} 1220 * and {@link #AGGREGATION_MODE_SUSPENDED}. See also {@link AggregationExceptions}.</td> 1221 * </tr> 1222 * <tr> 1223 * <td>int</td> 1224 * <td>{@link #DELETED}</td> 1225 * <td>read/write</td> 1226 * <td>The "deleted" flag: "0" by default, "1" if the row has been marked 1227 * for deletion. When {@link android.content.ContentResolver#delete} is 1228 * called on a raw contact, it is marked for deletion and removed from its 1229 * aggregate contact. The sync adaptor deletes the raw contact on the server and 1230 * then calls ContactResolver.delete once more, this time passing the 1231 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 1232 * the data removal.</td> 1233 * </tr> 1234 * <tr> 1235 * <td>int</td> 1236 * <td>{@link #TIMES_CONTACTED}</td> 1237 * <td>read/write</td> 1238 * <td>The number of times the contact has been contacted. To have an effect 1239 * on the corresponding value of the aggregate contact, this field 1240 * should be set at the time the raw contact is inserted. 1241 * See {@link ContactsContract.Contacts#markAsContacted}.</td> 1242 * </tr> 1243 * <tr> 1244 * <td>long</td> 1245 * <td>{@link #LAST_TIME_CONTACTED}</td> 1246 * <td>read/write</td> 1247 * <td>The timestamp of the last time the contact was contacted. To have an effect 1248 * on the corresponding value of the aggregate contact, this field 1249 * should be set at the time the raw contact is inserted. 1250 * See {@link ContactsContract.Contacts#markAsContacted}.</td> 1251 * </tr> 1252 * <tr> 1253 * <td>int</td> 1254 * <td>{@link #STARRED}</td> 1255 * <td>read/write</td> 1256 * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise. 1257 * Changing this field immediately effects the corresponding aggregate contact: 1258 * if any raw contacts in that aggregate contact are starred, then the contact 1259 * itself is marked as starred.</td> 1260 * </tr> 1261 * <tr> 1262 * <td>String</td> 1263 * <td>{@link #CUSTOM_RINGTONE}</td> 1264 * <td>read/write</td> 1265 * <td>A custom ringtone associated with a raw contact. Typically this is the 1266 * URI returned by an activity launched with the 1267 * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent. 1268 * To have an effect on the corresponding value of the aggregate contact, this field 1269 * should be set at the time the raw contact is inserted. To set a custom 1270 * ringtone on a contact, use the field {@link ContactsContract.Contacts#CUSTOM_RINGTONE} 1271 * instead.</td> 1272 * </tr> 1273 * <tr> 1274 * <td>int</td> 1275 * <td>{@link #SEND_TO_VOICEMAIL}</td> 1276 * <td>read/write</td> 1277 * <td>An indicator of whether calls from this raw contact should be forwarded 1278 * directly to voice mail ('1') or not ('0'). To have an effect 1279 * on the corresponding value of the aggregate contact, this field 1280 * should be set at the time the raw contact is inserted.</td> 1281 * </tr> 1282 * <tr> 1283 * <td>String</td> 1284 * <td>{@link #ACCOUNT_NAME}</td> 1285 * <td>read/write-once</td> 1286 * <td>The name of the account instance to which this row belongs, which when paired with 1287 * {@link #ACCOUNT_TYPE} identifies a specific account. It should be set at the time 1288 * the raw contact is inserted and never changed afterwards.</td> 1289 * </tr> 1290 * <tr> 1291 * <td>String</td> 1292 * <td>{@link #ACCOUNT_TYPE}</td> 1293 * <td>read/write-once</td> 1294 * <td>The type of account to which this row belongs, which when paired with 1295 * {@link #ACCOUNT_NAME} identifies a specific account. It should be set at the time 1296 * the raw contact is inserted and never changed afterwards.</td> 1297 * </tr> 1298 * <tr> 1299 * <td>String</td> 1300 * <td>{@link #SOURCE_ID}</td> 1301 * <td>read/write</td> 1302 * <td>String that uniquely identifies this row to its source account. 1303 * Typically it is set at the time the raw contact is inserted and never 1304 * changed afterwards. The one notable exception is a new raw contact: it 1305 * will have an account name and type, but no source id. This should 1306 * indicated to the sync adapter that a new contact needs to be created 1307 * server-side and its ID stored in the corresponding SOURCE_ID field on 1308 * the phone. 1309 * </td> 1310 * </tr> 1311 * <tr> 1312 * <td>int</td> 1313 * <td>{@link #VERSION}</td> 1314 * <td>read-only</td> 1315 * <td>Version number that is updated whenever this row or its related data 1316 * changes. This field can be used for optimistic locking of a raw contact. 1317 * </td> 1318 * </tr> 1319 * <tr> 1320 * <td>int</td> 1321 * <td>{@link #DIRTY}</td> 1322 * <td>read/write</td> 1323 * <td>Flag indicating that {@link #VERSION} has changed, and this row needs 1324 * to be synchronized by its owning account. The value is set to "1" automatically 1325 * whenever the raw contact changes, unless the URI has the 1326 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter specified. 1327 * The sync adapter should always supply this query parameter to prevent 1328 * unnecessary synchronization: user changes some data on the server, 1329 * the sync adapter updates the contact on the phone (without the 1330 * CALLER_IS_SYNCADAPTER flag) flag, which sets the DIRTY flag, 1331 * which triggers a sync to bring the changes to the server. 1332 * </td> 1333 * </tr> 1334 * <tr> 1335 * <td>String</td> 1336 * <td>{@link #SYNC1}</td> 1337 * <td>read/write</td> 1338 * <td>Generic column for use by sync adapters. Content provider 1339 * stores this information on behalf of the sync adapter but does not 1340 * interpret it in any way. 1341 * </td> 1342 * </tr> 1343 * <tr> 1344 * <td>String</td> 1345 * <td>{@link #SYNC2}</td> 1346 * <td>read/write</td> 1347 * <td>Generic column for use by sync adapters. 1348 * </td> 1349 * </tr> 1350 * <tr> 1351 * <td>String</td> 1352 * <td>{@link #SYNC3}</td> 1353 * <td>read/write</td> 1354 * <td>Generic column for use by sync adapters. 1355 * </td> 1356 * </tr> 1357 * <tr> 1358 * <td>String</td> 1359 * <td>{@link #SYNC4}</td> 1360 * <td>read/write</td> 1361 * <td>Generic column for use by sync adapters. 1362 * </td> 1363 * </tr> 1364 * </table> 1365 */ 1366 public static final class RawContacts implements BaseColumns, RawContactsColumns, 1367 ContactOptionsColumns, ContactNameColumns, SyncColumns { 1368 /** 1369 * This utility class cannot be instantiated 1370 */ 1371 private RawContacts() { 1372 } 1373 1374 /** 1375 * The content:// style URI for this table 1376 */ 1377 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts"); 1378 1379 /** 1380 * The MIME type of {@link #CONTENT_URI} providing a directory of 1381 * people. 1382 */ 1383 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact"; 1384 1385 /** 1386 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 1387 * person. 1388 */ 1389 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact"; 1390 1391 /** 1392 * Aggregation mode: aggregate asynchronously. 1393 */ 1394 public static final int AGGREGATION_MODE_DEFAULT = 0; 1395 1396 /** 1397 * Aggregation mode: aggregate at the time the raw contact is inserted/updated. 1398 * TODO: deprecate. Aggregation is now synchronous, this value is a no-op 1399 */ 1400 public static final int AGGREGATION_MODE_IMMEDIATE = 1; 1401 1402 /** 1403 * If {@link #AGGREGATION_MODE} is {@link #AGGREGATION_MODE_SUSPENDED}, changes 1404 * to the raw contact do not cause its aggregation to be revisited. Note that changing 1405 * {@link #AGGREGATION_MODE} from {@link #AGGREGATION_MODE_SUSPENDED} to 1406 * {@link #AGGREGATION_MODE_DEFAULT} does not trigger an aggregation pass. Any subsequent 1407 * change to the raw contact's data will. 1408 */ 1409 public static final int AGGREGATION_MODE_SUSPENDED = 2; 1410 1411 /** 1412 * Aggregation mode: never aggregate this raw contact (note that the raw contact will not 1413 * have a corresponding Aggregate and therefore will not be included in Aggregates 1414 * query results.) 1415 */ 1416 public static final int AGGREGATION_MODE_DISABLED = 3; 1417 1418 /** 1419 * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 1420 * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} 1421 * entry of the given {@link RawContacts} entry. 1422 */ 1423 public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) { 1424 // TODO: use a lighter query by joining rawcontacts with contacts in provider 1425 final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY); 1426 final Cursor cursor = resolver.query(dataUri, new String[] { 1427 RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY 1428 }, null, null, null); 1429 1430 Uri lookupUri = null; 1431 try { 1432 if (cursor != null && cursor.moveToFirst()) { 1433 final long contactId = cursor.getLong(0); 1434 final String lookupKey = cursor.getString(1); 1435 return Contacts.getLookupUri(contactId, lookupKey); 1436 } 1437 } finally { 1438 if (cursor != null) cursor.close(); 1439 } 1440 return lookupUri; 1441 } 1442 1443 /** 1444 * A sub-directory of a single raw contact that contains all of their 1445 * {@link ContactsContract.Data} rows. To access this directory 1446 * append {@link Data#CONTENT_DIRECTORY} to the contact URI. 1447 */ 1448 public static final class Data implements BaseColumns, DataColumns { 1449 /** 1450 * no public constructor since this is a utility class 1451 */ 1452 private Data() { 1453 } 1454 1455 /** 1456 * The directory twig for this sub-table 1457 */ 1458 public static final String CONTENT_DIRECTORY = "data"; 1459 } 1460 1461 /** 1462 * <p> 1463 * A sub-directory of a single raw contact that contains all of their 1464 * {@link ContactsContract.Data} rows. To access this directory append 1465 * {@link #CONTENT_DIRECTORY} to the contact URI. See 1466 * {@link RawContactsEntity} for a stand-alone table containing the same 1467 * data. 1468 * </p> 1469 * <p> 1470 * The Entity directory is similar to the {@link RawContacts.Data} 1471 * directory but with two important differences: 1472 * <ul> 1473 * <li>Entity has different ID fields: {@link #_ID} for the raw contact 1474 * and {@link #DATA_ID} for the data rows.</li> 1475 * <li>Entity always contains at least one row, even if there are no 1476 * actual data rows. In this case the {@link #DATA_ID} field will be 1477 * null.</li> 1478 * </ul> 1479 * Using Entity should preferred to using two separate queries: 1480 * RawContacts followed by Data. The reason is that Entity reads all 1481 * data for a raw contact in one transaction, so there is no possibility 1482 * of the data changing between the two queries. 1483 */ 1484 public static final class Entity implements BaseColumns, DataColumns { 1485 /** 1486 * no public constructor since this is a utility class 1487 */ 1488 private Entity() { 1489 } 1490 1491 /** 1492 * The directory twig for this sub-table 1493 */ 1494 public static final String CONTENT_DIRECTORY = "entity"; 1495 1496 /** 1497 * The ID of the data column. The value will be null if this raw contact has no 1498 * data rows. 1499 * <P>Type: INTEGER</P> 1500 */ 1501 public static final String DATA_ID = "data_id"; 1502 } 1503 1504 public static EntityIterator newEntityIterator(Cursor cursor) { 1505 return new EntityIteratorImpl(cursor); 1506 } 1507 1508 private static class EntityIteratorImpl extends CursorEntityIterator { 1509 private static final String[] DATA_KEYS = new String[]{ 1510 Data.DATA1, 1511 Data.DATA2, 1512 Data.DATA3, 1513 Data.DATA4, 1514 Data.DATA5, 1515 Data.DATA6, 1516 Data.DATA7, 1517 Data.DATA8, 1518 Data.DATA9, 1519 Data.DATA10, 1520 Data.DATA11, 1521 Data.DATA12, 1522 Data.DATA13, 1523 Data.DATA14, 1524 Data.DATA15, 1525 Data.SYNC1, 1526 Data.SYNC2, 1527 Data.SYNC3, 1528 Data.SYNC4}; 1529 1530 public EntityIteratorImpl(Cursor cursor) { 1531 super(cursor); 1532 } 1533 1534 @Override 1535 public android.content.Entity getEntityAndIncrementCursor(Cursor cursor) 1536 throws RemoteException { 1537 final int columnRawContactId = cursor.getColumnIndexOrThrow(RawContacts._ID); 1538 final long rawContactId = cursor.getLong(columnRawContactId); 1539 1540 // we expect the cursor is already at the row we need to read from 1541 ContentValues cv = new ContentValues(); 1542 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_NAME); 1543 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_TYPE); 1544 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, _ID); 1545 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DIRTY); 1546 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, VERSION); 1547 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SOURCE_ID); 1548 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC1); 1549 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC2); 1550 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC3); 1551 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC4); 1552 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DELETED); 1553 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID); 1554 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED); 1555 DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, IS_RESTRICTED); 1556 android.content.Entity contact = new android.content.Entity(cv); 1557 1558 // read data rows until the contact id changes 1559 do { 1560 if (rawContactId != cursor.getLong(columnRawContactId)) { 1561 break; 1562 } 1563 // add the data to to the contact 1564 cv = new ContentValues(); 1565 cv.put(Data._ID, cursor.getLong(cursor.getColumnIndexOrThrow(Entity.DATA_ID))); 1566 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 1567 Data.RES_PACKAGE); 1568 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Data.MIMETYPE); 1569 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.IS_PRIMARY); 1570 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, 1571 Data.IS_SUPER_PRIMARY); 1572 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.DATA_VERSION); 1573 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 1574 CommonDataKinds.GroupMembership.GROUP_SOURCE_ID); 1575 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 1576 Data.DATA_VERSION); 1577 for (String key : DATA_KEYS) { 1578 final int columnIndex = cursor.getColumnIndexOrThrow(key); 1579 if (cursor.isNull(columnIndex)) { 1580 // don't put anything 1581 } else { 1582 try { 1583 cv.put(key, cursor.getString(columnIndex)); 1584 } catch (SQLiteException e) { 1585 cv.put(key, cursor.getBlob(columnIndex)); 1586 } 1587 } 1588 // TODO: go back to this version of the code when bug 1589 // http://b/issue?id=2306370 is fixed. 1590// if (cursor.isNull(columnIndex)) { 1591// // don't put anything 1592// } else if (cursor.isLong(columnIndex)) { 1593// values.put(key, cursor.getLong(columnIndex)); 1594// } else if (cursor.isFloat(columnIndex)) { 1595// values.put(key, cursor.getFloat(columnIndex)); 1596// } else if (cursor.isString(columnIndex)) { 1597// values.put(key, cursor.getString(columnIndex)); 1598// } else if (cursor.isBlob(columnIndex)) { 1599// values.put(key, cursor.getBlob(columnIndex)); 1600// } 1601 } 1602 contact.addSubValue(ContactsContract.Data.CONTENT_URI, cv); 1603 } while (cursor.moveToNext()); 1604 1605 return contact; 1606 } 1607 1608 } 1609 } 1610 1611 /** 1612 * Social status update columns. 1613 * 1614 * @see StatusUpdates 1615 * @see ContactsContract.Data 1616 */ 1617 protected interface StatusColumns { 1618 /** 1619 * Contact's latest presence level. 1620 * <P>Type: INTEGER (one of the values below)</P> 1621 */ 1622 public static final String PRESENCE = "mode"; 1623 1624 /** 1625 * @deprecated use {@link #PRESENCE} 1626 */ 1627 @Deprecated 1628 public static final String PRESENCE_STATUS = PRESENCE; 1629 1630 /** 1631 * An allowed value of {@link #PRESENCE}. 1632 */ 1633 int OFFLINE = 0; 1634 1635 /** 1636 * An allowed value of {@link #PRESENCE}. 1637 */ 1638 int INVISIBLE = 1; 1639 1640 /** 1641 * An allowed value of {@link #PRESENCE}. 1642 */ 1643 int AWAY = 2; 1644 1645 /** 1646 * An allowed value of {@link #PRESENCE}. 1647 */ 1648 int IDLE = 3; 1649 1650 /** 1651 * An allowed value of {@link #PRESENCE}. 1652 */ 1653 int DO_NOT_DISTURB = 4; 1654 1655 /** 1656 * An allowed value of {@link #PRESENCE}. 1657 */ 1658 int AVAILABLE = 5; 1659 1660 /** 1661 * Contact latest status update. 1662 * <p>Type: TEXT</p> 1663 */ 1664 public static final String STATUS = "status"; 1665 1666 /** 1667 * @deprecated use {@link #STATUS} 1668 */ 1669 @Deprecated 1670 public static final String PRESENCE_CUSTOM_STATUS = STATUS; 1671 1672 /** 1673 * The absolute time in milliseconds when the latest status was inserted/updated. 1674 * <p>Type: NUMBER</p> 1675 */ 1676 public static final String STATUS_TIMESTAMP = "status_ts"; 1677 1678 /** 1679 * The package containing resources for this status: label and icon. 1680 * <p>Type: NUMBER</p> 1681 */ 1682 public static final String STATUS_RES_PACKAGE = "status_res_package"; 1683 1684 /** 1685 * The resource ID of the label describing the source of the status update, e.g. "Google 1686 * Talk". This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. 1687 * <p>Type: NUMBER</p> 1688 */ 1689 public static final String STATUS_LABEL = "status_label"; 1690 1691 /** 1692 * The resource ID of the icon for the source of the status update. 1693 * This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. 1694 * <p>Type: NUMBER</p> 1695 */ 1696 public static final String STATUS_ICON = "status_icon"; 1697 } 1698 1699 /** 1700 * Columns in the Data table. 1701 * 1702 * @see ContactsContract.Data 1703 */ 1704 protected interface DataColumns { 1705 /** 1706 * The package name to use when creating {@link Resources} objects for 1707 * this data row. This value is only designed for use when building user 1708 * interfaces, and should not be used to infer the owner. 1709 * 1710 * @hide 1711 */ 1712 public static final String RES_PACKAGE = "res_package"; 1713 1714 /** 1715 * The MIME type of the item represented by this row. 1716 */ 1717 public static final String MIMETYPE = "mimetype"; 1718 1719 /** 1720 * A reference to the {@link RawContacts#_ID} 1721 * that this data belongs to. 1722 */ 1723 public static final String RAW_CONTACT_ID = "raw_contact_id"; 1724 1725 /** 1726 * Whether this is the primary entry of its kind for the raw contact it belongs to. 1727 * <P>Type: INTEGER (if set, non-0 means true)</P> 1728 */ 1729 public static final String IS_PRIMARY = "is_primary"; 1730 1731 /** 1732 * Whether this is the primary entry of its kind for the aggregate 1733 * contact it belongs to. Any data record that is "super primary" must 1734 * also be "primary". 1735 * <P>Type: INTEGER (if set, non-0 means true)</P> 1736 */ 1737 public static final String IS_SUPER_PRIMARY = "is_super_primary"; 1738 1739 /** 1740 * The version of this data record. This is a read-only value. The data column is 1741 * guaranteed to not change without the version going up. This value is monotonically 1742 * increasing. 1743 * <P>Type: INTEGER</P> 1744 */ 1745 public static final String DATA_VERSION = "data_version"; 1746 1747 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1748 public static final String DATA1 = "data1"; 1749 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1750 public static final String DATA2 = "data2"; 1751 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1752 public static final String DATA3 = "data3"; 1753 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1754 public static final String DATA4 = "data4"; 1755 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1756 public static final String DATA5 = "data5"; 1757 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1758 public static final String DATA6 = "data6"; 1759 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1760 public static final String DATA7 = "data7"; 1761 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1762 public static final String DATA8 = "data8"; 1763 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1764 public static final String DATA9 = "data9"; 1765 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1766 public static final String DATA10 = "data10"; 1767 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1768 public static final String DATA11 = "data11"; 1769 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1770 public static final String DATA12 = "data12"; 1771 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1772 public static final String DATA13 = "data13"; 1773 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 1774 public static final String DATA14 = "data14"; 1775 /** 1776 * Generic data column, the meaning is {@link #MIMETYPE} specific. By convention, 1777 * this field is used to store BLOBs (binary data). 1778 */ 1779 public static final String DATA15 = "data15"; 1780 1781 /** Generic column for use by sync adapters. */ 1782 public static final String SYNC1 = "data_sync1"; 1783 /** Generic column for use by sync adapters. */ 1784 public static final String SYNC2 = "data_sync2"; 1785 /** Generic column for use by sync adapters. */ 1786 public static final String SYNC3 = "data_sync3"; 1787 /** Generic column for use by sync adapters. */ 1788 public static final String SYNC4 = "data_sync4"; 1789 } 1790 1791 /** 1792 * Combines all columns returned by {@link ContactsContract.Data} table queries. 1793 * 1794 * @see ContactsContract.Data 1795 */ 1796 protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns, 1797 RawContactsColumns, ContactsColumns, ContactNameColumns, ContactOptionsColumns, 1798 ContactStatusColumns { 1799 } 1800 1801 /** 1802 * <p> 1803 * Constants for the data table, which contains data points tied to a raw 1804 * contact. Each row of the data table is typically used to store a single 1805 * piece of contact 1806 * information (such as a phone number) and its 1807 * associated metadata (such as whether it is a work or home number). 1808 * </p> 1809 * <h3>Data kinds</h3> 1810 * <p> 1811 * Data is a generic table that can hold any kind of contact data. 1812 * The kind of data stored in a given row is specified by the row's 1813 * {@link #MIMETYPE} value, which determines the meaning of the 1814 * generic columns {@link #DATA1} through 1815 * {@link #DATA15}. 1816 * For example, if the data kind is 1817 * {@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}, then the column 1818 * {@link #DATA1} stores the 1819 * phone number, but if the data kind is 1820 * {@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}, then {@link #DATA1} 1821 * stores the email address. 1822 * Sync adapters and applications can introduce their own data kinds. 1823 * </p> 1824 * <p> 1825 * ContactsContract defines a small number of pre-defined data kinds, e.g. 1826 * {@link CommonDataKinds.Phone}, {@link CommonDataKinds.Email} etc. As a 1827 * convenience, these classes define data kind specific aliases for DATA1 etc. 1828 * For example, {@link CommonDataKinds.Phone Phone.NUMBER} is the same as 1829 * {@link ContactsContract.Data Data.DATA1}. 1830 * </p> 1831 * <p> 1832 * {@link #DATA1} is an indexed column and should be used for the data element that is 1833 * expected to be most frequently used in query selections. For example, in the 1834 * case of a row representing email addresses {@link #DATA1} should probably 1835 * be used for the email address itself, while {@link #DATA2} etc can be 1836 * used for auxiliary information like type of email address. 1837 * <p> 1838 * <p> 1839 * By convention, {@link #DATA15} is used for storing BLOBs (binary data). 1840 * </p> 1841 * <p> 1842 * Typically you should refrain from introducing new kinds of data for an other 1843 * party's account types. For example, if you add a data row for 1844 * "favorite song" to a raw contact owned by a Google account, it will not 1845 * get synced to the server, because the Google sync adapter does not know 1846 * how to handle this data kind. Thus new data kinds are typically 1847 * introduced along with new account types, i.e. new sync adapters. 1848 * </p> 1849 * <h3>Batch operations</h3> 1850 * <p> 1851 * Data rows can be inserted/updated/deleted using the traditional 1852 * {@link ContentResolver#insert}, {@link ContentResolver#update} and 1853 * {@link ContentResolver#delete} methods, however the newer mechanism based 1854 * on a batch of {@link ContentProviderOperation} will prove to be a better 1855 * choice in almost all cases. All operations in a batch are executed in a 1856 * single transaction, which ensures that the phone-side and server-side 1857 * state of a raw contact are always consistent. Also, the batch-based 1858 * approach is far more efficient: not only are the database operations 1859 * faster when executed in a single transaction, but also sending a batch of 1860 * commands to the content provider saves a lot of time on context switching 1861 * between your process and the process in which the content provider runs. 1862 * </p> 1863 * <p> 1864 * The flip side of using batched operations is that a large batch may lock 1865 * up the database for a long time preventing other applications from 1866 * accessing data and potentially causing ANRs ("Application Not Responding" 1867 * dialogs.) 1868 * </p> 1869 * <p> 1870 * To avoid such lockups of the database, make sure to insert "yield points" 1871 * in the batch. A yield point indicates to the content provider that before 1872 * executing the next operation it can commit the changes that have already 1873 * been made, yield to other requests, open another transaction and continue 1874 * processing operations. A yield point will not automatically commit the 1875 * transaction, but only if there is another request waiting on the 1876 * database. Normally a sync adapter should insert a yield point at the 1877 * beginning of each raw contact operation sequence in the batch. See 1878 * {@link ContentProviderOperation.Builder#withYieldAllowed(boolean)}. 1879 * </p> 1880 * <h3>Operations</h3> 1881 * <dl> 1882 * <dt><b>Insert</b></dt> 1883 * <dd> 1884 * <p> 1885 * An individual data row can be inserted using the traditional 1886 * {@link ContentResolver#insert(Uri, ContentValues)} method. Multiple rows 1887 * should always be inserted as a batch. 1888 * </p> 1889 * <p> 1890 * An example of a traditional insert: 1891 * <pre> 1892 * ContentValues values = new ContentValues(); 1893 * values.put(Data.RAW_CONTACT_ID, rawContactId); 1894 * values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 1895 * values.put(Phone.NUMBER, "1-800-GOOG-411"); 1896 * values.put(Phone.TYPE, Phone.TYPE_CUSTOM); 1897 * values.put(Phone.LABEL, "free directory assistance"); 1898 * Uri dataUri = getContentResolver().insert(Data.CONTENT_URI, values); 1899 * </pre> 1900 * <p> 1901 * The same done using ContentProviderOperations: 1902 * <pre> 1903 * ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 1904 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 1905 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 1906 * .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE) 1907 * .withValue(Phone.NUMBER, "1-800-GOOG-411") 1908 * .withValue(Phone.TYPE, Phone.TYPE_CUSTOM) 1909 * .withValue(Phone.LABEL, "free directory assistance") 1910 * .build()); 1911 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 1912 * </pre> 1913 * </p> 1914 * <dt><b>Update</b></dt> 1915 * <dd> 1916 * <p> 1917 * Just as with insert, update can be done incrementally or as a batch, 1918 * the batch mode being the preferred method: 1919 * <pre> 1920 * ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 1921 * ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI) 1922 * .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}) 1923 * .withValue(Email.DATA, "somebody@android.com") 1924 * .build()); 1925 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 1926 * </pre> 1927 * </p> 1928 * </dd> 1929 * <dt><b>Delete</b></dt> 1930 * <dd> 1931 * <p> 1932 * Just as with insert and update, deletion can be done either using the 1933 * {@link ContentResolver#delete} method or using a ContentProviderOperation: 1934 * <pre> 1935 * ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 1936 * ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI) 1937 * .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}) 1938 * .build()); 1939 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 1940 * </pre> 1941 * </p> 1942 * </dd> 1943 * <dt><b>Query</b></dt> 1944 * <dd> 1945 * <p> 1946 * <dl> 1947 * <dt>Finding all Data of a given type for a given contact</dt> 1948 * <dd> 1949 * <pre> 1950 * Cursor c = getContentResolver().query(Data.CONTENT_URI, 1951 * new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL}, 1952 * Data.CONTACT_ID + "=?" + " AND " 1953 * + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", 1954 * new String[] {String.valueOf(contactId)}, null); 1955 * </pre> 1956 * </p> 1957 * <p> 1958 * </dd> 1959 * <dt>Finding all Data of a given type for a given raw contact</dt> 1960 * <dd> 1961 * <pre> 1962 * Cursor c = getContentResolver().query(Data.CONTENT_URI, 1963 * new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL}, 1964 * Data.RAW_CONTACT_ID + "=?" + " AND " 1965 * + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", 1966 * new String[] {String.valueOf(rawContactId)}, null); 1967 * </pre> 1968 * </dd> 1969 * <dt>Finding all Data for a given raw contact</dt> 1970 * <dd> 1971 * Most sync adapters will want to read all data rows for a raw contact 1972 * along with the raw contact itself. For that you should use the 1973 * {@link RawContactsEntity}. See also {@link RawContacts}. 1974 * </dd> 1975 * </dl> 1976 * </p> 1977 * </dd> 1978 * </dl> 1979 * <h2>Columns</h2> 1980 * <p> 1981 * Many columns are available via a {@link Data#CONTENT_URI} query. For best performance you 1982 * should explicitly specify a projection to only those columns that you need. 1983 * </p> 1984 * <table class="jd-sumtable"> 1985 * <tr> 1986 * <th colspan='4'>Data</th> 1987 * </tr> 1988 * <tr> 1989 * <td style="width: 7em;">long</td> 1990 * <td style="width: 20em;">{@link #_ID}</td> 1991 * <td style="width: 5em;">read-only</td> 1992 * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words, 1993 * it would be a bad idea to delete and reinsert a data row. A sync adapter should 1994 * always do an update instead.</td> 1995 * </tr> 1996 * <tr> 1997 * <td>String</td> 1998 * <td>{@link #MIMETYPE}</td> 1999 * <td>read/write-once</td> 2000 * <td> 2001 * <p>The MIME type of the item represented by this row. Examples of common 2002 * MIME types are: 2003 * <ul> 2004 * <li>{@link CommonDataKinds.StructuredName StructuredName.CONTENT_ITEM_TYPE}</li> 2005 * <li>{@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}</li> 2006 * <li>{@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}</li> 2007 * <li>{@link CommonDataKinds.Photo Photo.CONTENT_ITEM_TYPE}</li> 2008 * <li>{@link CommonDataKinds.Organization Organization.CONTENT_ITEM_TYPE}</li> 2009 * <li>{@link CommonDataKinds.Im Im.CONTENT_ITEM_TYPE}</li> 2010 * <li>{@link CommonDataKinds.Nickname Nickname.CONTENT_ITEM_TYPE}</li> 2011 * <li>{@link CommonDataKinds.Note Note.CONTENT_ITEM_TYPE}</li> 2012 * <li>{@link CommonDataKinds.StructuredPostal StructuredPostal.CONTENT_ITEM_TYPE}</li> 2013 * <li>{@link CommonDataKinds.GroupMembership GroupMembership.CONTENT_ITEM_TYPE}</li> 2014 * <li>{@link CommonDataKinds.Website Website.CONTENT_ITEM_TYPE}</li> 2015 * <li>{@link CommonDataKinds.Event Event.CONTENT_ITEM_TYPE}</li> 2016 * <li>{@link CommonDataKinds.Relation Relation.CONTENT_ITEM_TYPE}</li> 2017 * </ul> 2018 * </p> 2019 * </td> 2020 * </tr> 2021 * <tr> 2022 * <td>long</td> 2023 * <td>{@link #RAW_CONTACT_ID}</td> 2024 * <td>read/write-once</td> 2025 * <td>The id of the row in the {@link RawContacts} table that this data belongs to.</td> 2026 * </tr> 2027 * <tr> 2028 * <td>int</td> 2029 * <td>{@link #IS_PRIMARY}</td> 2030 * <td>read/write</td> 2031 * <td>Whether this is the primary entry of its kind for the raw contact it belongs to. 2032 * "1" if true, "0" if false. 2033 * </td> 2034 * </tr> 2035 * <tr> 2036 * <td>int</td> 2037 * <td>{@link #IS_SUPER_PRIMARY}</td> 2038 * <td>read/write</td> 2039 * <td>Whether this is the primary entry of its kind for the aggregate 2040 * contact it belongs to. Any data record that is "super primary" must 2041 * also be "primary". For example, the super-primary entry may be 2042 * interpreted as the default contact value of its kind (for example, 2043 * the default phone number to use for the contact).</td> 2044 * </tr> 2045 * <tr> 2046 * <td>int</td> 2047 * <td>{@link #DATA_VERSION}</td> 2048 * <td>read-only</td> 2049 * <td>The version of this data record. Whenever the data row changes 2050 * the version goes up. This value is monotonically increasing.</td> 2051 * </tr> 2052 * <tr> 2053 * <td>Any type</td> 2054 * <td> 2055 * {@link #DATA1}<br> 2056 * {@link #DATA2}<br> 2057 * {@link #DATA3}<br> 2058 * {@link #DATA4}<br> 2059 * {@link #DATA5}<br> 2060 * {@link #DATA6}<br> 2061 * {@link #DATA7}<br> 2062 * {@link #DATA8}<br> 2063 * {@link #DATA9}<br> 2064 * {@link #DATA10}<br> 2065 * {@link #DATA11}<br> 2066 * {@link #DATA12}<br> 2067 * {@link #DATA13}<br> 2068 * {@link #DATA14}<br> 2069 * {@link #DATA15} 2070 * </td> 2071 * <td>read/write</td> 2072 * <td> 2073 * <p> 2074 * Generic data columns. The meaning of each column is determined by the 2075 * {@link #MIMETYPE}. By convention, {@link #DATA15} is used for storing 2076 * BLOBs (binary data). 2077 * </p> 2078 * <p> 2079 * Data columns whose meaning is not explicitly defined for a given MIMETYPE 2080 * should not be used. There is no guarantee that any sync adapter will 2081 * preserve them. Sync adapters themselves should not use such columns either, 2082 * but should instead use {@link #SYNC1}-{@link #SYNC4}. 2083 * </p> 2084 * </td> 2085 * </tr> 2086 * <tr> 2087 * <td>Any type</td> 2088 * <td> 2089 * {@link #SYNC1}<br> 2090 * {@link #SYNC2}<br> 2091 * {@link #SYNC3}<br> 2092 * {@link #SYNC4} 2093 * </td> 2094 * <td>read/write</td> 2095 * <td>Generic columns for use by sync adapters. For example, a Photo row 2096 * may store the image URL in SYNC1, a status (not loaded, loading, loaded, error) 2097 * in SYNC2, server-side version number in SYNC3 and error code in SYNC4.</td> 2098 * </tr> 2099 * </table> 2100 * 2101 * <p> 2102 * Some columns from the most recent associated status update are also available 2103 * through an implicit join. 2104 * </p> 2105 * <table class="jd-sumtable"> 2106 * <tr> 2107 * <th colspan='4'>Join with {@link StatusUpdates}</th> 2108 * </tr> 2109 * <tr> 2110 * <td style="width: 7em;">int</td> 2111 * <td style="width: 20em;">{@link #PRESENCE}</td> 2112 * <td style="width: 5em;">read-only</td> 2113 * <td>IM presence status linked to this data row. Compare with 2114 * {@link #CONTACT_PRESENCE}, which contains the contact's presence across 2115 * all IM rows. See {@link StatusUpdates} for individual status definitions. 2116 * The provider may choose not to store this value 2117 * in persistent storage. The expectation is that presence status will be 2118 * updated on a regular basic. 2119 * </td> 2120 * </tr> 2121 * <tr> 2122 * <td>String</td> 2123 * <td>{@link #STATUS}</td> 2124 * <td>read-only</td> 2125 * <td>Latest status update linked with this data row.</td> 2126 * </tr> 2127 * <tr> 2128 * <td>long</td> 2129 * <td>{@link #STATUS_TIMESTAMP}</td> 2130 * <td>read-only</td> 2131 * <td>The absolute time in milliseconds when the latest status was 2132 * inserted/updated for this data row.</td> 2133 * </tr> 2134 * <tr> 2135 * <td>String</td> 2136 * <td>{@link #STATUS_RES_PACKAGE}</td> 2137 * <td>read-only</td> 2138 * <td>The package containing resources for this status: label and icon.</td> 2139 * </tr> 2140 * <tr> 2141 * <td>long</td> 2142 * <td>{@link #STATUS_LABEL}</td> 2143 * <td>read-only</td> 2144 * <td>The resource ID of the label describing the source of status update linked 2145 * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 2146 * </tr> 2147 * <tr> 2148 * <td>long</td> 2149 * <td>{@link #STATUS_ICON}</td> 2150 * <td>read-only</td> 2151 * <td>The resource ID of the icon for the source of the status update linked 2152 * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 2153 * </tr> 2154 * </table> 2155 * 2156 * <p> 2157 * Some columns from the associated raw contact are also available through an 2158 * implicit join. The other columns are excluded as uninteresting in this 2159 * context. 2160 * </p> 2161 * 2162 * <table class="jd-sumtable"> 2163 * <tr> 2164 * <th colspan='4'>Join with {@link ContactsContract.RawContacts}</th> 2165 * </tr> 2166 * <tr> 2167 * <td style="width: 7em;">long</td> 2168 * <td style="width: 20em;">{@link #CONTACT_ID}</td> 2169 * <td style="width: 5em;">read-only</td> 2170 * <td>The id of the row in the {@link Contacts} table that this data belongs 2171 * to.</td> 2172 * </tr> 2173 * <tr> 2174 * <td>int</td> 2175 * <td>{@link #AGGREGATION_MODE}</td> 2176 * <td>read-only</td> 2177 * <td>See {@link RawContacts}.</td> 2178 * </tr> 2179 * <tr> 2180 * <td>int</td> 2181 * <td>{@link #DELETED}</td> 2182 * <td>read-only</td> 2183 * <td>See {@link RawContacts}.</td> 2184 * </tr> 2185 * </table> 2186 * 2187 * <p> 2188 * The ID column for the associated aggregated contact table 2189 * {@link ContactsContract.Contacts} is available 2190 * via the implicit join to the {@link RawContacts} table, see above. 2191 * The remaining columns from this table are also 2192 * available, through an implicit join. This 2193 * facilitates lookup by 2194 * the value of a single data element, such as the email address. 2195 * </p> 2196 * 2197 * <table class="jd-sumtable"> 2198 * <tr> 2199 * <th colspan='4'>Join with {@link ContactsContract.Contacts}</th> 2200 * </tr> 2201 * <tr> 2202 * <td style="width: 7em;">String</td> 2203 * <td style="width: 20em;">{@link #LOOKUP_KEY}</td> 2204 * <td style="width: 5em;">read-only</td> 2205 * <td>See {@link ContactsContract.Contacts}</td> 2206 * </tr> 2207 * <tr> 2208 * <td>String</td> 2209 * <td>{@link #DISPLAY_NAME}</td> 2210 * <td>read-only</td> 2211 * <td>See {@link ContactsContract.Contacts}</td> 2212 * </tr> 2213 * <tr> 2214 * <td>long</td> 2215 * <td>{@link #PHOTO_ID}</td> 2216 * <td>read-only</td> 2217 * <td>See {@link ContactsContract.Contacts}.</td> 2218 * </tr> 2219 * <tr> 2220 * <td>int</td> 2221 * <td>{@link #IN_VISIBLE_GROUP}</td> 2222 * <td>read-only</td> 2223 * <td>See {@link ContactsContract.Contacts}.</td> 2224 * </tr> 2225 * <tr> 2226 * <td>int</td> 2227 * <td>{@link #HAS_PHONE_NUMBER}</td> 2228 * <td>read-only</td> 2229 * <td>See {@link ContactsContract.Contacts}.</td> 2230 * </tr> 2231 * <tr> 2232 * <td>int</td> 2233 * <td>{@link #TIMES_CONTACTED}</td> 2234 * <td>read-only</td> 2235 * <td>See {@link ContactsContract.Contacts}.</td> 2236 * </tr> 2237 * <tr> 2238 * <td>long</td> 2239 * <td>{@link #LAST_TIME_CONTACTED}</td> 2240 * <td>read-only</td> 2241 * <td>See {@link ContactsContract.Contacts}.</td> 2242 * </tr> 2243 * <tr> 2244 * <td>int</td> 2245 * <td>{@link #STARRED}</td> 2246 * <td>read-only</td> 2247 * <td>See {@link ContactsContract.Contacts}.</td> 2248 * </tr> 2249 * <tr> 2250 * <td>String</td> 2251 * <td>{@link #CUSTOM_RINGTONE}</td> 2252 * <td>read-only</td> 2253 * <td>See {@link ContactsContract.Contacts}.</td> 2254 * </tr> 2255 * <tr> 2256 * <td>int</td> 2257 * <td>{@link #SEND_TO_VOICEMAIL}</td> 2258 * <td>read-only</td> 2259 * <td>See {@link ContactsContract.Contacts}.</td> 2260 * </tr> 2261 * <tr> 2262 * <td>int</td> 2263 * <td>{@link #CONTACT_PRESENCE}</td> 2264 * <td>read-only</td> 2265 * <td>See {@link ContactsContract.Contacts}.</td> 2266 * </tr> 2267 * <tr> 2268 * <td>String</td> 2269 * <td>{@link #CONTACT_STATUS}</td> 2270 * <td>read-only</td> 2271 * <td>See {@link ContactsContract.Contacts}.</td> 2272 * </tr> 2273 * <tr> 2274 * <td>long</td> 2275 * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td> 2276 * <td>read-only</td> 2277 * <td>See {@link ContactsContract.Contacts}.</td> 2278 * </tr> 2279 * <tr> 2280 * <td>String</td> 2281 * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td> 2282 * <td>read-only</td> 2283 * <td>See {@link ContactsContract.Contacts}.</td> 2284 * </tr> 2285 * <tr> 2286 * <td>long</td> 2287 * <td>{@link #CONTACT_STATUS_LABEL}</td> 2288 * <td>read-only</td> 2289 * <td>See {@link ContactsContract.Contacts}.</td> 2290 * </tr> 2291 * <tr> 2292 * <td>long</td> 2293 * <td>{@link #CONTACT_STATUS_ICON}</td> 2294 * <td>read-only</td> 2295 * <td>See {@link ContactsContract.Contacts}.</td> 2296 * </tr> 2297 * </table> 2298 */ 2299 public final static class Data implements DataColumnsWithJoins { 2300 /** 2301 * This utility class cannot be instantiated 2302 */ 2303 private Data() {} 2304 2305 /** 2306 * The content:// style URI for this table, which requests a directory 2307 * of data rows matching the selection criteria. 2308 */ 2309 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data"); 2310 2311 /** 2312 * The MIME type of the results from {@link #CONTENT_URI}. 2313 */ 2314 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; 2315 2316 /** 2317 * <p> 2318 * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward 2319 * Data.CONTENT_URI contains only exportable data. 2320 * </p> 2321 * <p> 2322 * This flag is useful (currently) only for vCard exporter in Contacts app, which 2323 * needs to exclude "un-exportable" data from available data to export, while 2324 * Contacts app itself has priviledge to access all data including "un-exportable" 2325 * ones and providers return all of them regardless of the callers' intention. 2326 * </p> 2327 * <p> 2328 * Type: INTEGER 2329 * </p> 2330 * 2331 * @hide Maybe available only in Eclair and not really ready for public use. 2332 * TODO: remove, or implement this feature completely. As of now (Eclair), 2333 * we only use this flag in queryEntities(), not query(). 2334 */ 2335 public static final String FOR_EXPORT_ONLY = "for_export_only"; 2336 2337 /** 2338 * <p> 2339 * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 2340 * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} 2341 * entry of the given {@link ContactsContract.Data} entry. 2342 * </p> 2343 * <p> 2344 * Returns the Uri for the contact in the first entry returned by 2345 * {@link ContentResolver#query(Uri, String[], String, String[], String)} 2346 * for the provided {@code dataUri}. If the query returns null or empty 2347 * results, silently returns null. 2348 * </p> 2349 */ 2350 public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { 2351 final Cursor cursor = resolver.query(dataUri, new String[] { 2352 RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY 2353 }, null, null, null); 2354 2355 Uri lookupUri = null; 2356 try { 2357 if (cursor != null && cursor.moveToFirst()) { 2358 final long contactId = cursor.getLong(0); 2359 final String lookupKey = cursor.getString(1); 2360 return Contacts.getLookupUri(contactId, lookupKey); 2361 } 2362 } finally { 2363 if (cursor != null) cursor.close(); 2364 } 2365 return lookupUri; 2366 } 2367 } 2368 2369 /** 2370 * <p> 2371 * Constants for the raw contacts entities table, which can be thought of as 2372 * an outer join of the raw_contacts table with the data table. It is a strictly 2373 * read-only table. 2374 * </p> 2375 * <p> 2376 * If a raw contact has data rows, the RawContactsEntity cursor will contain 2377 * a one row for each data row. If the raw contact has no data rows, the 2378 * cursor will still contain one row with the raw contact-level information 2379 * and nulls for data columns. 2380 * 2381 * <pre> 2382 * Uri entityUri = ContentUris.withAppendedId(RawContactsEntity.CONTENT_URI, rawContactId); 2383 * Cursor c = getContentResolver().query(entityUri, 2384 * new String[]{ 2385 * RawContactsEntity.SOURCE_ID, 2386 * RawContactsEntity.DATA_ID, 2387 * RawContactsEntity.MIMETYPE, 2388 * RawContactsEntity.DATA1 2389 * }, null, null, null); 2390 * try { 2391 * while (c.moveToNext()) { 2392 * String sourceId = c.getString(0); 2393 * if (!c.isNull(1)) { 2394 * String mimeType = c.getString(2); 2395 * String data = c.getString(3); 2396 * ... 2397 * } 2398 * } 2399 * } finally { 2400 * c.close(); 2401 * } 2402 * </pre> 2403 * 2404 * <h3>Columns</h3> 2405 * RawContactsEntity has a combination of RawContact and Data columns. 2406 * 2407 * <table class="jd-sumtable"> 2408 * <tr> 2409 * <th colspan='4'>RawContacts</th> 2410 * </tr> 2411 * <tr> 2412 * <td style="width: 7em;">long</td> 2413 * <td style="width: 20em;">{@link #_ID}</td> 2414 * <td style="width: 5em;">read-only</td> 2415 * <td>Raw contact row ID. See {@link RawContacts}.</td> 2416 * </tr> 2417 * <tr> 2418 * <td>long</td> 2419 * <td>{@link #CONTACT_ID}</td> 2420 * <td>read-only</td> 2421 * <td>See {@link RawContacts}.</td> 2422 * </tr> 2423 * <tr> 2424 * <td>int</td> 2425 * <td>{@link #AGGREGATION_MODE}</td> 2426 * <td>read-only</td> 2427 * <td>See {@link RawContacts}.</td> 2428 * </tr> 2429 * <tr> 2430 * <td>int</td> 2431 * <td>{@link #DELETED}</td> 2432 * <td>read-only</td> 2433 * <td>See {@link RawContacts}.</td> 2434 * </tr> 2435 * </table> 2436 * 2437 * <table class="jd-sumtable"> 2438 * <tr> 2439 * <th colspan='4'>Data</th> 2440 * </tr> 2441 * <tr> 2442 * <td style="width: 7em;">long</td> 2443 * <td style="width: 20em;">{@link #DATA_ID}</td> 2444 * <td style="width: 5em;">read-only</td> 2445 * <td>Data row ID. It will be null if the raw contact has no data rows.</td> 2446 * </tr> 2447 * <tr> 2448 * <td>String</td> 2449 * <td>{@link #MIMETYPE}</td> 2450 * <td>read-only</td> 2451 * <td>See {@link ContactsContract.Data}.</td> 2452 * </tr> 2453 * <tr> 2454 * <td>int</td> 2455 * <td>{@link #IS_PRIMARY}</td> 2456 * <td>read-only</td> 2457 * <td>See {@link ContactsContract.Data}.</td> 2458 * </tr> 2459 * <tr> 2460 * <td>int</td> 2461 * <td>{@link #IS_SUPER_PRIMARY}</td> 2462 * <td>read-only</td> 2463 * <td>See {@link ContactsContract.Data}.</td> 2464 * </tr> 2465 * <tr> 2466 * <td>int</td> 2467 * <td>{@link #DATA_VERSION}</td> 2468 * <td>read-only</td> 2469 * <td>See {@link ContactsContract.Data}.</td> 2470 * </tr> 2471 * <tr> 2472 * <td>Any type</td> 2473 * <td> 2474 * {@link #DATA1}<br> 2475 * {@link #DATA2}<br> 2476 * {@link #DATA3}<br> 2477 * {@link #DATA4}<br> 2478 * {@link #DATA5}<br> 2479 * {@link #DATA6}<br> 2480 * {@link #DATA7}<br> 2481 * {@link #DATA8}<br> 2482 * {@link #DATA9}<br> 2483 * {@link #DATA10}<br> 2484 * {@link #DATA11}<br> 2485 * {@link #DATA12}<br> 2486 * {@link #DATA13}<br> 2487 * {@link #DATA14}<br> 2488 * {@link #DATA15} 2489 * </td> 2490 * <td>read-only</td> 2491 * <td>See {@link ContactsContract.Data}.</td> 2492 * </tr> 2493 * <tr> 2494 * <td>Any type</td> 2495 * <td> 2496 * {@link #SYNC1}<br> 2497 * {@link #SYNC2}<br> 2498 * {@link #SYNC3}<br> 2499 * {@link #SYNC4} 2500 * </td> 2501 * <td>read-only</td> 2502 * <td>See {@link ContactsContract.Data}.</td> 2503 * </tr> 2504 * </table> 2505 */ 2506 public final static class RawContactsEntity 2507 implements BaseColumns, DataColumns, RawContactsColumns { 2508 /** 2509 * This utility class cannot be instantiated 2510 */ 2511 private RawContactsEntity() {} 2512 2513 /** 2514 * The content:// style URI for this table 2515 */ 2516 public static final Uri CONTENT_URI = 2517 Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities"); 2518 2519 /** 2520 * The MIME type of {@link #CONTENT_URI} providing a directory of raw contact entities. 2521 */ 2522 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity"; 2523 2524 /** 2525 * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward 2526 * Data.CONTENT_URI contains only exportable data. 2527 * 2528 * This flag is useful (currently) only for vCard exporter in Contacts app, which 2529 * needs to exclude "un-exportable" data from available data to export, while 2530 * Contacts app itself has priviledge to access all data including "un-expotable" 2531 * ones and providers return all of them regardless of the callers' intention. 2532 * <P>Type: INTEGER</p> 2533 * 2534 * @hide Maybe available only in Eclair and not really ready for public use. 2535 * TODO: remove, or implement this feature completely. As of now (Eclair), 2536 * we only use this flag in queryEntities(), not query(). 2537 */ 2538 public static final String FOR_EXPORT_ONLY = "for_export_only"; 2539 2540 /** 2541 * The ID of the data column. The value will be null if this raw contact has no data rows. 2542 * <P>Type: INTEGER</P> 2543 */ 2544 public static final String DATA_ID = "data_id"; 2545 } 2546 2547 /** 2548 * @see PhoneLookup 2549 */ 2550 protected interface PhoneLookupColumns { 2551 /** 2552 * The phone number as the user entered it. 2553 * <P>Type: TEXT</P> 2554 */ 2555 public static final String NUMBER = "number"; 2556 2557 /** 2558 * The type of phone number, for example Home or Work. 2559 * <P>Type: INTEGER</P> 2560 */ 2561 public static final String TYPE = "type"; 2562 2563 /** 2564 * The user defined label for the phone number. 2565 * <P>Type: TEXT</P> 2566 */ 2567 public static final String LABEL = "label"; 2568 } 2569 2570 /** 2571 * A table that represents the result of looking up a phone number, for 2572 * example for caller ID. To perform a lookup you must append the number you 2573 * want to find to {@link #CONTENT_FILTER_URI}. This query is highly 2574 * optimized. 2575 * <pre> 2576 * Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); 2577 * resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,... 2578 * </pre> 2579 * 2580 * <h3>Columns</h3> 2581 * 2582 * <table class="jd-sumtable"> 2583 * <tr> 2584 * <th colspan='4'>PhoneLookup</th> 2585 * </tr> 2586 * <tr> 2587 * <td>long</td> 2588 * <td>{@link #_ID}</td> 2589 * <td>read-only</td> 2590 * <td>Data row ID.</td> 2591 * </tr> 2592 * <tr> 2593 * <td>String</td> 2594 * <td>{@link #NUMBER}</td> 2595 * <td>read-only</td> 2596 * <td>Phone number.</td> 2597 * </tr> 2598 * <tr> 2599 * <td>String</td> 2600 * <td>{@link #TYPE}</td> 2601 * <td>read-only</td> 2602 * <td>Phone number type. See {@link CommonDataKinds.Phone}.</td> 2603 * </tr> 2604 * <tr> 2605 * <td>String</td> 2606 * <td>{@link #LABEL}</td> 2607 * <td>read-only</td> 2608 * <td>Custom label for the phone number. See {@link CommonDataKinds.Phone}.</td> 2609 * </tr> 2610 * </table> 2611 * <p> 2612 * Columns from the Contacts table are also available through a join. 2613 * </p> 2614 * <table class="jd-sumtable"> 2615 * <tr> 2616 * <th colspan='4'>Join with {@link Contacts}</th> 2617 * </tr> 2618 * <tr> 2619 * <td>String</td> 2620 * <td>{@link #LOOKUP_KEY}</td> 2621 * <td>read-only</td> 2622 * <td>See {@link ContactsContract.Contacts}</td> 2623 * </tr> 2624 * <tr> 2625 * <td>String</td> 2626 * <td>{@link #DISPLAY_NAME}</td> 2627 * <td>read-only</td> 2628 * <td>See {@link ContactsContract.Contacts}</td> 2629 * </tr> 2630 * <tr> 2631 * <td>long</td> 2632 * <td>{@link #PHOTO_ID}</td> 2633 * <td>read-only</td> 2634 * <td>See {@link ContactsContract.Contacts}.</td> 2635 * </tr> 2636 * <tr> 2637 * <td>int</td> 2638 * <td>{@link #IN_VISIBLE_GROUP}</td> 2639 * <td>read-only</td> 2640 * <td>See {@link ContactsContract.Contacts}.</td> 2641 * </tr> 2642 * <tr> 2643 * <td>int</td> 2644 * <td>{@link #HAS_PHONE_NUMBER}</td> 2645 * <td>read-only</td> 2646 * <td>See {@link ContactsContract.Contacts}.</td> 2647 * </tr> 2648 * <tr> 2649 * <td>int</td> 2650 * <td>{@link #TIMES_CONTACTED}</td> 2651 * <td>read-only</td> 2652 * <td>See {@link ContactsContract.Contacts}.</td> 2653 * </tr> 2654 * <tr> 2655 * <td>long</td> 2656 * <td>{@link #LAST_TIME_CONTACTED}</td> 2657 * <td>read-only</td> 2658 * <td>See {@link ContactsContract.Contacts}.</td> 2659 * </tr> 2660 * <tr> 2661 * <td>int</td> 2662 * <td>{@link #STARRED}</td> 2663 * <td>read-only</td> 2664 * <td>See {@link ContactsContract.Contacts}.</td> 2665 * </tr> 2666 * <tr> 2667 * <td>String</td> 2668 * <td>{@link #CUSTOM_RINGTONE}</td> 2669 * <td>read-only</td> 2670 * <td>See {@link ContactsContract.Contacts}.</td> 2671 * </tr> 2672 * <tr> 2673 * <td>int</td> 2674 * <td>{@link #SEND_TO_VOICEMAIL}</td> 2675 * <td>read-only</td> 2676 * <td>See {@link ContactsContract.Contacts}.</td> 2677 * </tr> 2678 * </table> 2679 */ 2680 public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns, 2681 ContactsColumns, ContactOptionsColumns { 2682 /** 2683 * This utility class cannot be instantiated 2684 */ 2685 private PhoneLookup() {} 2686 2687 /** 2688 * The content:// style URI for this table. Append the phone number you want to lookup 2689 * to this URI and query it to perform a lookup. For example: 2690 * <pre> 2691 * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, Uri.encode(phoneNumber)); 2692 * </pre> 2693 */ 2694 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI, 2695 "phone_lookup"); 2696 } 2697 2698 /** 2699 * Additional data mixed in with {@link StatusColumns} to link 2700 * back to specific {@link ContactsContract.Data#_ID} entries. 2701 * 2702 * @see StatusUpdates 2703 */ 2704 protected interface PresenceColumns { 2705 2706 /** 2707 * Reference to the {@link Data#_ID} entry that owns this presence. 2708 * <P>Type: INTEGER</P> 2709 */ 2710 public static final String DATA_ID = "presence_data_id"; 2711 2712 /** 2713 * See {@link CommonDataKinds.Im} for a list of defined protocol constants. 2714 * <p>Type: NUMBER</p> 2715 */ 2716 public static final String PROTOCOL = "protocol"; 2717 2718 /** 2719 * Name of the custom protocol. Should be supplied along with the {@link #PROTOCOL} value 2720 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. Should be null or 2721 * omitted if {@link #PROTOCOL} value is not 2722 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. 2723 * 2724 * <p>Type: NUMBER</p> 2725 */ 2726 public static final String CUSTOM_PROTOCOL = "custom_protocol"; 2727 2728 /** 2729 * The IM handle the presence item is for. The handle is scoped to 2730 * {@link #PROTOCOL}. 2731 * <P>Type: TEXT</P> 2732 */ 2733 public static final String IM_HANDLE = "im_handle"; 2734 2735 /** 2736 * The IM account for the local user that the presence data came from. 2737 * <P>Type: TEXT</P> 2738 */ 2739 public static final String IM_ACCOUNT = "im_account"; 2740 } 2741 2742 /** 2743 * <p> 2744 * A status update is linked to a {@link ContactsContract.Data} row and captures 2745 * the user's latest status update via the corresponding source, e.g. 2746 * "Having lunch" via "Google Talk". 2747 * </p> 2748 * <p> 2749 * There are two ways a status update can be inserted: by explicitly linking 2750 * it to a Data row using {@link #DATA_ID} or indirectly linking it to a data row 2751 * using a combination of {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and 2752 * {@link #IM_HANDLE}. There is no difference between insert and update, you can use 2753 * either. 2754 * </p> 2755 * <p> 2756 * You cannot use {@link ContentResolver#update} to change a status, but 2757 * {@link ContentResolver#insert} will replace the latests status if it already 2758 * exists. 2759 * </p> 2760 * <p> 2761 * Use {@link ContentResolver#bulkInsert(Uri, ContentValues[])} to insert/update statuses 2762 * for multiple contacts at once. 2763 * </p> 2764 * 2765 * <h3>Columns</h3> 2766 * <table class="jd-sumtable"> 2767 * <tr> 2768 * <th colspan='4'>StatusUpdates</th> 2769 * </tr> 2770 * <tr> 2771 * <td>long</td> 2772 * <td>{@link #DATA_ID}</td> 2773 * <td>read/write</td> 2774 * <td>Reference to the {@link Data#_ID} entry that owns this presence. If this 2775 * field is <i>not</i> specified, the provider will attempt to find a data row 2776 * that matches the {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and 2777 * {@link #IM_HANDLE} columns. 2778 * </td> 2779 * </tr> 2780 * <tr> 2781 * <td>long</td> 2782 * <td>{@link #PROTOCOL}</td> 2783 * <td>read/write</td> 2784 * <td>See {@link CommonDataKinds.Im} for a list of defined protocol constants.</td> 2785 * </tr> 2786 * <tr> 2787 * <td>String</td> 2788 * <td>{@link #CUSTOM_PROTOCOL}</td> 2789 * <td>read/write</td> 2790 * <td>Name of the custom protocol. Should be supplied along with the {@link #PROTOCOL} value 2791 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. Should be null or 2792 * omitted if {@link #PROTOCOL} value is not 2793 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.</td> 2794 * </tr> 2795 * <tr> 2796 * <td>String</td> 2797 * <td>{@link #IM_HANDLE}</td> 2798 * <td>read/write</td> 2799 * <td> The IM handle the presence item is for. The handle is scoped to 2800 * {@link #PROTOCOL}.</td> 2801 * </tr> 2802 * <tr> 2803 * <td>String</td> 2804 * <td>{@link #IM_ACCOUNT}</td> 2805 * <td>read/write</td> 2806 * <td>The IM account for the local user that the presence data came from.</td> 2807 * </tr> 2808 * <tr> 2809 * <td>int</td> 2810 * <td>{@link #PRESENCE}</td> 2811 * <td>read/write</td> 2812 * <td>Contact IM presence status. The allowed values are: 2813 * <p> 2814 * <ul> 2815 * <li>{@link #OFFLINE}</li> 2816 * <li>{@link #INVISIBLE}</li> 2817 * <li>{@link #AWAY}</li> 2818 * <li>{@link #IDLE}</li> 2819 * <li>{@link #DO_NOT_DISTURB}</li> 2820 * <li>{@link #AVAILABLE}</li> 2821 * </ul> 2822 * </p> 2823 * <p> 2824 * Since presence status is inherently volatile, the content provider 2825 * may choose not to store this field in long-term storage. 2826 * </p> 2827 * </td> 2828 * </tr> 2829 * <tr> 2830 * <td>String</td> 2831 * <td>{@link #STATUS}</td> 2832 * <td>read/write</td> 2833 * <td>Contact's latest status update, e.g. "having toast for breakfast"</td> 2834 * </tr> 2835 * <tr> 2836 * <td>long</td> 2837 * <td>{@link #STATUS_TIMESTAMP}</td> 2838 * <td>read/write</td> 2839 * <td>The absolute time in milliseconds when the status was 2840 * entered by the user. If this value is not provided, the provider will follow 2841 * this logic: if there was no prior status update, the value will be left as null. 2842 * If there was a prior status update, the provider will default this field 2843 * to the current time.</td> 2844 * </tr> 2845 * <tr> 2846 * <td>String</td> 2847 * <td>{@link #STATUS_RES_PACKAGE}</td> 2848 * <td>read/write</td> 2849 * <td> The package containing resources for this status: label and icon.</td> 2850 * </tr> 2851 * <tr> 2852 * <td>long</td> 2853 * <td>{@link #STATUS_LABEL}</td> 2854 * <td>read/write</td> 2855 * <td>The resource ID of the label describing the source of contact status, 2856 * e.g. "Google Talk". This resource is scoped by the 2857 * {@link #STATUS_RES_PACKAGE}.</td> 2858 * </tr> 2859 * <tr> 2860 * <td>long</td> 2861 * <td>{@link #STATUS_ICON}</td> 2862 * <td>read/write</td> 2863 * <td>The resource ID of the icon for the source of contact status. This 2864 * resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 2865 * </tr> 2866 * </table> 2867 */ 2868 public static class StatusUpdates implements StatusColumns, PresenceColumns { 2869 2870 /** 2871 * This utility class cannot be instantiated 2872 */ 2873 private StatusUpdates() {} 2874 2875 /** 2876 * The content:// style URI for this table 2877 */ 2878 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "status_updates"); 2879 2880 /** 2881 * Gets the resource ID for the proper presence icon. 2882 * 2883 * @param status the status to get the icon for 2884 * @return the resource ID for the proper presence icon 2885 */ 2886 public static final int getPresenceIconResourceId(int status) { 2887 switch (status) { 2888 case AVAILABLE: 2889 return android.R.drawable.presence_online; 2890 case IDLE: 2891 case AWAY: 2892 return android.R.drawable.presence_away; 2893 case DO_NOT_DISTURB: 2894 return android.R.drawable.presence_busy; 2895 case INVISIBLE: 2896 return android.R.drawable.presence_invisible; 2897 case OFFLINE: 2898 default: 2899 return android.R.drawable.presence_offline; 2900 } 2901 } 2902 2903 /** 2904 * Returns the precedence of the status code the higher number being the higher precedence. 2905 * 2906 * @param status The status code. 2907 * @return An integer representing the precedence, 0 being the lowest. 2908 */ 2909 public static final int getPresencePrecedence(int status) { 2910 // Keep this function here incase we want to enforce a different precedence than the 2911 // natural order of the status constants. 2912 return status; 2913 } 2914 2915 /** 2916 * The MIME type of {@link #CONTENT_URI} providing a directory of 2917 * status update details. 2918 */ 2919 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/status-update"; 2920 2921 /** 2922 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 2923 * status update detail. 2924 */ 2925 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update"; 2926 } 2927 2928 /** 2929 * @deprecated This old name was never meant to be made public. Do not use. 2930 */ 2931 @Deprecated 2932 public static final class Presence extends StatusUpdates { 2933 2934 } 2935 2936 /** 2937 * Container for definitions of common data types stored in the {@link ContactsContract.Data} 2938 * table. 2939 */ 2940 public static final class CommonDataKinds { 2941 /** 2942 * This utility class cannot be instantiated 2943 */ 2944 private CommonDataKinds() {} 2945 2946 /** 2947 * The {@link Data#RES_PACKAGE} value for common data that should be 2948 * shown using a default style. 2949 * 2950 * @hide RES_PACKAGE is hidden 2951 */ 2952 public static final String PACKAGE_COMMON = "common"; 2953 2954 /** 2955 * The base types that all "Typed" data kinds support. 2956 */ 2957 public interface BaseTypes { 2958 /** 2959 * A custom type. The custom label should be supplied by user. 2960 */ 2961 public static int TYPE_CUSTOM = 0; 2962 } 2963 2964 /** 2965 * Columns common across the specific types. 2966 */ 2967 protected interface CommonColumns extends BaseTypes { 2968 /** 2969 * The data for the contact method. 2970 * <P>Type: TEXT</P> 2971 */ 2972 public static final String DATA = DataColumns.DATA1; 2973 2974 /** 2975 * The type of data, for example Home or Work. 2976 * <P>Type: INTEGER</P> 2977 */ 2978 public static final String TYPE = DataColumns.DATA2; 2979 2980 /** 2981 * The user defined label for the the contact method. 2982 * <P>Type: TEXT</P> 2983 */ 2984 public static final String LABEL = DataColumns.DATA3; 2985 } 2986 2987 /** 2988 * A data kind representing the contact's proper name. You can use all 2989 * columns defined for {@link ContactsContract.Data} as well as the following aliases. 2990 * 2991 * <h2>Column aliases</h2> 2992 * <table class="jd-sumtable"> 2993 * <tr> 2994 * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th> 2995 * </tr> 2996 * <tr> 2997 * <td>String</td> 2998 * <td>{@link #DISPLAY_NAME}</td> 2999 * <td>{@link #DATA1}</td> 3000 * <td></td> 3001 * </tr> 3002 * <tr> 3003 * <td>String</td> 3004 * <td>{@link #GIVEN_NAME}</td> 3005 * <td>{@link #DATA2}</td> 3006 * <td></td> 3007 * </tr> 3008 * <tr> 3009 * <td>String</td> 3010 * <td>{@link #FAMILY_NAME}</td> 3011 * <td>{@link #DATA3}</td> 3012 * <td></td> 3013 * </tr> 3014 * <tr> 3015 * <td>String</td> 3016 * <td>{@link #PREFIX}</td> 3017 * <td>{@link #DATA4}</td> 3018 * <td>Common prefixes in English names are "Mr", "Ms", "Dr" etc.</td> 3019 * </tr> 3020 * <tr> 3021 * <td>String</td> 3022 * <td>{@link #MIDDLE_NAME}</td> 3023 * <td>{@link #DATA5}</td> 3024 * <td></td> 3025 * </tr> 3026 * <tr> 3027 * <td>String</td> 3028 * <td>{@link #SUFFIX}</td> 3029 * <td>{@link #DATA6}</td> 3030 * <td>Common suffixes in English names are "Sr", "Jr", "III" etc.</td> 3031 * </tr> 3032 * <tr> 3033 * <td>String</td> 3034 * <td>{@link #PHONETIC_GIVEN_NAME}</td> 3035 * <td>{@link #DATA7}</td> 3036 * <td>Used for phonetic spelling of the name, e.g. Pinyin, Katakana, Hiragana</td> 3037 * </tr> 3038 * <tr> 3039 * <td>String</td> 3040 * <td>{@link #PHONETIC_MIDDLE_NAME}</td> 3041 * <td>{@link #DATA8}</td> 3042 * <td></td> 3043 * </tr> 3044 * <tr> 3045 * <td>String</td> 3046 * <td>{@link #PHONETIC_FAMILY_NAME}</td> 3047 * <td>{@link #DATA9}</td> 3048 * <td></td> 3049 * </tr> 3050 * </table> 3051 */ 3052 public static final class StructuredName implements DataColumnsWithJoins { 3053 /** 3054 * This utility class cannot be instantiated 3055 */ 3056 private StructuredName() {} 3057 3058 /** MIME type used when storing this in data table. */ 3059 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name"; 3060 3061 /** 3062 * The name that should be used to display the contact. 3063 * <i>Unstructured component of the name should be consistent with 3064 * its structured representation.</i> 3065 * <p> 3066 * Type: TEXT 3067 */ 3068 public static final String DISPLAY_NAME = DATA1; 3069 3070 /** 3071 * The given name for the contact. 3072 * <P>Type: TEXT</P> 3073 */ 3074 public static final String GIVEN_NAME = DATA2; 3075 3076 /** 3077 * The family name for the contact. 3078 * <P>Type: TEXT</P> 3079 */ 3080 public static final String FAMILY_NAME = DATA3; 3081 3082 /** 3083 * The contact's honorific prefix, e.g. "Sir" 3084 * <P>Type: TEXT</P> 3085 */ 3086 public static final String PREFIX = DATA4; 3087 3088 /** 3089 * The contact's middle name 3090 * <P>Type: TEXT</P> 3091 */ 3092 public static final String MIDDLE_NAME = DATA5; 3093 3094 /** 3095 * The contact's honorific suffix, e.g. "Jr" 3096 */ 3097 public static final String SUFFIX = DATA6; 3098 3099 /** 3100 * The phonetic version of the given name for the contact. 3101 * <P>Type: TEXT</P> 3102 */ 3103 public static final String PHONETIC_GIVEN_NAME = DATA7; 3104 3105 /** 3106 * The phonetic version of the additional name for the contact. 3107 * <P>Type: TEXT</P> 3108 */ 3109 public static final String PHONETIC_MIDDLE_NAME = DATA8; 3110 3111 /** 3112 * The phonetic version of the family name for the contact. 3113 * <P>Type: TEXT</P> 3114 */ 3115 public static final String PHONETIC_FAMILY_NAME = DATA9; 3116 3117 /** 3118 * The style used for combining given/middle/family name into a full name. 3119 * See {@link ContactsContract.FullNameStyle}. 3120 * 3121 * @hide 3122 */ 3123 public static final String FULL_NAME_STYLE = DATA10; 3124 3125 /** 3126 * The alphabet used for capturing the phonetic name. 3127 * See ContactsContract.PhoneticNameStyle. 3128 * @hide 3129 */ 3130 public static final String PHONETIC_NAME_STYLE = DATA11; 3131 } 3132 3133 /** 3134 * <p>A data kind representing the contact's nickname. For example, for 3135 * Bob Parr ("Mr. Incredible"): 3136 * <pre> 3137 * ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 3138 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 3139 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 3140 * .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 3141 * .withValue(StructuredName.DISPLAY_NAME, "Bob Parr") 3142 * .build()); 3143 * 3144 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 3145 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 3146 * .withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE) 3147 * .withValue(Nickname.NAME, "Mr. Incredible") 3148 * .withValue(Nickname.TYPE, Nickname.TYPE_CUSTOM) 3149 * .withValue(Nickname.LABEL, "Superhero") 3150 * .build()); 3151 * 3152 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 3153 * </pre> 3154 * </p> 3155 * <p> 3156 * You can use all columns defined for {@link ContactsContract.Data} as well as the 3157 * following aliases. 3158 * </p> 3159 * 3160 * <h2>Column aliases</h2> 3161 * <table class="jd-sumtable"> 3162 * <tr> 3163 * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th> 3164 * </tr> 3165 * <tr> 3166 * <td>String</td> 3167 * <td>{@link #NAME}</td> 3168 * <td>{@link #DATA1}</td> 3169 * <td></td> 3170 * </tr> 3171 * <tr> 3172 * <td>int</td> 3173 * <td>{@link #TYPE}</td> 3174 * <td>{@link #DATA2}</td> 3175 * <td> 3176 * Allowed values are: 3177 * <p> 3178 * <ul> 3179 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 3180 * <li>{@link #TYPE_DEFAULT}</li> 3181 * <li>{@link #TYPE_OTHER_NAME}</li> 3182 * <li>{@link #TYPE_MAINDEN_NAME}</li> 3183 * <li>{@link #TYPE_SHORT_NAME}</li> 3184 * <li>{@link #TYPE_INITIALS}</li> 3185 * </ul> 3186 * </p> 3187 * </td> 3188 * </tr> 3189 * <tr> 3190 * <td>String</td> 3191 * <td>{@link #LABEL}</td> 3192 * <td>{@link #DATA3}</td> 3193 * <td></td> 3194 * </tr> 3195 * </table> 3196 */ 3197 public static final class Nickname implements DataColumnsWithJoins, CommonColumns { 3198 /** 3199 * This utility class cannot be instantiated 3200 */ 3201 private Nickname() {} 3202 3203 /** MIME type used when storing this in data table. */ 3204 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname"; 3205 3206 public static final int TYPE_DEFAULT = 1; 3207 public static final int TYPE_OTHER_NAME = 2; 3208 public static final int TYPE_MAINDEN_NAME = 3; 3209 public static final int TYPE_SHORT_NAME = 4; 3210 public static final int TYPE_INITIALS = 5; 3211 3212 /** 3213 * The name itself 3214 */ 3215 public static final String NAME = DATA; 3216 } 3217 3218 /** 3219 * <p> 3220 * A data kind representing a telephone number. 3221 * </p> 3222 * <p> 3223 * You can use all columns defined for {@link ContactsContract.Data} as 3224 * well as the following aliases. 3225 * </p> 3226 * <h2>Column aliases</h2> 3227 * <table class="jd-sumtable"> 3228 * <tr> 3229 * <th>Type</th> 3230 * <th>Alias</th><th colspan='2'>Data column</th> 3231 * </tr> 3232 * <tr> 3233 * <td>String</td> 3234 * <td>{@link #NUMBER}</td> 3235 * <td>{@link #DATA1}</td> 3236 * <td></td> 3237 * </tr> 3238 * <tr> 3239 * <td>int</td> 3240 * <td>{@link #TYPE}</td> 3241 * <td>{@link #DATA2}</td> 3242 * <td>Allowed values are: 3243 * <p> 3244 * <ul> 3245 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 3246 * <li>{@link #TYPE_HOME}</li> 3247 * <li>{@link #TYPE_MOBILE}</li> 3248 * <li>{@link #TYPE_WORK}</li> 3249 * <li>{@link #TYPE_FAX_WORK}</li> 3250 * <li>{@link #TYPE_FAX_HOME}</li> 3251 * <li>{@link #TYPE_PAGER}</li> 3252 * <li>{@link #TYPE_OTHER}</li> 3253 * <li>{@link #TYPE_CALLBACK}</li> 3254 * <li>{@link #TYPE_CAR}</li> 3255 * <li>{@link #TYPE_COMPANY_MAIN}</li> 3256 * <li>{@link #TYPE_ISDN}</li> 3257 * <li>{@link #TYPE_MAIN}</li> 3258 * <li>{@link #TYPE_OTHER_FAX}</li> 3259 * <li>{@link #TYPE_RADIO}</li> 3260 * <li>{@link #TYPE_TELEX}</li> 3261 * <li>{@link #TYPE_TTY_TDD}</li> 3262 * <li>{@link #TYPE_WORK_MOBILE}</li> 3263 * <li>{@link #TYPE_WORK_PAGER}</li> 3264 * <li>{@link #TYPE_ASSISTANT}</li> 3265 * <li>{@link #TYPE_MMS}</li> 3266 * </ul> 3267 * </p> 3268 * </td> 3269 * </tr> 3270 * <tr> 3271 * <td>String</td> 3272 * <td>{@link #LABEL}</td> 3273 * <td>{@link #DATA3}</td> 3274 * <td></td> 3275 * </tr> 3276 * </table> 3277 */ 3278 public static final class Phone implements DataColumnsWithJoins, CommonColumns { 3279 /** 3280 * This utility class cannot be instantiated 3281 */ 3282 private Phone() {} 3283 3284 /** MIME type used when storing this in data table. */ 3285 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2"; 3286 3287 /** 3288 * The MIME type of {@link #CONTENT_URI} providing a directory of 3289 * phones. 3290 */ 3291 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2"; 3292 3293 /** 3294 * The content:// style URI for all data records of the 3295 * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the 3296 * associated raw contact and aggregate contact data. 3297 */ 3298 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 3299 "phones"); 3300 3301 /** 3302 * The content:// style URL for phone lookup using a filter. The filter returns 3303 * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied 3304 * to display names as well as phone numbers. The filter argument should be passed 3305 * as an additional path segment after this URI. 3306 */ 3307 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, 3308 "filter"); 3309 3310 public static final int TYPE_HOME = 1; 3311 public static final int TYPE_MOBILE = 2; 3312 public static final int TYPE_WORK = 3; 3313 public static final int TYPE_FAX_WORK = 4; 3314 public static final int TYPE_FAX_HOME = 5; 3315 public static final int TYPE_PAGER = 6; 3316 public static final int TYPE_OTHER = 7; 3317 public static final int TYPE_CALLBACK = 8; 3318 public static final int TYPE_CAR = 9; 3319 public static final int TYPE_COMPANY_MAIN = 10; 3320 public static final int TYPE_ISDN = 11; 3321 public static final int TYPE_MAIN = 12; 3322 public static final int TYPE_OTHER_FAX = 13; 3323 public static final int TYPE_RADIO = 14; 3324 public static final int TYPE_TELEX = 15; 3325 public static final int TYPE_TTY_TDD = 16; 3326 public static final int TYPE_WORK_MOBILE = 17; 3327 public static final int TYPE_WORK_PAGER = 18; 3328 public static final int TYPE_ASSISTANT = 19; 3329 public static final int TYPE_MMS = 20; 3330 3331 /** 3332 * The phone number as the user entered it. 3333 * <P>Type: TEXT</P> 3334 */ 3335 public static final String NUMBER = DATA; 3336 3337 /** 3338 * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. 3339 * @hide 3340 */ 3341 @Deprecated 3342 public static final CharSequence getDisplayLabel(Context context, int type, 3343 CharSequence label, CharSequence[] labelArray) { 3344 return getTypeLabel(context.getResources(), type, label); 3345 } 3346 3347 /** 3348 * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. 3349 * @hide 3350 */ 3351 @Deprecated 3352 public static final CharSequence getDisplayLabel(Context context, int type, 3353 CharSequence label) { 3354 return getTypeLabel(context.getResources(), type, label); 3355 } 3356 3357 /** 3358 * Return the string resource that best describes the given 3359 * {@link #TYPE}. Will always return a valid resource. 3360 */ 3361 public static final int getTypeLabelResource(int type) { 3362 switch (type) { 3363 case TYPE_HOME: return com.android.internal.R.string.phoneTypeHome; 3364 case TYPE_MOBILE: return com.android.internal.R.string.phoneTypeMobile; 3365 case TYPE_WORK: return com.android.internal.R.string.phoneTypeWork; 3366 case TYPE_FAX_WORK: return com.android.internal.R.string.phoneTypeFaxWork; 3367 case TYPE_FAX_HOME: return com.android.internal.R.string.phoneTypeFaxHome; 3368 case TYPE_PAGER: return com.android.internal.R.string.phoneTypePager; 3369 case TYPE_OTHER: return com.android.internal.R.string.phoneTypeOther; 3370 case TYPE_CALLBACK: return com.android.internal.R.string.phoneTypeCallback; 3371 case TYPE_CAR: return com.android.internal.R.string.phoneTypeCar; 3372 case TYPE_COMPANY_MAIN: return com.android.internal.R.string.phoneTypeCompanyMain; 3373 case TYPE_ISDN: return com.android.internal.R.string.phoneTypeIsdn; 3374 case TYPE_MAIN: return com.android.internal.R.string.phoneTypeMain; 3375 case TYPE_OTHER_FAX: return com.android.internal.R.string.phoneTypeOtherFax; 3376 case TYPE_RADIO: return com.android.internal.R.string.phoneTypeRadio; 3377 case TYPE_TELEX: return com.android.internal.R.string.phoneTypeTelex; 3378 case TYPE_TTY_TDD: return com.android.internal.R.string.phoneTypeTtyTdd; 3379 case TYPE_WORK_MOBILE: return com.android.internal.R.string.phoneTypeWorkMobile; 3380 case TYPE_WORK_PAGER: return com.android.internal.R.string.phoneTypeWorkPager; 3381 case TYPE_ASSISTANT: return com.android.internal.R.string.phoneTypeAssistant; 3382 case TYPE_MMS: return com.android.internal.R.string.phoneTypeMms; 3383 default: return com.android.internal.R.string.phoneTypeCustom; 3384 } 3385 } 3386 3387 /** 3388 * Return a {@link CharSequence} that best describes the given type, 3389 * possibly substituting the given {@link #LABEL} value 3390 * for {@link #TYPE_CUSTOM}. 3391 */ 3392 public static final CharSequence getTypeLabel(Resources res, int type, 3393 CharSequence label) { 3394 if ((type == TYPE_CUSTOM || type == TYPE_ASSISTANT) && !TextUtils.isEmpty(label)) { 3395 return label; 3396 } else { 3397 final int labelRes = getTypeLabelResource(type); 3398 return res.getText(labelRes); 3399 } 3400 } 3401 } 3402 3403 /** 3404 * <p> 3405 * A data kind representing an email address. 3406 * </p> 3407 * <p> 3408 * You can use all columns defined for {@link ContactsContract.Data} as 3409 * well as the following aliases. 3410 * </p> 3411 * <h2>Column aliases</h2> 3412 * <table class="jd-sumtable"> 3413 * <tr> 3414 * <th>Type</th> 3415 * <th>Alias</th><th colspan='2'>Data column</th> 3416 * </tr> 3417 * <tr> 3418 * <td>String</td> 3419 * <td>{@link #DATA}</td> 3420 * <td>{@link #DATA1}</td> 3421 * <td>Email address itself.</td> 3422 * </tr> 3423 * <tr> 3424 * <td>int</td> 3425 * <td>{@link #TYPE}</td> 3426 * <td>{@link #DATA2}</td> 3427 * <td>Allowed values are: 3428 * <p> 3429 * <ul> 3430 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 3431 * <li>{@link #TYPE_HOME}</li> 3432 * <li>{@link #TYPE_WORK}</li> 3433 * <li>{@link #TYPE_OTHER}</li> 3434 * <li>{@link #TYPE_MOBILE}</li> 3435 * </ul> 3436 * </p> 3437 * </td> 3438 * </tr> 3439 * <tr> 3440 * <td>String</td> 3441 * <td>{@link #LABEL}</td> 3442 * <td>{@link #DATA3}</td> 3443 * <td></td> 3444 * </tr> 3445 * </table> 3446 */ 3447 public static final class Email implements DataColumnsWithJoins, CommonColumns { 3448 /** 3449 * This utility class cannot be instantiated 3450 */ 3451 private Email() {} 3452 3453 /** MIME type used when storing this in data table. */ 3454 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2"; 3455 3456 /** 3457 * The MIME type of {@link #CONTENT_URI} providing a directory of email addresses. 3458 */ 3459 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2"; 3460 3461 /** 3462 * The content:// style URI for all data records of the 3463 * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the 3464 * associated raw contact and aggregate contact data. 3465 */ 3466 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 3467 "emails"); 3468 3469 /** 3470 * <p> 3471 * The content:// style URL for looking up data rows by email address. The 3472 * lookup argument, an email address, should be passed as an additional path segment 3473 * after this URI. 3474 * </p> 3475 * <p>Example: 3476 * <pre> 3477 * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(email)); 3478 * Cursor c = getContentResolver().query(uri, 3479 * new String[]{Email.CONTACT_ID, Email.DISPLAY_NAME, Email.DATA}, 3480 * null, null, null); 3481 * </pre> 3482 * </p> 3483 */ 3484 public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, 3485 "lookup"); 3486 3487 /** 3488 * <p> 3489 * The content:// style URL for email lookup using a filter. The filter returns 3490 * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied 3491 * to display names as well as email addresses. The filter argument should be passed 3492 * as an additional path segment after this URI. 3493 * </p> 3494 * <p>The query in the following example will return "Robert Parr (bob@incredibles.com)" 3495 * as well as "Bob Parr (incredible@android.com)". 3496 * <pre> 3497 * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode("bob")); 3498 * Cursor c = getContentResolver().query(uri, 3499 * new String[]{Email.DISPLAY_NAME, Email.DATA}, 3500 * null, null, null); 3501 * </pre> 3502 * </p> 3503 */ 3504 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, 3505 "filter"); 3506 3507 /** 3508 * The email address. 3509 * <P>Type: TEXT</P> 3510 * @hide TODO: Unhide in a separate CL 3511 */ 3512 public static final String ADDRESS = DATA1; 3513 3514 public static final int TYPE_HOME = 1; 3515 public static final int TYPE_WORK = 2; 3516 public static final int TYPE_OTHER = 3; 3517 public static final int TYPE_MOBILE = 4; 3518 3519 /** 3520 * The display name for the email address 3521 * <P>Type: TEXT</P> 3522 */ 3523 public static final String DISPLAY_NAME = DATA4; 3524 3525 /** 3526 * Return the string resource that best describes the given 3527 * {@link #TYPE}. Will always return a valid resource. 3528 */ 3529 public static final int getTypeLabelResource(int type) { 3530 switch (type) { 3531 case TYPE_HOME: return com.android.internal.R.string.emailTypeHome; 3532 case TYPE_WORK: return com.android.internal.R.string.emailTypeWork; 3533 case TYPE_OTHER: return com.android.internal.R.string.emailTypeOther; 3534 case TYPE_MOBILE: return com.android.internal.R.string.emailTypeMobile; 3535 default: return com.android.internal.R.string.emailTypeCustom; 3536 } 3537 } 3538 3539 /** 3540 * Return a {@link CharSequence} that best describes the given type, 3541 * possibly substituting the given {@link #LABEL} value 3542 * for {@link #TYPE_CUSTOM}. 3543 */ 3544 public static final CharSequence getTypeLabel(Resources res, int type, 3545 CharSequence label) { 3546 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 3547 return label; 3548 } else { 3549 final int labelRes = getTypeLabelResource(type); 3550 return res.getText(labelRes); 3551 } 3552 } 3553 } 3554 3555 /** 3556 * <p> 3557 * A data kind representing a postal addresses. 3558 * </p> 3559 * <p> 3560 * You can use all columns defined for {@link ContactsContract.Data} as 3561 * well as the following aliases. 3562 * </p> 3563 * <h2>Column aliases</h2> 3564 * <table class="jd-sumtable"> 3565 * <tr> 3566 * <th>Type</th> 3567 * <th>Alias</th><th colspan='2'>Data column</th> 3568 * </tr> 3569 * <tr> 3570 * <td>String</td> 3571 * <td>{@link #FORMATTED_ADDRESS}</td> 3572 * <td>{@link #DATA1}</td> 3573 * <td></td> 3574 * </tr> 3575 * <tr> 3576 * <td>int</td> 3577 * <td>{@link #TYPE}</td> 3578 * <td>{@link #DATA2}</td> 3579 * <td>Allowed values are: 3580 * <p> 3581 * <ul> 3582 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 3583 * <li>{@link #TYPE_HOME}</li> 3584 * <li>{@link #TYPE_WORK}</li> 3585 * <li>{@link #TYPE_OTHER}</li> 3586 * </ul> 3587 * </p> 3588 * </td> 3589 * </tr> 3590 * <tr> 3591 * <td>String</td> 3592 * <td>{@link #LABEL}</td> 3593 * <td>{@link #DATA3}</td> 3594 * <td></td> 3595 * </tr> 3596 * <tr> 3597 * <td>String</td> 3598 * <td>{@link #STREET}</td> 3599 * <td>{@link #DATA4}</td> 3600 * <td></td> 3601 * </tr> 3602 * <tr> 3603 * <td>String</td> 3604 * <td>{@link #POBOX}</td> 3605 * <td>{@link #DATA5}</td> 3606 * <td>Post Office Box number</td> 3607 * </tr> 3608 * <tr> 3609 * <td>String</td> 3610 * <td>{@link #NEIGHBORHOOD}</td> 3611 * <td>{@link #DATA6}</td> 3612 * <td></td> 3613 * </tr> 3614 * <tr> 3615 * <td>String</td> 3616 * <td>{@link #CITY}</td> 3617 * <td>{@link #DATA7}</td> 3618 * <td></td> 3619 * </tr> 3620 * <tr> 3621 * <td>String</td> 3622 * <td>{@link #REGION}</td> 3623 * <td>{@link #DATA8}</td> 3624 * <td></td> 3625 * </tr> 3626 * <tr> 3627 * <td>String</td> 3628 * <td>{@link #POSTCODE}</td> 3629 * <td>{@link #DATA9}</td> 3630 * <td></td> 3631 * </tr> 3632 * <tr> 3633 * <td>String</td> 3634 * <td>{@link #COUNTRY}</td> 3635 * <td>{@link #DATA10}</td> 3636 * <td></td> 3637 * </tr> 3638 * </table> 3639 */ 3640 public static final class StructuredPostal implements DataColumnsWithJoins, CommonColumns { 3641 /** 3642 * This utility class cannot be instantiated 3643 */ 3644 private StructuredPostal() { 3645 } 3646 3647 /** MIME type used when storing this in data table. */ 3648 public static final String CONTENT_ITEM_TYPE = 3649 "vnd.android.cursor.item/postal-address_v2"; 3650 3651 /** 3652 * The MIME type of {@link #CONTENT_URI} providing a directory of 3653 * postal addresses. 3654 */ 3655 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2"; 3656 3657 /** 3658 * The content:// style URI for all data records of the 3659 * {@link StructuredPostal#CONTENT_ITEM_TYPE} MIME type. 3660 */ 3661 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 3662 "postals"); 3663 3664 public static final int TYPE_HOME = 1; 3665 public static final int TYPE_WORK = 2; 3666 public static final int TYPE_OTHER = 3; 3667 3668 /** 3669 * The full, unstructured postal address. <i>This field must be 3670 * consistent with any structured data.</i> 3671 * <p> 3672 * Type: TEXT 3673 */ 3674 public static final String FORMATTED_ADDRESS = DATA; 3675 3676 /** 3677 * Can be street, avenue, road, etc. This element also includes the 3678 * house number and room/apartment/flat/floor number. 3679 * <p> 3680 * Type: TEXT 3681 */ 3682 public static final String STREET = DATA4; 3683 3684 /** 3685 * Covers actual P.O. boxes, drawers, locked bags, etc. This is 3686 * usually but not always mutually exclusive with street. 3687 * <p> 3688 * Type: TEXT 3689 */ 3690 public static final String POBOX = DATA5; 3691 3692 /** 3693 * This is used to disambiguate a street address when a city 3694 * contains more than one street with the same name, or to specify a 3695 * small place whose mail is routed through a larger postal town. In 3696 * China it could be a county or a minor city. 3697 * <p> 3698 * Type: TEXT 3699 */ 3700 public static final String NEIGHBORHOOD = DATA6; 3701 3702 /** 3703 * Can be city, village, town, borough, etc. This is the postal town 3704 * and not necessarily the place of residence or place of business. 3705 * <p> 3706 * Type: TEXT 3707 */ 3708 public static final String CITY = DATA7; 3709 3710 /** 3711 * A state, province, county (in Ireland), Land (in Germany), 3712 * departement (in France), etc. 3713 * <p> 3714 * Type: TEXT 3715 */ 3716 public static final String REGION = DATA8; 3717 3718 /** 3719 * Postal code. Usually country-wide, but sometimes specific to the 3720 * city (e.g. "2" in "Dublin 2, Ireland" addresses). 3721 * <p> 3722 * Type: TEXT 3723 */ 3724 public static final String POSTCODE = DATA9; 3725 3726 /** 3727 * The name or code of the country. 3728 * <p> 3729 * Type: TEXT 3730 */ 3731 public static final String COUNTRY = DATA10; 3732 3733 /** 3734 * Return the string resource that best describes the given 3735 * {@link #TYPE}. Will always return a valid resource. 3736 */ 3737 public static final int getTypeLabelResource(int type) { 3738 switch (type) { 3739 case TYPE_HOME: return com.android.internal.R.string.postalTypeHome; 3740 case TYPE_WORK: return com.android.internal.R.string.postalTypeWork; 3741 case TYPE_OTHER: return com.android.internal.R.string.postalTypeOther; 3742 default: return com.android.internal.R.string.postalTypeCustom; 3743 } 3744 } 3745 3746 /** 3747 * Return a {@link CharSequence} that best describes the given type, 3748 * possibly substituting the given {@link #LABEL} value 3749 * for {@link #TYPE_CUSTOM}. 3750 */ 3751 public static final CharSequence getTypeLabel(Resources res, int type, 3752 CharSequence label) { 3753 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 3754 return label; 3755 } else { 3756 final int labelRes = getTypeLabelResource(type); 3757 return res.getText(labelRes); 3758 } 3759 } 3760 } 3761 3762 /** 3763 * <p> 3764 * A data kind representing an IM address 3765 * </p> 3766 * <p> 3767 * You can use all columns defined for {@link ContactsContract.Data} as 3768 * well as the following aliases. 3769 * </p> 3770 * <h2>Column aliases</h2> 3771 * <table class="jd-sumtable"> 3772 * <tr> 3773 * <th>Type</th> 3774 * <th>Alias</th><th colspan='2'>Data column</th> 3775 * </tr> 3776 * <tr> 3777 * <td>String</td> 3778 * <td>{@link #DATA}</td> 3779 * <td>{@link #DATA1}</td> 3780 * <td></td> 3781 * </tr> 3782 * <tr> 3783 * <td>int</td> 3784 * <td>{@link #TYPE}</td> 3785 * <td>{@link #DATA2}</td> 3786 * <td>Allowed values are: 3787 * <p> 3788 * <ul> 3789 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 3790 * <li>{@link #TYPE_HOME}</li> 3791 * <li>{@link #TYPE_WORK}</li> 3792 * <li>{@link #TYPE_OTHER}</li> 3793 * </ul> 3794 * </p> 3795 * </td> 3796 * </tr> 3797 * <tr> 3798 * <td>String</td> 3799 * <td>{@link #LABEL}</td> 3800 * <td>{@link #DATA3}</td> 3801 * <td></td> 3802 * </tr> 3803 * <tr> 3804 * <td>String</td> 3805 * <td>{@link #PROTOCOL}</td> 3806 * <td>{@link #DATA5}</td> 3807 * <td> 3808 * <p> 3809 * Allowed values: 3810 * <ul> 3811 * <li>{@link #PROTOCOL_CUSTOM}. Also provide the actual protocol name 3812 * as {@link #CUSTOM_PROTOCOL}.</li> 3813 * <li>{@link #PROTOCOL_AIM}</li> 3814 * <li>{@link #PROTOCOL_MSN}</li> 3815 * <li>{@link #PROTOCOL_YAHOO}</li> 3816 * <li>{@link #PROTOCOL_SKYPE}</li> 3817 * <li>{@link #PROTOCOL_QQ}</li> 3818 * <li>{@link #PROTOCOL_GOOGLE_TALK}</li> 3819 * <li>{@link #PROTOCOL_ICQ}</li> 3820 * <li>{@link #PROTOCOL_JABBER}</li> 3821 * <li>{@link #PROTOCOL_NETMEETING}</li> 3822 * </ul> 3823 * </p> 3824 * </td> 3825 * </tr> 3826 * <tr> 3827 * <td>String</td> 3828 * <td>{@link #CUSTOM_PROTOCOL}</td> 3829 * <td>{@link #DATA6}</td> 3830 * <td></td> 3831 * </tr> 3832 * </table> 3833 */ 3834 public static final class Im implements DataColumnsWithJoins, CommonColumns { 3835 /** 3836 * This utility class cannot be instantiated 3837 */ 3838 private Im() {} 3839 3840 /** MIME type used when storing this in data table. */ 3841 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im"; 3842 3843 public static final int TYPE_HOME = 1; 3844 public static final int TYPE_WORK = 2; 3845 public static final int TYPE_OTHER = 3; 3846 3847 /** 3848 * This column should be populated with one of the defined 3849 * constants, e.g. {@link #PROTOCOL_YAHOO}. If the value of this 3850 * column is {@link #PROTOCOL_CUSTOM}, the {@link #CUSTOM_PROTOCOL} 3851 * should contain the name of the custom protocol. 3852 */ 3853 public static final String PROTOCOL = DATA5; 3854 3855 public static final String CUSTOM_PROTOCOL = DATA6; 3856 3857 /* 3858 * The predefined IM protocol types. 3859 */ 3860 public static final int PROTOCOL_CUSTOM = -1; 3861 public static final int PROTOCOL_AIM = 0; 3862 public static final int PROTOCOL_MSN = 1; 3863 public static final int PROTOCOL_YAHOO = 2; 3864 public static final int PROTOCOL_SKYPE = 3; 3865 public static final int PROTOCOL_QQ = 4; 3866 public static final int PROTOCOL_GOOGLE_TALK = 5; 3867 public static final int PROTOCOL_ICQ = 6; 3868 public static final int PROTOCOL_JABBER = 7; 3869 public static final int PROTOCOL_NETMEETING = 8; 3870 3871 /** 3872 * Return the string resource that best describes the given 3873 * {@link #TYPE}. Will always return a valid resource. 3874 */ 3875 public static final int getTypeLabelResource(int type) { 3876 switch (type) { 3877 case TYPE_HOME: return com.android.internal.R.string.imTypeHome; 3878 case TYPE_WORK: return com.android.internal.R.string.imTypeWork; 3879 case TYPE_OTHER: return com.android.internal.R.string.imTypeOther; 3880 default: return com.android.internal.R.string.imTypeCustom; 3881 } 3882 } 3883 3884 /** 3885 * Return a {@link CharSequence} that best describes the given type, 3886 * possibly substituting the given {@link #LABEL} value 3887 * for {@link #TYPE_CUSTOM}. 3888 */ 3889 public static final CharSequence getTypeLabel(Resources res, int type, 3890 CharSequence label) { 3891 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 3892 return label; 3893 } else { 3894 final int labelRes = getTypeLabelResource(type); 3895 return res.getText(labelRes); 3896 } 3897 } 3898 3899 /** 3900 * Return the string resource that best describes the given 3901 * {@link #PROTOCOL}. Will always return a valid resource. 3902 */ 3903 public static final int getProtocolLabelResource(int type) { 3904 switch (type) { 3905 case PROTOCOL_AIM: return com.android.internal.R.string.imProtocolAim; 3906 case PROTOCOL_MSN: return com.android.internal.R.string.imProtocolMsn; 3907 case PROTOCOL_YAHOO: return com.android.internal.R.string.imProtocolYahoo; 3908 case PROTOCOL_SKYPE: return com.android.internal.R.string.imProtocolSkype; 3909 case PROTOCOL_QQ: return com.android.internal.R.string.imProtocolQq; 3910 case PROTOCOL_GOOGLE_TALK: return com.android.internal.R.string.imProtocolGoogleTalk; 3911 case PROTOCOL_ICQ: return com.android.internal.R.string.imProtocolIcq; 3912 case PROTOCOL_JABBER: return com.android.internal.R.string.imProtocolJabber; 3913 case PROTOCOL_NETMEETING: return com.android.internal.R.string.imProtocolNetMeeting; 3914 default: return com.android.internal.R.string.imProtocolCustom; 3915 } 3916 } 3917 3918 /** 3919 * Return a {@link CharSequence} that best describes the given 3920 * protocol, possibly substituting the given 3921 * {@link #CUSTOM_PROTOCOL} value for {@link #PROTOCOL_CUSTOM}. 3922 */ 3923 public static final CharSequence getProtocolLabel(Resources res, int type, 3924 CharSequence label) { 3925 if (type == PROTOCOL_CUSTOM && !TextUtils.isEmpty(label)) { 3926 return label; 3927 } else { 3928 final int labelRes = getProtocolLabelResource(type); 3929 return res.getText(labelRes); 3930 } 3931 } 3932 } 3933 3934 /** 3935 * <p> 3936 * A data kind representing an organization. 3937 * </p> 3938 * <p> 3939 * You can use all columns defined for {@link ContactsContract.Data} as 3940 * well as the following aliases. 3941 * </p> 3942 * <h2>Column aliases</h2> 3943 * <table class="jd-sumtable"> 3944 * <tr> 3945 * <th>Type</th> 3946 * <th>Alias</th><th colspan='2'>Data column</th> 3947 * </tr> 3948 * <tr> 3949 * <td>String</td> 3950 * <td>{@link #COMPANY}</td> 3951 * <td>{@link #DATA1}</td> 3952 * <td></td> 3953 * </tr> 3954 * <tr> 3955 * <td>int</td> 3956 * <td>{@link #TYPE}</td> 3957 * <td>{@link #DATA2}</td> 3958 * <td>Allowed values are: 3959 * <p> 3960 * <ul> 3961 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 3962 * <li>{@link #TYPE_WORK}</li> 3963 * <li>{@link #TYPE_OTHER}</li> 3964 * </ul> 3965 * </p> 3966 * </td> 3967 * </tr> 3968 * <tr> 3969 * <td>String</td> 3970 * <td>{@link #LABEL}</td> 3971 * <td>{@link #DATA3}</td> 3972 * <td></td> 3973 * </tr> 3974 * <tr> 3975 * <td>String</td> 3976 * <td>{@link #TITLE}</td> 3977 * <td>{@link #DATA4}</td> 3978 * <td></td> 3979 * </tr> 3980 * <tr> 3981 * <td>String</td> 3982 * <td>{@link #DEPARTMENT}</td> 3983 * <td>{@link #DATA5}</td> 3984 * <td></td> 3985 * </tr> 3986 * <tr> 3987 * <td>String</td> 3988 * <td>{@link #JOB_DESCRIPTION}</td> 3989 * <td>{@link #DATA6}</td> 3990 * <td></td> 3991 * </tr> 3992 * <tr> 3993 * <td>String</td> 3994 * <td>{@link #SYMBOL}</td> 3995 * <td>{@link #DATA7}</td> 3996 * <td></td> 3997 * </tr> 3998 * <tr> 3999 * <td>String</td> 4000 * <td>{@link #PHONETIC_NAME}</td> 4001 * <td>{@link #DATA8}</td> 4002 * <td></td> 4003 * </tr> 4004 * <tr> 4005 * <td>String</td> 4006 * <td>{@link #OFFICE_LOCATION}</td> 4007 * <td>{@link #DATA9}</td> 4008 * <td></td> 4009 * </tr> 4010 * <tr> 4011 * <td>String</td> 4012 * <td>PHONETIC_NAME_STYLE</td> 4013 * <td>{@link #DATA10}</td> 4014 * <td></td> 4015 * </tr> 4016 * </table> 4017 */ 4018 public static final class Organization implements DataColumnsWithJoins, CommonColumns { 4019 /** 4020 * This utility class cannot be instantiated 4021 */ 4022 private Organization() {} 4023 4024 /** MIME type used when storing this in data table. */ 4025 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization"; 4026 4027 public static final int TYPE_WORK = 1; 4028 public static final int TYPE_OTHER = 2; 4029 4030 /** 4031 * The company as the user entered it. 4032 * <P>Type: TEXT</P> 4033 */ 4034 public static final String COMPANY = DATA; 4035 4036 /** 4037 * The position title at this company as the user entered it. 4038 * <P>Type: TEXT</P> 4039 */ 4040 public static final String TITLE = DATA4; 4041 4042 /** 4043 * The department at this company as the user entered it. 4044 * <P>Type: TEXT</P> 4045 */ 4046 public static final String DEPARTMENT = DATA5; 4047 4048 /** 4049 * The job description at this company as the user entered it. 4050 * <P>Type: TEXT</P> 4051 */ 4052 public static final String JOB_DESCRIPTION = DATA6; 4053 4054 /** 4055 * The symbol of this company as the user entered it. 4056 * <P>Type: TEXT</P> 4057 */ 4058 public static final String SYMBOL = DATA7; 4059 4060 /** 4061 * The phonetic name of this company as the user entered it. 4062 * <P>Type: TEXT</P> 4063 */ 4064 public static final String PHONETIC_NAME = DATA8; 4065 4066 /** 4067 * The office location of this organization. 4068 * <P>Type: TEXT</P> 4069 */ 4070 public static final String OFFICE_LOCATION = DATA9; 4071 4072 /** 4073 * The alphabet used for capturing the phonetic name. 4074 * See {@link ContactsContract.PhoneticNameStyle}. 4075 * @hide 4076 */ 4077 public static final String PHONETIC_NAME_STYLE = DATA10; 4078 4079 /** 4080 * Return the string resource that best describes the given 4081 * {@link #TYPE}. Will always return a valid resource. 4082 */ 4083 public static final int getTypeLabelResource(int type) { 4084 switch (type) { 4085 case TYPE_WORK: return com.android.internal.R.string.orgTypeWork; 4086 case TYPE_OTHER: return com.android.internal.R.string.orgTypeOther; 4087 default: return com.android.internal.R.string.orgTypeCustom; 4088 } 4089 } 4090 4091 /** 4092 * Return a {@link CharSequence} that best describes the given type, 4093 * possibly substituting the given {@link #LABEL} value 4094 * for {@link #TYPE_CUSTOM}. 4095 */ 4096 public static final CharSequence getTypeLabel(Resources res, int type, 4097 CharSequence label) { 4098 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 4099 return label; 4100 } else { 4101 final int labelRes = getTypeLabelResource(type); 4102 return res.getText(labelRes); 4103 } 4104 } 4105 } 4106 4107 /** 4108 * <p> 4109 * A data kind representing a relation. 4110 * </p> 4111 * <p> 4112 * You can use all columns defined for {@link ContactsContract.Data} as 4113 * well as the following aliases. 4114 * </p> 4115 * <h2>Column aliases</h2> 4116 * <table class="jd-sumtable"> 4117 * <tr> 4118 * <th>Type</th> 4119 * <th>Alias</th><th colspan='2'>Data column</th> 4120 * </tr> 4121 * <tr> 4122 * <td>String</td> 4123 * <td>{@link #NAME}</td> 4124 * <td>{@link #DATA1}</td> 4125 * <td></td> 4126 * </tr> 4127 * <tr> 4128 * <td>int</td> 4129 * <td>{@link #TYPE}</td> 4130 * <td>{@link #DATA2}</td> 4131 * <td>Allowed values are: 4132 * <p> 4133 * <ul> 4134 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4135 * <li>{@link #TYPE_ASSISTANT}</li> 4136 * <li>{@link #TYPE_BROTHER}</li> 4137 * <li>{@link #TYPE_CHILD}</li> 4138 * <li>{@link #TYPE_DOMESTIC_PARTNER}</li> 4139 * <li>{@link #TYPE_FATHER}</li> 4140 * <li>{@link #TYPE_FRIEND}</li> 4141 * <li>{@link #TYPE_MANAGER}</li> 4142 * <li>{@link #TYPE_MOTHER}</li> 4143 * <li>{@link #TYPE_PARENT}</li> 4144 * <li>{@link #TYPE_PARTNER}</li> 4145 * <li>{@link #TYPE_REFERRED_BY}</li> 4146 * <li>{@link #TYPE_RELATIVE}</li> 4147 * <li>{@link #TYPE_SISTER}</li> 4148 * <li>{@link #TYPE_SPOUSE}</li> 4149 * </ul> 4150 * </p> 4151 * </td> 4152 * </tr> 4153 * <tr> 4154 * <td>String</td> 4155 * <td>{@link #LABEL}</td> 4156 * <td>{@link #DATA3}</td> 4157 * <td></td> 4158 * </tr> 4159 * </table> 4160 */ 4161 public static final class Relation implements DataColumnsWithJoins, CommonColumns { 4162 /** 4163 * This utility class cannot be instantiated 4164 */ 4165 private Relation() {} 4166 4167 /** MIME type used when storing this in data table. */ 4168 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation"; 4169 4170 public static final int TYPE_ASSISTANT = 1; 4171 public static final int TYPE_BROTHER = 2; 4172 public static final int TYPE_CHILD = 3; 4173 public static final int TYPE_DOMESTIC_PARTNER = 4; 4174 public static final int TYPE_FATHER = 5; 4175 public static final int TYPE_FRIEND = 6; 4176 public static final int TYPE_MANAGER = 7; 4177 public static final int TYPE_MOTHER = 8; 4178 public static final int TYPE_PARENT = 9; 4179 public static final int TYPE_PARTNER = 10; 4180 public static final int TYPE_REFERRED_BY = 11; 4181 public static final int TYPE_RELATIVE = 12; 4182 public static final int TYPE_SISTER = 13; 4183 public static final int TYPE_SPOUSE = 14; 4184 4185 /** 4186 * The name of the relative as the user entered it. 4187 * <P>Type: TEXT</P> 4188 */ 4189 public static final String NAME = DATA; 4190 } 4191 4192 /** 4193 * <p> 4194 * A data kind representing an event. 4195 * </p> 4196 * <p> 4197 * You can use all columns defined for {@link ContactsContract.Data} as 4198 * well as the following aliases. 4199 * </p> 4200 * <h2>Column aliases</h2> 4201 * <table class="jd-sumtable"> 4202 * <tr> 4203 * <th>Type</th> 4204 * <th>Alias</th><th colspan='2'>Data column</th> 4205 * </tr> 4206 * <tr> 4207 * <td>String</td> 4208 * <td>{@link #START_DATE}</td> 4209 * <td>{@link #DATA1}</td> 4210 * <td></td> 4211 * </tr> 4212 * <tr> 4213 * <td>int</td> 4214 * <td>{@link #TYPE}</td> 4215 * <td>{@link #DATA2}</td> 4216 * <td>Allowed values are: 4217 * <p> 4218 * <ul> 4219 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4220 * <li>{@link #TYPE_ANNIVERSARY}</li> 4221 * <li>{@link #TYPE_OTHER}</li> 4222 * <li>{@link #TYPE_BIRTHDAY}</li> 4223 * </ul> 4224 * </p> 4225 * </td> 4226 * </tr> 4227 * <tr> 4228 * <td>String</td> 4229 * <td>{@link #LABEL}</td> 4230 * <td>{@link #DATA3}</td> 4231 * <td></td> 4232 * </tr> 4233 * </table> 4234 */ 4235 public static final class Event implements DataColumnsWithJoins, CommonColumns { 4236 /** 4237 * This utility class cannot be instantiated 4238 */ 4239 private Event() {} 4240 4241 /** MIME type used when storing this in data table. */ 4242 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event"; 4243 4244 public static final int TYPE_ANNIVERSARY = 1; 4245 public static final int TYPE_OTHER = 2; 4246 public static final int TYPE_BIRTHDAY = 3; 4247 4248 /** 4249 * The event start date as the user entered it. 4250 * <P>Type: TEXT</P> 4251 */ 4252 public static final String START_DATE = DATA; 4253 4254 /** 4255 * Return the string resource that best describes the given 4256 * {@link #TYPE}. Will always return a valid resource. 4257 */ 4258 public static int getTypeResource(Integer type) { 4259 if (type == null) { 4260 return com.android.internal.R.string.eventTypeOther; 4261 } 4262 switch (type) { 4263 case TYPE_ANNIVERSARY: 4264 return com.android.internal.R.string.eventTypeAnniversary; 4265 case TYPE_BIRTHDAY: return com.android.internal.R.string.eventTypeBirthday; 4266 case TYPE_OTHER: return com.android.internal.R.string.eventTypeOther; 4267 default: return com.android.internal.R.string.eventTypeOther; 4268 } 4269 } 4270 } 4271 4272 /** 4273 * <p> 4274 * A data kind representing an photo for the contact. 4275 * </p> 4276 * <p> 4277 * Some sync adapters will choose to download photos in a separate 4278 * pass. A common pattern is to use columns {@link ContactsContract.Data#SYNC1} 4279 * through {@link ContactsContract.Data#SYNC4} to store temporary 4280 * data, e.g. the image URL or ID, state of download, server-side version 4281 * of the image. It is allowed for the {@link #PHOTO} to be null. 4282 * </p> 4283 * <p> 4284 * You can use all columns defined for {@link ContactsContract.Data} as 4285 * well as the following aliases. 4286 * </p> 4287 * <h2>Column aliases</h2> 4288 * <table class="jd-sumtable"> 4289 * <tr> 4290 * <th>Type</th> 4291 * <th>Alias</th><th colspan='2'>Data column</th> 4292 * </tr> 4293 * <tr> 4294 * <td>BLOB</td> 4295 * <td>{@link #PHOTO}</td> 4296 * <td>{@link #DATA15}</td> 4297 * <td>By convention, binary data is stored in DATA15.</td> 4298 * </tr> 4299 * </table> 4300 */ 4301 public static final class Photo implements DataColumnsWithJoins { 4302 /** 4303 * This utility class cannot be instantiated 4304 */ 4305 private Photo() {} 4306 4307 /** MIME type used when storing this in data table. */ 4308 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo"; 4309 4310 /** 4311 * Thumbnail photo of the raw contact. This is the raw bytes of an image 4312 * that could be inflated using {@link android.graphics.BitmapFactory}. 4313 * <p> 4314 * Type: BLOB 4315 */ 4316 public static final String PHOTO = DATA15; 4317 } 4318 4319 /** 4320 * <p> 4321 * Notes about the contact. 4322 * </p> 4323 * <p> 4324 * You can use all columns defined for {@link ContactsContract.Data} as 4325 * well as the following aliases. 4326 * </p> 4327 * <h2>Column aliases</h2> 4328 * <table class="jd-sumtable"> 4329 * <tr> 4330 * <th>Type</th> 4331 * <th>Alias</th><th colspan='2'>Data column</th> 4332 * </tr> 4333 * <tr> 4334 * <td>String</td> 4335 * <td>{@link #NOTE}</td> 4336 * <td>{@link #DATA1}</td> 4337 * <td></td> 4338 * </tr> 4339 * </table> 4340 */ 4341 public static final class Note implements DataColumnsWithJoins { 4342 /** 4343 * This utility class cannot be instantiated 4344 */ 4345 private Note() {} 4346 4347 /** MIME type used when storing this in data table. */ 4348 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note"; 4349 4350 /** 4351 * The note text. 4352 * <P>Type: TEXT</P> 4353 */ 4354 public static final String NOTE = DATA1; 4355 } 4356 4357 /** 4358 * <p> 4359 * Group Membership. 4360 * </p> 4361 * <p> 4362 * You can use all columns defined for {@link ContactsContract.Data} as 4363 * well as the following aliases. 4364 * </p> 4365 * <h2>Column aliases</h2> 4366 * <table class="jd-sumtable"> 4367 * <tr> 4368 * <th>Type</th> 4369 * <th>Alias</th><th colspan='2'>Data column</th> 4370 * </tr> 4371 * <tr> 4372 * <td>long</td> 4373 * <td>{@link #GROUP_ROW_ID}</td> 4374 * <td>{@link #DATA1}</td> 4375 * <td></td> 4376 * </tr> 4377 * <tr> 4378 * <td>String</td> 4379 * <td>{@link #GROUP_SOURCE_ID}</td> 4380 * <td>none</td> 4381 * <td> 4382 * <p> 4383 * The sourceid of the group that this group membership refers to. 4384 * Exactly one of this or {@link #GROUP_ROW_ID} must be set when 4385 * inserting a row. 4386 * </p> 4387 * <p> 4388 * If this field is specified, the provider will first try to 4389 * look up a group with this {@link Groups Groups.SOURCE_ID}. If such a group 4390 * is found, it will use the corresponding row id. If the group is not 4391 * found, it will create one. 4392 * </td> 4393 * </tr> 4394 * </table> 4395 */ 4396 public static final class GroupMembership implements DataColumnsWithJoins { 4397 /** 4398 * This utility class cannot be instantiated 4399 */ 4400 private GroupMembership() {} 4401 4402 /** MIME type used when storing this in data table. */ 4403 public static final String CONTENT_ITEM_TYPE = 4404 "vnd.android.cursor.item/group_membership"; 4405 4406 /** 4407 * The row id of the group that this group membership refers to. Exactly one of 4408 * this or {@link #GROUP_SOURCE_ID} must be set when inserting a row. 4409 * <P>Type: INTEGER</P> 4410 */ 4411 public static final String GROUP_ROW_ID = DATA1; 4412 4413 /** 4414 * The sourceid of the group that this group membership refers to. Exactly one of 4415 * this or {@link #GROUP_ROW_ID} must be set when inserting a row. 4416 * <P>Type: TEXT</P> 4417 */ 4418 public static final String GROUP_SOURCE_ID = "group_sourceid"; 4419 } 4420 4421 /** 4422 * <p> 4423 * A data kind representing a website related to the contact. 4424 * </p> 4425 * <p> 4426 * You can use all columns defined for {@link ContactsContract.Data} as 4427 * well as the following aliases. 4428 * </p> 4429 * <h2>Column aliases</h2> 4430 * <table class="jd-sumtable"> 4431 * <tr> 4432 * <th>Type</th> 4433 * <th>Alias</th><th colspan='2'>Data column</th> 4434 * </tr> 4435 * <tr> 4436 * <td>String</td> 4437 * <td>{@link #URL}</td> 4438 * <td>{@link #DATA1}</td> 4439 * <td></td> 4440 * </tr> 4441 * <tr> 4442 * <td>int</td> 4443 * <td>{@link #TYPE}</td> 4444 * <td>{@link #DATA2}</td> 4445 * <td>Allowed values are: 4446 * <p> 4447 * <ul> 4448 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4449 * <li>{@link #TYPE_HOMEPAGE}</li> 4450 * <li>{@link #TYPE_BLOG}</li> 4451 * <li>{@link #TYPE_PROFILE}</li> 4452 * <li>{@link #TYPE_HOME}</li> 4453 * <li>{@link #TYPE_WORK}</li> 4454 * <li>{@link #TYPE_FTP}</li> 4455 * <li>{@link #TYPE_OTHER}</li> 4456 * </ul> 4457 * </p> 4458 * </td> 4459 * </tr> 4460 * <tr> 4461 * <td>String</td> 4462 * <td>{@link #LABEL}</td> 4463 * <td>{@link #DATA3}</td> 4464 * <td></td> 4465 * </tr> 4466 * </table> 4467 */ 4468 public static final class Website implements DataColumnsWithJoins, CommonColumns { 4469 /** 4470 * This utility class cannot be instantiated 4471 */ 4472 private Website() {} 4473 4474 /** MIME type used when storing this in data table. */ 4475 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website"; 4476 4477 public static final int TYPE_HOMEPAGE = 1; 4478 public static final int TYPE_BLOG = 2; 4479 public static final int TYPE_PROFILE = 3; 4480 public static final int TYPE_HOME = 4; 4481 public static final int TYPE_WORK = 5; 4482 public static final int TYPE_FTP = 6; 4483 public static final int TYPE_OTHER = 7; 4484 4485 /** 4486 * The website URL string. 4487 * <P>Type: TEXT</P> 4488 */ 4489 public static final String URL = DATA; 4490 } 4491 } 4492 4493 /** 4494 * @see Groups 4495 */ 4496 protected interface GroupsColumns { 4497 /** 4498 * The display title of this group. 4499 * <p> 4500 * Type: TEXT 4501 */ 4502 public static final String TITLE = "title"; 4503 4504 /** 4505 * The package name to use when creating {@link Resources} objects for 4506 * this group. This value is only designed for use when building user 4507 * interfaces, and should not be used to infer the owner. 4508 * 4509 * @hide 4510 */ 4511 public static final String RES_PACKAGE = "res_package"; 4512 4513 /** 4514 * The display title of this group to load as a resource from 4515 * {@link #RES_PACKAGE}, which may be localized. 4516 * <P>Type: TEXT</P> 4517 * 4518 * @hide 4519 */ 4520 public static final String TITLE_RES = "title_res"; 4521 4522 /** 4523 * Notes about the group. 4524 * <p> 4525 * Type: TEXT 4526 */ 4527 public static final String NOTES = "notes"; 4528 4529 /** 4530 * The ID of this group if it is a System Group, i.e. a group that has a special meaning 4531 * to the sync adapter, null otherwise. 4532 * <P>Type: TEXT</P> 4533 */ 4534 public static final String SYSTEM_ID = "system_id"; 4535 4536 /** 4537 * The total number of {@link Contacts} that have 4538 * {@link CommonDataKinds.GroupMembership} in this group. Read-only value that is only 4539 * present when querying {@link Groups#CONTENT_SUMMARY_URI}. 4540 * <p> 4541 * Type: INTEGER 4542 */ 4543 public static final String SUMMARY_COUNT = "summ_count"; 4544 4545 /** 4546 * The total number of {@link Contacts} that have both 4547 * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers. 4548 * Read-only value that is only present when querying 4549 * {@link Groups#CONTENT_SUMMARY_URI}. 4550 * <p> 4551 * Type: INTEGER 4552 */ 4553 public static final String SUMMARY_WITH_PHONES = "summ_phones"; 4554 4555 /** 4556 * Flag indicating if the contacts belonging to this group should be 4557 * visible in any user interface. 4558 * <p> 4559 * Type: INTEGER (boolean) 4560 */ 4561 public static final String GROUP_VISIBLE = "group_visible"; 4562 4563 /** 4564 * The "deleted" flag: "0" by default, "1" if the row has been marked 4565 * for deletion. When {@link android.content.ContentResolver#delete} is 4566 * called on a group, it is marked for deletion. The sync adaptor 4567 * deletes the group on the server and then calls ContactResolver.delete 4568 * once more, this time setting the the 4569 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to 4570 * finalize the data removal. 4571 * <P>Type: INTEGER</P> 4572 */ 4573 public static final String DELETED = "deleted"; 4574 4575 /** 4576 * Whether this group should be synced if the SYNC_EVERYTHING settings 4577 * is false for this group's account. 4578 * <p> 4579 * Type: INTEGER (boolean) 4580 */ 4581 public static final String SHOULD_SYNC = "should_sync"; 4582 } 4583 4584 /** 4585 * Constants for the groups table. Only per-account groups are supported. 4586 * <h2>Columns</h2> 4587 * <table class="jd-sumtable"> 4588 * <tr> 4589 * <th colspan='4'>Groups</th> 4590 * </tr> 4591 * <tr> 4592 * <td>long</td> 4593 * <td>{@link #_ID}</td> 4594 * <td>read-only</td> 4595 * <td>Row ID. Sync adapter should try to preserve row IDs during updates. 4596 * In other words, it would be a really bad idea to delete and reinsert a 4597 * group. A sync adapter should always do an update instead.</td> 4598 * </tr> 4599 * <tr> 4600 * <td>String</td> 4601 * <td>{@link #TITLE}</td> 4602 * <td>read/write</td> 4603 * <td>The display title of this group.</td> 4604 * </tr> 4605 * <tr> 4606 * <td>String</td> 4607 * <td>{@link #NOTES}</td> 4608 * <td>read/write</td> 4609 * <td>Notes about the group.</td> 4610 * </tr> 4611 * <tr> 4612 * <td>String</td> 4613 * <td>{@link #SYSTEM_ID}</td> 4614 * <td>read/write</td> 4615 * <td>The ID of this group if it is a System Group, i.e. a group that has a 4616 * special meaning to the sync adapter, null otherwise.</td> 4617 * </tr> 4618 * <tr> 4619 * <td>int</td> 4620 * <td>{@link #SUMMARY_COUNT}</td> 4621 * <td>read-only</td> 4622 * <td>The total number of {@link Contacts} that have 4623 * {@link CommonDataKinds.GroupMembership} in this group. Read-only value 4624 * that is only present when querying {@link Groups#CONTENT_SUMMARY_URI}.</td> 4625 * </tr> 4626 * <tr> 4627 * <td>int</td> 4628 * <td>{@link #SUMMARY_WITH_PHONES}</td> 4629 * <td>read-only</td> 4630 * <td>The total number of {@link Contacts} that have both 4631 * {@link CommonDataKinds.GroupMembership} in this group, and also have 4632 * phone numbers. Read-only value that is only present when querying 4633 * {@link Groups#CONTENT_SUMMARY_URI}.</td> 4634 * </tr> 4635 * <tr> 4636 * <td>int</td> 4637 * <td>{@link #GROUP_VISIBLE}</td> 4638 * <td>read-only</td> 4639 * <td>Flag indicating if the contacts belonging to this group should be 4640 * visible in any user interface. Allowed values: 0 and 1.</td> 4641 * </tr> 4642 * <tr> 4643 * <td>int</td> 4644 * <td>{@link #DELETED}</td> 4645 * <td>read/write</td> 4646 * <td>The "deleted" flag: "0" by default, "1" if the row has been marked 4647 * for deletion. When {@link android.content.ContentResolver#delete} is 4648 * called on a group, it is marked for deletion. The sync adaptor deletes 4649 * the group on the server and then calls ContactResolver.delete once more, 4650 * this time setting the the {@link ContactsContract#CALLER_IS_SYNCADAPTER} 4651 * query parameter to finalize the data removal.</td> 4652 * </tr> 4653 * <tr> 4654 * <td>int</td> 4655 * <td>{@link #SHOULD_SYNC}</td> 4656 * <td>read/write</td> 4657 * <td>Whether this group should be synced if the SYNC_EVERYTHING settings 4658 * is false for this group's account.</td> 4659 * </tr> 4660 * </table> 4661 */ 4662 public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns { 4663 /** 4664 * This utility class cannot be instantiated 4665 */ 4666 private Groups() { 4667 } 4668 4669 /** 4670 * The content:// style URI for this table 4671 */ 4672 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "groups"); 4673 4674 /** 4675 * The content:// style URI for this table joined with details data from 4676 * {@link ContactsContract.Data}. 4677 */ 4678 public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI, 4679 "groups_summary"); 4680 4681 /** 4682 * The MIME type of a directory of groups. 4683 */ 4684 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/group"; 4685 4686 /** 4687 * The MIME type of a single group. 4688 */ 4689 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group"; 4690 4691 public static EntityIterator newEntityIterator(Cursor cursor) { 4692 return new EntityIteratorImpl(cursor); 4693 } 4694 4695 private static class EntityIteratorImpl extends CursorEntityIterator { 4696 public EntityIteratorImpl(Cursor cursor) { 4697 super(cursor); 4698 } 4699 4700 @Override 4701 public Entity getEntityAndIncrementCursor(Cursor cursor) throws RemoteException { 4702 // we expect the cursor is already at the row we need to read from 4703 final ContentValues values = new ContentValues(); 4704 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, _ID); 4705 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_NAME); 4706 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_TYPE); 4707 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DIRTY); 4708 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, VERSION); 4709 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SOURCE_ID); 4710 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, RES_PACKAGE); 4711 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE); 4712 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE_RES); 4713 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, GROUP_VISIBLE); 4714 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC1); 4715 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC2); 4716 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC3); 4717 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC4); 4718 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYSTEM_ID); 4719 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DELETED); 4720 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, NOTES); 4721 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SHOULD_SYNC); 4722 cursor.moveToNext(); 4723 return new Entity(values); 4724 } 4725 } 4726 } 4727 4728 /** 4729 * <p> 4730 * Constants for the contact aggregation exceptions table, which contains 4731 * aggregation rules overriding those used by automatic aggregation. This 4732 * type only supports query and update. Neither insert nor delete are 4733 * supported. 4734 * </p> 4735 * <h2>Columns</h2> 4736 * <table class="jd-sumtable"> 4737 * <tr> 4738 * <th colspan='4'>AggregationExceptions</th> 4739 * </tr> 4740 * <tr> 4741 * <td>int</td> 4742 * <td>{@link #TYPE}</td> 4743 * <td>read/write</td> 4744 * <td>The type of exception: {@link #TYPE_KEEP_TOGETHER}, 4745 * {@link #TYPE_KEEP_SEPARATE} or {@link #TYPE_AUTOMATIC}.</td> 4746 * </tr> 4747 * <tr> 4748 * <td>long</td> 4749 * <td>{@link #RAW_CONTACT_ID1}</td> 4750 * <td>read/write</td> 4751 * <td>A reference to the {@link RawContacts#_ID} of the raw contact that 4752 * the rule applies to.</td> 4753 * </tr> 4754 * <tr> 4755 * <td>long</td> 4756 * <td>{@link #RAW_CONTACT_ID2}</td> 4757 * <td>read/write</td> 4758 * <td>A reference to the other {@link RawContacts#_ID} of the raw contact 4759 * that the rule applies to.</td> 4760 * </tr> 4761 * </table> 4762 */ 4763 public static final class AggregationExceptions implements BaseColumns { 4764 /** 4765 * This utility class cannot be instantiated 4766 */ 4767 private AggregationExceptions() {} 4768 4769 /** 4770 * The content:// style URI for this table 4771 */ 4772 public static final Uri CONTENT_URI = 4773 Uri.withAppendedPath(AUTHORITY_URI, "aggregation_exceptions"); 4774 4775 /** 4776 * The MIME type of {@link #CONTENT_URI} providing a directory of data. 4777 */ 4778 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception"; 4779 4780 /** 4781 * The MIME type of a {@link #CONTENT_URI} subdirectory of an aggregation exception 4782 */ 4783 public static final String CONTENT_ITEM_TYPE = 4784 "vnd.android.cursor.item/aggregation_exception"; 4785 4786 /** 4787 * The type of exception: {@link #TYPE_KEEP_TOGETHER}, {@link #TYPE_KEEP_SEPARATE} or 4788 * {@link #TYPE_AUTOMATIC}. 4789 * 4790 * <P>Type: INTEGER</P> 4791 */ 4792 public static final String TYPE = "type"; 4793 4794 /** 4795 * Allows the provider to automatically decide whether the specified raw contacts should 4796 * be included in the same aggregate contact or not. 4797 */ 4798 public static final int TYPE_AUTOMATIC = 0; 4799 4800 /** 4801 * Makes sure that the specified raw contacts are included in the same 4802 * aggregate contact. 4803 */ 4804 public static final int TYPE_KEEP_TOGETHER = 1; 4805 4806 /** 4807 * Makes sure that the specified raw contacts are NOT included in the same 4808 * aggregate contact. 4809 */ 4810 public static final int TYPE_KEEP_SEPARATE = 2; 4811 4812 /** 4813 * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to. 4814 */ 4815 public static final String RAW_CONTACT_ID1 = "raw_contact_id1"; 4816 4817 /** 4818 * A reference to the other {@link RawContacts#_ID} of the raw contact that the rule 4819 * applies to. 4820 */ 4821 public static final String RAW_CONTACT_ID2 = "raw_contact_id2"; 4822 } 4823 4824 /** 4825 * @see Settings 4826 */ 4827 protected interface SettingsColumns { 4828 /** 4829 * The name of the account instance to which this row belongs. 4830 * <P>Type: TEXT</P> 4831 */ 4832 public static final String ACCOUNT_NAME = "account_name"; 4833 4834 /** 4835 * The type of account to which this row belongs, which when paired with 4836 * {@link #ACCOUNT_NAME} identifies a specific account. 4837 * <P>Type: TEXT</P> 4838 */ 4839 public static final String ACCOUNT_TYPE = "account_type"; 4840 4841 /** 4842 * Depending on the mode defined by the sync-adapter, this flag controls 4843 * the top-level sync behavior for this data source. 4844 * <p> 4845 * Type: INTEGER (boolean) 4846 */ 4847 public static final String SHOULD_SYNC = "should_sync"; 4848 4849 /** 4850 * Flag indicating if contacts without any {@link CommonDataKinds.GroupMembership} 4851 * entries should be visible in any user interface. 4852 * <p> 4853 * Type: INTEGER (boolean) 4854 */ 4855 public static final String UNGROUPED_VISIBLE = "ungrouped_visible"; 4856 4857 /** 4858 * Read-only flag indicating if this {@link #SHOULD_SYNC} or any 4859 * {@link Groups#SHOULD_SYNC} under this account have been marked as 4860 * unsynced. 4861 */ 4862 public static final String ANY_UNSYNCED = "any_unsynced"; 4863 4864 /** 4865 * Read-only count of {@link Contacts} from a specific source that have 4866 * no {@link CommonDataKinds.GroupMembership} entries. 4867 * <p> 4868 * Type: INTEGER 4869 */ 4870 public static final String UNGROUPED_COUNT = "summ_count"; 4871 4872 /** 4873 * Read-only count of {@link Contacts} from a specific source that have 4874 * no {@link CommonDataKinds.GroupMembership} entries, and also have phone numbers. 4875 * <p> 4876 * Type: INTEGER 4877 */ 4878 public static final String UNGROUPED_WITH_PHONES = "summ_phones"; 4879 } 4880 4881 /** 4882 * <p> 4883 * Contacts-specific settings for various {@link Account}'s. 4884 * </p> 4885 * <h2>Columns</h2> 4886 * <table class="jd-sumtable"> 4887 * <tr> 4888 * <th colspan='4'>Settings</th> 4889 * </tr> 4890 * <tr> 4891 * <td>String</td> 4892 * <td>{@link #ACCOUNT_NAME}</td> 4893 * <td>read/write-once</td> 4894 * <td>The name of the account instance to which this row belongs.</td> 4895 * </tr> 4896 * <tr> 4897 * <td>String</td> 4898 * <td>{@link #ACCOUNT_TYPE}</td> 4899 * <td>read/write-once</td> 4900 * <td>The type of account to which this row belongs, which when paired with 4901 * {@link #ACCOUNT_NAME} identifies a specific account.</td> 4902 * </tr> 4903 * <tr> 4904 * <td>int</td> 4905 * <td>{@link #SHOULD_SYNC}</td> 4906 * <td>read/write</td> 4907 * <td>Depending on the mode defined by the sync-adapter, this flag controls 4908 * the top-level sync behavior for this data source.</td> 4909 * </tr> 4910 * <tr> 4911 * <td>int</td> 4912 * <td>{@link #UNGROUPED_VISIBLE}</td> 4913 * <td>read/write</td> 4914 * <td>Flag indicating if contacts without any 4915 * {@link CommonDataKinds.GroupMembership} entries should be visible in any 4916 * user interface.</td> 4917 * </tr> 4918 * <tr> 4919 * <td>int</td> 4920 * <td>{@link #ANY_UNSYNCED}</td> 4921 * <td>read-only</td> 4922 * <td>Read-only flag indicating if this {@link #SHOULD_SYNC} or any 4923 * {@link Groups#SHOULD_SYNC} under this account have been marked as 4924 * unsynced.</td> 4925 * </tr> 4926 * <tr> 4927 * <td>int</td> 4928 * <td>{@link #UNGROUPED_COUNT}</td> 4929 * <td>read-only</td> 4930 * <td>Read-only count of {@link Contacts} from a specific source that have 4931 * no {@link CommonDataKinds.GroupMembership} entries.</td> 4932 * </tr> 4933 * <tr> 4934 * <td>int</td> 4935 * <td>{@link #UNGROUPED_WITH_PHONES}</td> 4936 * <td>read-only</td> 4937 * <td>Read-only count of {@link Contacts} from a specific source that have 4938 * no {@link CommonDataKinds.GroupMembership} entries, and also have phone 4939 * numbers.</td> 4940 * </tr> 4941 * </table> 4942 */ 4943 4944 public static final class Settings implements SettingsColumns { 4945 /** 4946 * This utility class cannot be instantiated 4947 */ 4948 private Settings() { 4949 } 4950 4951 /** 4952 * The content:// style URI for this table 4953 */ 4954 public static final Uri CONTENT_URI = 4955 Uri.withAppendedPath(AUTHORITY_URI, "settings"); 4956 4957 /** 4958 * The MIME-type of {@link #CONTENT_URI} providing a directory of 4959 * settings. 4960 */ 4961 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting"; 4962 4963 /** 4964 * The MIME-type of {@link #CONTENT_URI} providing a single setting. 4965 */ 4966 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting"; 4967 } 4968 4969 /** 4970 * Helper methods to display QuickContact dialogs that allow users to pivot on 4971 * a specific {@link Contacts} entry. 4972 */ 4973 public static final class QuickContact { 4974 /** 4975 * Action used to trigger person pivot dialog. 4976 * @hide 4977 */ 4978 public static final String ACTION_QUICK_CONTACT = 4979 "com.android.contacts.action.QUICK_CONTACT"; 4980 4981 /** 4982 * Extra used to specify pivot dialog location in screen coordinates. 4983 * @deprecated Use {@link Intent#setSourceBounds(Rect)} instead. 4984 * @hide 4985 */ 4986 @Deprecated 4987 public static final String EXTRA_TARGET_RECT = "target_rect"; 4988 4989 /** 4990 * Extra used to specify size of pivot dialog. 4991 * @hide 4992 */ 4993 public static final String EXTRA_MODE = "mode"; 4994 4995 /** 4996 * Extra used to indicate a list of specific MIME-types to exclude and 4997 * not display. Stored as a {@link String} array. 4998 * @hide 4999 */ 5000 public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes"; 5001 5002 /** 5003 * Small QuickContact mode, usually presented with minimal actions. 5004 */ 5005 public static final int MODE_SMALL = 1; 5006 5007 /** 5008 * Medium QuickContact mode, includes actions and light summary describing 5009 * the {@link Contacts} entry being shown. This may include social 5010 * status and presence details. 5011 */ 5012 public static final int MODE_MEDIUM = 2; 5013 5014 /** 5015 * Large QuickContact mode, includes actions and larger, card-like summary 5016 * of the {@link Contacts} entry being shown. This may include detailed 5017 * information, such as a photo. 5018 */ 5019 public static final int MODE_LARGE = 3; 5020 5021 /** 5022 * Trigger a dialog that lists the various methods of interacting with 5023 * the requested {@link Contacts} entry. This may be based on available 5024 * {@link ContactsContract.Data} rows under that contact, and may also 5025 * include social status and presence details. 5026 * 5027 * @param context The parent {@link Context} that may be used as the 5028 * parent for this dialog. 5029 * @param target Specific {@link View} from your layout that this dialog 5030 * should be centered around. In particular, if the dialog 5031 * has a "callout" arrow, it will be pointed and centered 5032 * around this {@link View}. 5033 * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 5034 * {@link Uri} that describes a specific contact to feature 5035 * in this dialog. 5036 * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or 5037 * {@link #MODE_LARGE}, indicating the desired dialog size, 5038 * when supported. 5039 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 5040 * to exclude when showing this dialog. For example, when 5041 * already viewing the contact details card, this can be used 5042 * to omit the details entry from the dialog. 5043 */ 5044 public static void showQuickContact(Context context, View target, Uri lookupUri, int mode, 5045 String[] excludeMimes) { 5046 // Find location and bounds of target view, adjusting based on the 5047 // assumed local density. 5048 final float appScale = context.getResources().getCompatibilityInfo().applicationScale; 5049 final int[] pos = new int[2]; 5050 target.getLocationOnScreen(pos); 5051 5052 final Rect rect = new Rect(); 5053 rect.left = (int) (pos[0] * appScale + 0.5f); 5054 rect.top = (int) (pos[1] * appScale + 0.5f); 5055 rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f); 5056 rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f); 5057 5058 // Trigger with obtained rectangle 5059 showQuickContact(context, rect, lookupUri, mode, excludeMimes); 5060 } 5061 5062 /** 5063 * Trigger a dialog that lists the various methods of interacting with 5064 * the requested {@link Contacts} entry. This may be based on available 5065 * {@link ContactsContract.Data} rows under that contact, and may also 5066 * include social status and presence details. 5067 * 5068 * @param context The parent {@link Context} that may be used as the 5069 * parent for this dialog. 5070 * @param target Specific {@link Rect} that this dialog should be 5071 * centered around, in screen coordinates. In particular, if 5072 * the dialog has a "callout" arrow, it will be pointed and 5073 * centered around this {@link Rect}. If you are running at a 5074 * non-native density, you need to manually adjust using 5075 * {@link DisplayMetrics#density} before calling. 5076 * @param lookupUri A 5077 * {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 5078 * {@link Uri} that describes a specific contact to feature 5079 * in this dialog. 5080 * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or 5081 * {@link #MODE_LARGE}, indicating the desired dialog size, 5082 * when supported. 5083 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 5084 * to exclude when showing this dialog. For example, when 5085 * already viewing the contact details card, this can be used 5086 * to omit the details entry from the dialog. 5087 */ 5088 public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode, 5089 String[] excludeMimes) { 5090 // Launch pivot dialog through intent for now 5091 final Intent intent = new Intent(ACTION_QUICK_CONTACT); 5092 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP 5093 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 5094 5095 intent.setData(lookupUri); 5096 intent.setSourceBounds(target); 5097 intent.putExtra(EXTRA_MODE, mode); 5098 intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes); 5099 context.startActivity(intent); 5100 } 5101 } 5102 5103 /** 5104 * Contains helper classes used to create or manage {@link android.content.Intent Intents} 5105 * that involve contacts. 5106 */ 5107 public static final class Intents { 5108 /** 5109 * This is the intent that is fired when a search suggestion is clicked on. 5110 */ 5111 public static final String SEARCH_SUGGESTION_CLICKED = 5112 "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED"; 5113 5114 /** 5115 * This is the intent that is fired when a search suggestion for dialing a number 5116 * is clicked on. 5117 */ 5118 public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = 5119 "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED"; 5120 5121 /** 5122 * This is the intent that is fired when a search suggestion for creating a contact 5123 * is clicked on. 5124 */ 5125 public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = 5126 "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED"; 5127 5128 /** 5129 * Starts an Activity that lets the user pick a contact to attach an image to. 5130 * After picking the contact it launches the image cropper in face detection mode. 5131 */ 5132 public static final String ATTACH_IMAGE = 5133 "com.android.contacts.action.ATTACH_IMAGE"; 5134 5135 /** 5136 * Takes as input a data URI with a mailto: or tel: scheme. If a single 5137 * contact exists with the given data it will be shown. If no contact 5138 * exists, a dialog will ask the user if they want to create a new 5139 * contact with the provided details filled in. If multiple contacts 5140 * share the data the user will be prompted to pick which contact they 5141 * want to view. 5142 * <p> 5143 * For <code>mailto:</code> URIs, the scheme specific portion must be a 5144 * raw email address, such as one built using 5145 * {@link Uri#fromParts(String, String, String)}. 5146 * <p> 5147 * For <code>tel:</code> URIs, the scheme specific portion is compared 5148 * to existing numbers using the standard caller ID lookup algorithm. 5149 * The number must be properly encoded, for example using 5150 * {@link Uri#fromParts(String, String, String)}. 5151 * <p> 5152 * Any extras from the {@link Insert} class will be passed along to the 5153 * create activity if there are no contacts to show. 5154 * <p> 5155 * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip 5156 * prompting the user when the contact doesn't exist. 5157 */ 5158 public static final String SHOW_OR_CREATE_CONTACT = 5159 "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; 5160 5161 /** 5162 * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new 5163 * contact if no matching contact found. Otherwise, default behavior is 5164 * to prompt user with dialog before creating. 5165 * <p> 5166 * Type: BOOLEAN 5167 */ 5168 public static final String EXTRA_FORCE_CREATE = 5169 "com.android.contacts.action.FORCE_CREATE"; 5170 5171 /** 5172 * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact 5173 * description to be shown when prompting user about creating a new 5174 * contact. 5175 * <p> 5176 * Type: STRING 5177 */ 5178 public static final String EXTRA_CREATE_DESCRIPTION = 5179 "com.android.contacts.action.CREATE_DESCRIPTION"; 5180 5181 /** 5182 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a 5183 * dialog location using screen coordinates. When not specified, the 5184 * dialog will be centered. 5185 * 5186 * @hide 5187 */ 5188 @Deprecated 5189 public static final String EXTRA_TARGET_RECT = "target_rect"; 5190 5191 /** 5192 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a 5193 * desired dialog style, usually a variation on size. One of 5194 * {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}. 5195 * 5196 * @hide 5197 */ 5198 @Deprecated 5199 public static final String EXTRA_MODE = "mode"; 5200 5201 /** 5202 * Value for {@link #EXTRA_MODE} to show a small-sized dialog. 5203 * 5204 * @hide 5205 */ 5206 @Deprecated 5207 public static final int MODE_SMALL = 1; 5208 5209 /** 5210 * Value for {@link #EXTRA_MODE} to show a medium-sized dialog. 5211 * 5212 * @hide 5213 */ 5214 @Deprecated 5215 public static final int MODE_MEDIUM = 2; 5216 5217 /** 5218 * Value for {@link #EXTRA_MODE} to show a large-sized dialog. 5219 * 5220 * @hide 5221 */ 5222 @Deprecated 5223 public static final int MODE_LARGE = 3; 5224 5225 /** 5226 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to indicate 5227 * a list of specific MIME-types to exclude and not display. Stored as a 5228 * {@link String} array. 5229 * 5230 * @hide 5231 */ 5232 @Deprecated 5233 public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes"; 5234 5235 /** 5236 * Intents related to the Contacts app UI. 5237 * 5238 * @hide 5239 */ 5240 public static final class UI { 5241 /** 5242 * The action for the default contacts list tab. 5243 */ 5244 public static final String LIST_DEFAULT = 5245 "com.android.contacts.action.LIST_DEFAULT"; 5246 5247 /** 5248 * The action for the contacts list tab. 5249 */ 5250 public static final String LIST_GROUP_ACTION = 5251 "com.android.contacts.action.LIST_GROUP"; 5252 5253 /** 5254 * When in LIST_GROUP_ACTION mode, this is the group to display. 5255 */ 5256 public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP"; 5257 5258 /** 5259 * The action for the all contacts list tab. 5260 */ 5261 public static final String LIST_ALL_CONTACTS_ACTION = 5262 "com.android.contacts.action.LIST_ALL_CONTACTS"; 5263 5264 /** 5265 * The action for the contacts with phone numbers list tab. 5266 */ 5267 public static final String LIST_CONTACTS_WITH_PHONES_ACTION = 5268 "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES"; 5269 5270 /** 5271 * The action for the starred contacts list tab. 5272 */ 5273 public static final String LIST_STARRED_ACTION = 5274 "com.android.contacts.action.LIST_STARRED"; 5275 5276 /** 5277 * The action for the frequent contacts list tab. 5278 */ 5279 public static final String LIST_FREQUENT_ACTION = 5280 "com.android.contacts.action.LIST_FREQUENT"; 5281 5282 /** 5283 * The action for the "strequent" contacts list tab. It first lists the starred 5284 * contacts in alphabetical order and then the frequent contacts in descending 5285 * order of the number of times they have been contacted. 5286 */ 5287 public static final String LIST_STREQUENT_ACTION = 5288 "com.android.contacts.action.LIST_STREQUENT"; 5289 5290 /** 5291 * A key for to be used as an intent extra to set the activity 5292 * title to a custom String value. 5293 */ 5294 public static final String TITLE_EXTRA_KEY = 5295 "com.android.contacts.extra.TITLE_EXTRA"; 5296 5297 /** 5298 * Activity Action: Display a filtered list of contacts 5299 * <p> 5300 * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for 5301 * filtering 5302 * <p> 5303 * Output: Nothing. 5304 */ 5305 public static final String FILTER_CONTACTS_ACTION = 5306 "com.android.contacts.action.FILTER_CONTACTS"; 5307 5308 /** 5309 * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION} 5310 * intents to supply the text on which to filter. 5311 */ 5312 public static final String FILTER_TEXT_EXTRA_KEY = 5313 "com.android.contacts.extra.FILTER_TEXT"; 5314 } 5315 5316 /** 5317 * Convenience class that contains string constants used 5318 * to create contact {@link android.content.Intent Intents}. 5319 */ 5320 public static final class Insert { 5321 /** The action code to use when adding a contact */ 5322 public static final String ACTION = Intent.ACTION_INSERT; 5323 5324 /** 5325 * If present, forces a bypass of quick insert mode. 5326 */ 5327 public static final String FULL_MODE = "full_mode"; 5328 5329 /** 5330 * The extra field for the contact name. 5331 * <P>Type: String</P> 5332 */ 5333 public static final String NAME = "name"; 5334 5335 // TODO add structured name values here. 5336 5337 /** 5338 * The extra field for the contact phonetic name. 5339 * <P>Type: String</P> 5340 */ 5341 public static final String PHONETIC_NAME = "phonetic_name"; 5342 5343 /** 5344 * The extra field for the contact company. 5345 * <P>Type: String</P> 5346 */ 5347 public static final String COMPANY = "company"; 5348 5349 /** 5350 * The extra field for the contact job title. 5351 * <P>Type: String</P> 5352 */ 5353 public static final String JOB_TITLE = "job_title"; 5354 5355 /** 5356 * The extra field for the contact notes. 5357 * <P>Type: String</P> 5358 */ 5359 public static final String NOTES = "notes"; 5360 5361 /** 5362 * The extra field for the contact phone number. 5363 * <P>Type: String</P> 5364 */ 5365 public static final String PHONE = "phone"; 5366 5367 /** 5368 * The extra field for the contact phone number type. 5369 * <P>Type: Either an integer value from 5370 * {@link CommonDataKinds.Phone}, 5371 * or a string specifying a custom label.</P> 5372 */ 5373 public static final String PHONE_TYPE = "phone_type"; 5374 5375 /** 5376 * The extra field for the phone isprimary flag. 5377 * <P>Type: boolean</P> 5378 */ 5379 public static final String PHONE_ISPRIMARY = "phone_isprimary"; 5380 5381 /** 5382 * The extra field for an optional second contact phone number. 5383 * <P>Type: String</P> 5384 */ 5385 public static final String SECONDARY_PHONE = "secondary_phone"; 5386 5387 /** 5388 * The extra field for an optional second contact phone number type. 5389 * <P>Type: Either an integer value from 5390 * {@link CommonDataKinds.Phone}, 5391 * or a string specifying a custom label.</P> 5392 */ 5393 public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type"; 5394 5395 /** 5396 * The extra field for an optional third contact phone number. 5397 * <P>Type: String</P> 5398 */ 5399 public static final String TERTIARY_PHONE = "tertiary_phone"; 5400 5401 /** 5402 * The extra field for an optional third contact phone number type. 5403 * <P>Type: Either an integer value from 5404 * {@link CommonDataKinds.Phone}, 5405 * or a string specifying a custom label.</P> 5406 */ 5407 public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type"; 5408 5409 /** 5410 * The extra field for the contact email address. 5411 * <P>Type: String</P> 5412 */ 5413 public static final String EMAIL = "email"; 5414 5415 /** 5416 * The extra field for the contact email type. 5417 * <P>Type: Either an integer value from 5418 * {@link CommonDataKinds.Email} 5419 * or a string specifying a custom label.</P> 5420 */ 5421 public static final String EMAIL_TYPE = "email_type"; 5422 5423 /** 5424 * The extra field for the email isprimary flag. 5425 * <P>Type: boolean</P> 5426 */ 5427 public static final String EMAIL_ISPRIMARY = "email_isprimary"; 5428 5429 /** 5430 * The extra field for an optional second contact email address. 5431 * <P>Type: String</P> 5432 */ 5433 public static final String SECONDARY_EMAIL = "secondary_email"; 5434 5435 /** 5436 * The extra field for an optional second contact email type. 5437 * <P>Type: Either an integer value from 5438 * {@link CommonDataKinds.Email} 5439 * or a string specifying a custom label.</P> 5440 */ 5441 public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type"; 5442 5443 /** 5444 * The extra field for an optional third contact email address. 5445 * <P>Type: String</P> 5446 */ 5447 public static final String TERTIARY_EMAIL = "tertiary_email"; 5448 5449 /** 5450 * The extra field for an optional third contact email type. 5451 * <P>Type: Either an integer value from 5452 * {@link CommonDataKinds.Email} 5453 * or a string specifying a custom label.</P> 5454 */ 5455 public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type"; 5456 5457 /** 5458 * The extra field for the contact postal address. 5459 * <P>Type: String</P> 5460 */ 5461 public static final String POSTAL = "postal"; 5462 5463 /** 5464 * The extra field for the contact postal address type. 5465 * <P>Type: Either an integer value from 5466 * {@link CommonDataKinds.StructuredPostal} 5467 * or a string specifying a custom label.</P> 5468 */ 5469 public static final String POSTAL_TYPE = "postal_type"; 5470 5471 /** 5472 * The extra field for the postal isprimary flag. 5473 * <P>Type: boolean</P> 5474 */ 5475 public static final String POSTAL_ISPRIMARY = "postal_isprimary"; 5476 5477 /** 5478 * The extra field for an IM handle. 5479 * <P>Type: String</P> 5480 */ 5481 public static final String IM_HANDLE = "im_handle"; 5482 5483 /** 5484 * The extra field for the IM protocol 5485 */ 5486 public static final String IM_PROTOCOL = "im_protocol"; 5487 5488 /** 5489 * The extra field for the IM isprimary flag. 5490 * <P>Type: boolean</P> 5491 */ 5492 public static final String IM_ISPRIMARY = "im_isprimary"; 5493 } 5494 } 5495 5496} 5497