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