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