ContactsContract.java revision 554344ee7444c0d973f0d4ef768f72d33cc8d4fc
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package android.provider; 18 19import android.accounts.Account; 20import android.content.ContentProviderClient; 21import android.content.ContentProviderOperation; 22import android.content.ContentResolver; 23import android.content.ContentUris; 24import android.content.ContentValues; 25import android.content.Context; 26import android.content.CursorEntityIterator; 27import android.content.Entity; 28import android.content.EntityIterator; 29import android.content.Intent; 30import android.content.res.Resources; 31import android.database.Cursor; 32import android.database.DatabaseUtils; 33import android.graphics.Rect; 34import android.net.Uri; 35import android.os.RemoteException; 36import android.text.TextUtils; 37import android.util.DisplayMetrics; 38import android.util.Pair; 39import android.view.View; 40 41import java.io.ByteArrayInputStream; 42import java.io.InputStream; 43import java.util.ArrayList; 44 45/** 46 * <p> 47 * The contract between the contacts provider and applications. Contains 48 * definitions for the supported URIs and columns. These APIs supersede 49 * {@link Contacts}. 50 * </p> 51 * <h3>Overview</h3> 52 * <p> 53 * ContactsContract defines an extensible database of contact-related 54 * information. Contact information is stored in a three-tier data model: 55 * </p> 56 * <ul> 57 * <li> 58 * A row in the {@link Data} table can store any kind of personal data, such 59 * as a phone number or email addresses. The set of data kinds that can be 60 * stored in this table is open-ended. There is a predefined set of common 61 * kinds, but any application can add its own data kinds. 62 * </li> 63 * <li> 64 * A row in the {@link RawContacts} table represents a set of data describing a 65 * person and associated with a single account (for example, one of the user's 66 * Gmail accounts). 67 * </li> 68 * <li> 69 * A row in the {@link Contacts} table represents an aggregate of one or more 70 * RawContacts presumably describing the same person. When data in or associated with 71 * the RawContacts table is changed, the affected aggregate contacts are updated as 72 * necessary. 73 * </li> 74 * </ul> 75 * <p> 76 * Other tables include: 77 * </p> 78 * <ul> 79 * <li> 80 * {@link Groups}, which contains information about raw contact groups 81 * such as Gmail contact groups. The 82 * current API does not support the notion of groups spanning multiple accounts. 83 * </li> 84 * <li> 85 * {@link StatusUpdates}, which contains social status updates including IM 86 * availability. 87 * </li> 88 * <li> 89 * {@link AggregationExceptions}, which is used for manual aggregation and 90 * disaggregation of raw contacts 91 * </li> 92 * <li> 93 * {@link Settings}, which contains visibility and sync settings for accounts 94 * and groups. 95 * </li> 96 * <li> 97 * {@link SyncState}, which contains free-form data maintained on behalf of sync 98 * adapters 99 * </li> 100 * <li> 101 * {@link PhoneLookup}, which is used for quick caller-ID lookup</li> 102 * </ul> 103 */ 104@SuppressWarnings("unused") 105public final class ContactsContract { 106 /** The authority for the contacts provider */ 107 public static final String AUTHORITY = "com.android.contacts"; 108 /** A content:// style uri to the authority for the contacts provider */ 109 public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); 110 111 /** 112 * An optional URI parameter for insert, update, or delete queries 113 * that allows the caller 114 * to specify that it is a sync adapter. The default value is false. If true 115 * {@link RawContacts#DIRTY} is not automatically set and the 116 * "syncToNetwork" parameter is set to false when calling 117 * {@link 118 * ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}. 119 * This prevents an unnecessary extra synchronization, see the discussion of 120 * the delete operation in {@link RawContacts}. 121 */ 122 public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; 123 124 /** 125 * An optional URI parameter for selection queries that instructs the 126 * provider to include the user's personal profile contact entry (if any) 127 * in the contact results. If present, the user's profile will always be 128 * the first entry returned. The default value is false. 129 * 130 * Specifying this parameter will result in a security error if the calling 131 * application does not have android.permission.READ_PROFILE permission. 132 */ 133 public static final String INCLUDE_PROFILE = "include_profile"; 134 135 /** 136 * A query parameter key used to specify the package that is requesting a query. 137 * This is used for restricting data based on package name. 138 * 139 * @hide 140 */ 141 public static final String REQUESTING_PACKAGE_PARAM_KEY = "requesting_package"; 142 143 /** 144 * Query parameter that should be used by the client to access a specific 145 * {@link Directory}. The parameter value should be the _ID of the corresponding 146 * directory, e.g. 147 * {@code content://com.android.contacts/data/emails/filter/acme?directory=3} 148 */ 149 public static final String DIRECTORY_PARAM_KEY = "directory"; 150 151 /** 152 * A query parameter that limits the number of results returned. The 153 * parameter value should be an integer. 154 */ 155 public static final String LIMIT_PARAM_KEY = "limit"; 156 157 /** 158 * A query parameter specifing a primary account. This parameter should be used with 159 * {@link #PRIMARY_ACCOUNT_TYPE}. The contacts provider handling a query may rely on 160 * this information to optimize its query results. 161 * 162 * For example, in an email composition screen, its implementation can specify an account when 163 * obtaining possible recipients, letting the provider know which account is selected during 164 * the composition. The provider may use the "primary account" information to optimize 165 * the search result. 166 * @hide 167 */ 168 public static final String PRIMARY_ACCOUNT_NAME = "name_for_primary_account"; 169 170 /** 171 * A query parameter specifing a primary account. This parameter should be used with 172 * {@link #PRIMARY_ACCOUNT_NAME}. See the doc in {@link #PRIMARY_ACCOUNT_NAME}. 173 * @hide 174 */ 175 public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account"; 176 177 178 /** 179 * @hide 180 */ 181 public static final class Preferences { 182 183 /** 184 * A key in the {@link android.provider.Settings android.provider.Settings} provider 185 * that stores the preferred sorting order for contacts (by given name vs. by family name). 186 * 187 * @hide 188 */ 189 public static final String SORT_ORDER = "android.contacts.SORT_ORDER"; 190 191 /** 192 * The value for the SORT_ORDER key corresponding to sorting by given name first. 193 * 194 * @hide 195 */ 196 public static final int SORT_ORDER_PRIMARY = 1; 197 198 /** 199 * The value for the SORT_ORDER key corresponding to sorting by family name first. 200 * 201 * @hide 202 */ 203 public static final int SORT_ORDER_ALTERNATIVE = 2; 204 205 /** 206 * A key in the {@link android.provider.Settings android.provider.Settings} provider 207 * that stores the preferred display order for contacts (given name first vs. family 208 * name first). 209 * 210 * @hide 211 */ 212 public static final String DISPLAY_ORDER = "android.contacts.DISPLAY_ORDER"; 213 214 /** 215 * The value for the DISPLAY_ORDER key corresponding to showing the given name first. 216 * 217 * @hide 218 */ 219 public static final int DISPLAY_ORDER_PRIMARY = 1; 220 221 /** 222 * The value for the DISPLAY_ORDER key corresponding to showing the family name first. 223 * 224 * @hide 225 */ 226 public static final int DISPLAY_ORDER_ALTERNATIVE = 2; 227 } 228 229 /** 230 * A Directory represents a contacts corpus, e.g. Local contacts, 231 * Google Apps Global Address List or Corporate Global Address List. 232 * <p> 233 * A Directory is implemented as a content provider with its unique authority and 234 * the same API as the main Contacts Provider. However, there is no expectation that 235 * every directory provider will implement this Contract in its entirety. If a 236 * directory provider does not have an implementation for a specific request, it 237 * should throw an UnsupportedOperationException. 238 * </p> 239 * <p> 240 * The most important use case for Directories is search. A Directory provider is 241 * expected to support at least {@link ContactsContract.Contacts#CONTENT_FILTER_URI 242 * Contacts.CONTENT_FILTER_URI}. If a Directory provider wants to participate 243 * in email and phone lookup functionalities, it should also implement 244 * {@link CommonDataKinds.Email#CONTENT_FILTER_URI CommonDataKinds.Email.CONTENT_FILTER_URI} 245 * and 246 * {@link CommonDataKinds.Phone#CONTENT_FILTER_URI CommonDataKinds.Phone.CONTENT_FILTER_URI}. 247 * </p> 248 * <p> 249 * A directory provider should return NULL for every projection field it does not 250 * recognize, rather than throwing an exception. This way it will not be broken 251 * if ContactsContract is extended with new fields in the future. 252 * </p> 253 * <p> 254 * The client interacts with a directory via Contacts Provider by supplying an 255 * optional {@code directory=} query parameter. 256 * <p> 257 * <p> 258 * When the Contacts Provider receives the request, it transforms the URI and forwards 259 * the request to the corresponding directory content provider. 260 * The URI is transformed in the following fashion: 261 * <ul> 262 * <li>The URI authority is replaced with the corresponding {@link #DIRECTORY_AUTHORITY}.</li> 263 * <li>The {@code accountName=} and {@code accountType=} parameters are added or 264 * replaced using the corresponding {@link #ACCOUNT_TYPE} and {@link #ACCOUNT_NAME} values.</li> 265 * <li>If the URI is missing a ContactsContract.REQUESTING_PACKAGE_PARAM_KEY 266 * parameter, this parameter is added.</li> 267 * </ul> 268 * </p> 269 * <p> 270 * Clients should send directory requests to Contacts Provider and let it 271 * forward them to the respective providers rather than constructing 272 * directory provider URIs by themselves. This level of indirection allows 273 * Contacts Provider to implement additional system-level features and 274 * optimizations. Access to Contacts Provider is protected by the 275 * READ_CONTACTS permission, but access to the directory provider is not. 276 * Therefore directory providers must reject requests coming from clients 277 * other than the Contacts Provider itself. An easy way to prevent such 278 * unauthorized access is to check the name of the calling package: 279 * <pre> 280 * private boolean isCallerAllowed() { 281 * PackageManager pm = getContext().getPackageManager(); 282 * for (String packageName: pm.getPackagesForUid(Binder.getCallingUid())) { 283 * if (packageName.equals("com.android.providers.contacts")) { 284 * return true; 285 * } 286 * } 287 * return false; 288 * } 289 * </pre> 290 * </p> 291 * <p> 292 * The Directory table is read-only and is maintained by the Contacts Provider 293 * automatically. 294 * </p> 295 * <p>It always has at least these two rows: 296 * <ul> 297 * <li> 298 * The local directory. It has {@link Directory#_ID Directory._ID} = 299 * {@link Directory#DEFAULT Directory.DEFAULT}. This directory can be used to access locally 300 * stored contacts. The same can be achieved by omitting the {@code directory=} 301 * parameter altogether. 302 * </li> 303 * <li> 304 * The local invisible contacts. The corresponding directory ID is 305 * {@link Directory#LOCAL_INVISIBLE Directory.LOCAL_INVISIBLE}. 306 * </li> 307 * </ul> 308 * </p> 309 * <p>Custom Directories are discovered by the Contacts Provider following this procedure: 310 * <ul> 311 * <li>It finds all installed content providers with meta data identifying them 312 * as directory providers in AndroidManifest.xml: 313 * <code> 314 * <meta-data android:name="android.content.ContactDirectory" 315 * android:value="true" /> 316 * </code> 317 * <p> 318 * This tag should be placed inside the corresponding content provider declaration. 319 * </p> 320 * </li> 321 * <li> 322 * Then Contacts Provider sends a {@link Directory#CONTENT_URI Directory.CONTENT_URI} 323 * query to each of the directory authorities. A directory provider must implement 324 * this query and return a list of directories. Each directory returned by 325 * the provider must have a unique combination for the {@link #ACCOUNT_NAME} and 326 * {@link #ACCOUNT_TYPE} columns (nulls are allowed). Since directory IDs are assigned 327 * automatically, the _ID field will not be part of the query projection. 328 * </li> 329 * <li>Contacts Provider compiles directory lists received from all directory 330 * providers into one, assigns each individual directory a globally unique ID and 331 * stores all directory records in the Directory table. 332 * </li> 333 * </ul> 334 * </p> 335 * <p>Contacts Provider automatically interrogates newly installed or replaced packages. 336 * Thus simply installing a package containing a directory provider is sufficient 337 * to have that provider registered. A package supplying a directory provider does 338 * not have to contain launchable activities. 339 * </p> 340 * <p> 341 * Every row in the Directory table is automatically associated with the corresponding package 342 * (apk). If the package is later uninstalled, all corresponding directory rows 343 * are automatically removed from the Contacts Provider. 344 * </p> 345 * <p> 346 * When the list of directories handled by a directory provider changes 347 * (for instance when the user adds a new Directory account), the directory provider 348 * should call {@link #notifyDirectoryChange} to notify the Contacts Provider of the change. 349 * In response, the Contacts Provider will requery the directory provider to obtain the 350 * new list of directories. 351 * </p> 352 * <p> 353 * A directory row can be optionally associated with an existing account 354 * (see {@link android.accounts.AccountManager}). If the account is later removed, 355 * the corresponding directory rows are automatically removed from the Contacts Provider. 356 * </p> 357 */ 358 public static final class Directory implements BaseColumns { 359 360 /** 361 * Not instantiable. 362 */ 363 private Directory() { 364 } 365 366 /** 367 * The content:// style URI for this table. Requests to this URI can be 368 * performed on the UI thread because they are always unblocking. 369 */ 370 public static final Uri CONTENT_URI = 371 Uri.withAppendedPath(AUTHORITY_URI, "directories"); 372 373 /** 374 * The MIME-type of {@link #CONTENT_URI} providing a directory of 375 * contact directories. 376 */ 377 public static final String CONTENT_TYPE = 378 "vnd.android.cursor.dir/contact_directories"; 379 380 /** 381 * The MIME type of a {@link #CONTENT_URI} item. 382 */ 383 public static final String CONTENT_ITEM_TYPE = 384 "vnd.android.cursor.item/contact_directory"; 385 386 /** 387 * _ID of the default directory, which represents locally stored contacts. 388 */ 389 public static final long DEFAULT = 0; 390 391 /** 392 * _ID of the directory that represents locally stored invisible contacts. 393 */ 394 public static final long LOCAL_INVISIBLE = 1; 395 396 /** 397 * The name of the package that owns this directory. Contacts Provider 398 * fill it in with the name of the package containing the directory provider. 399 * If the package is later uninstalled, the directories it owns are 400 * automatically removed from this table. 401 * 402 * <p>TYPE: TEXT</p> 403 */ 404 public static final String PACKAGE_NAME = "packageName"; 405 406 /** 407 * The type of directory captured as a resource ID in the context of the 408 * package {@link #PACKAGE_NAME}, e.g. "Corporate Directory" 409 * 410 * <p>TYPE: INTEGER</p> 411 */ 412 public static final String TYPE_RESOURCE_ID = "typeResourceId"; 413 414 /** 415 * An optional name that can be used in the UI to represent this directory, 416 * e.g. "Acme Corp" 417 * <p>TYPE: text</p> 418 */ 419 public static final String DISPLAY_NAME = "displayName"; 420 421 /** 422 * <p> 423 * The authority of the Directory Provider. Contacts Provider will 424 * use this authority to forward requests to the directory provider. 425 * A directory provider can leave this column empty - Contacts Provider will fill it in. 426 * </p> 427 * <p> 428 * Clients of this API should not send requests directly to this authority. 429 * All directory requests must be routed through Contacts Provider. 430 * </p> 431 * 432 * <p>TYPE: text</p> 433 */ 434 public static final String DIRECTORY_AUTHORITY = "authority"; 435 436 /** 437 * The account type which this directory is associated. 438 * 439 * <p>TYPE: text</p> 440 */ 441 public static final String ACCOUNT_TYPE = "accountType"; 442 443 /** 444 * The account with which this directory is associated. If the account is later 445 * removed, the directories it owns are automatically removed from this table. 446 * 447 * <p>TYPE: text</p> 448 */ 449 public static final String ACCOUNT_NAME = "accountName"; 450 451 /** 452 * One of {@link #EXPORT_SUPPORT_NONE}, {@link #EXPORT_SUPPORT_ANY_ACCOUNT}, 453 * {@link #EXPORT_SUPPORT_SAME_ACCOUNT_ONLY}. This is the expectation the 454 * directory has for data exported from it. Clients must obey this setting. 455 */ 456 public static final String EXPORT_SUPPORT = "exportSupport"; 457 458 /** 459 * An {@link #EXPORT_SUPPORT} setting that indicates that the directory 460 * does not allow any data to be copied out of it. 461 */ 462 public static final int EXPORT_SUPPORT_NONE = 0; 463 464 /** 465 * An {@link #EXPORT_SUPPORT} setting that indicates that the directory 466 * allow its data copied only to the account specified by 467 * {@link #ACCOUNT_TYPE}/{@link #ACCOUNT_NAME}. 468 */ 469 public static final int EXPORT_SUPPORT_SAME_ACCOUNT_ONLY = 1; 470 471 /** 472 * An {@link #EXPORT_SUPPORT} setting that indicates that the directory 473 * allow its data copied to any contacts account. 474 */ 475 public static final int EXPORT_SUPPORT_ANY_ACCOUNT = 2; 476 477 /** 478 * One of {@link #SHORTCUT_SUPPORT_NONE}, {@link #SHORTCUT_SUPPORT_DATA_ITEMS_ONLY}, 479 * {@link #SHORTCUT_SUPPORT_FULL}. This is the expectation the directory 480 * has for shortcuts created for its elements. Clients must obey this setting. 481 */ 482 public static final String SHORTCUT_SUPPORT = "shortcutSupport"; 483 484 /** 485 * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory 486 * does not allow any shortcuts created for its contacts. 487 */ 488 public static final int SHORTCUT_SUPPORT_NONE = 0; 489 490 /** 491 * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory 492 * allow creation of shortcuts for data items like email, phone or postal address, 493 * but not the entire contact. 494 */ 495 public static final int SHORTCUT_SUPPORT_DATA_ITEMS_ONLY = 1; 496 497 /** 498 * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory 499 * allow creation of shortcuts for contact as well as their constituent elements. 500 */ 501 public static final int SHORTCUT_SUPPORT_FULL = 2; 502 503 /** 504 * One of {@link #PHOTO_SUPPORT_NONE}, {@link #PHOTO_SUPPORT_THUMBNAIL_ONLY}, 505 * {@link #PHOTO_SUPPORT_FULL}. This is a feature flag indicating the extent 506 * to which the directory supports contact photos. 507 */ 508 public static final String PHOTO_SUPPORT = "photoSupport"; 509 510 /** 511 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 512 * does not provide any photos. 513 */ 514 public static final int PHOTO_SUPPORT_NONE = 0; 515 516 /** 517 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 518 * can only produce small size thumbnails of contact photos. 519 */ 520 public static final int PHOTO_SUPPORT_THUMBNAIL_ONLY = 1; 521 522 /** 523 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 524 * has full-size contact photos, but cannot provide scaled thumbnails. 525 */ 526 public static final int PHOTO_SUPPORT_FULL_SIZE_ONLY = 2; 527 528 /** 529 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 530 * can produce thumbnails as well as full-size contact photos. 531 */ 532 public static final int PHOTO_SUPPORT_FULL = 3; 533 534 /** 535 * Notifies the system of a change in the list of directories handled by 536 * a particular directory provider. The Contacts provider will turn around 537 * and send a query to the directory provider for the full list of directories, 538 * which will replace the previous list. 539 */ 540 public static void notifyDirectoryChange(ContentResolver resolver) { 541 // This is done to trigger a query by Contacts Provider back to the directory provider. 542 // No data needs to be sent back, because the provider can infer the calling 543 // package from binder. 544 ContentValues contentValues = new ContentValues(); 545 resolver.update(Directory.CONTENT_URI, contentValues, null, null); 546 } 547 } 548 549 /** 550 * @hide should be removed when users are updated to refer to SyncState 551 * @deprecated use SyncState instead 552 */ 553 @Deprecated 554 public interface SyncStateColumns extends SyncStateContract.Columns { 555 } 556 557 /** 558 * A table provided for sync adapters to use for storing private sync state data. 559 * 560 * @see SyncStateContract 561 */ 562 public static final class SyncState implements SyncStateContract.Columns { 563 /** 564 * This utility class cannot be instantiated 565 */ 566 private SyncState() {} 567 568 public static final String CONTENT_DIRECTORY = 569 SyncStateContract.Constants.CONTENT_DIRECTORY; 570 571 /** 572 * The content:// style URI for this table 573 */ 574 public static final Uri CONTENT_URI = 575 Uri.withAppendedPath(AUTHORITY_URI, CONTENT_DIRECTORY); 576 577 /** 578 * @see android.provider.SyncStateContract.Helpers#get 579 */ 580 public static byte[] get(ContentProviderClient provider, Account account) 581 throws RemoteException { 582 return SyncStateContract.Helpers.get(provider, CONTENT_URI, account); 583 } 584 585 /** 586 * @see android.provider.SyncStateContract.Helpers#get 587 */ 588 public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account) 589 throws RemoteException { 590 return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account); 591 } 592 593 /** 594 * @see android.provider.SyncStateContract.Helpers#set 595 */ 596 public static void set(ContentProviderClient provider, Account account, byte[] data) 597 throws RemoteException { 598 SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data); 599 } 600 601 /** 602 * @see android.provider.SyncStateContract.Helpers#newSetOperation 603 */ 604 public static ContentProviderOperation newSetOperation(Account account, byte[] data) { 605 return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data); 606 } 607 } 608 609 /** 610 * Generic columns for use by sync adapters. The specific functions of 611 * these columns are private to the sync adapter. Other clients of the API 612 * should not attempt to either read or write this column. 613 * 614 * @see RawContacts 615 * @see Groups 616 */ 617 protected interface BaseSyncColumns { 618 619 /** Generic column for use by sync adapters. */ 620 public static final String SYNC1 = "sync1"; 621 /** Generic column for use by sync adapters. */ 622 public static final String SYNC2 = "sync2"; 623 /** Generic column for use by sync adapters. */ 624 public static final String SYNC3 = "sync3"; 625 /** Generic column for use by sync adapters. */ 626 public static final String SYNC4 = "sync4"; 627 } 628 629 /** 630 * Columns that appear when each row of a table belongs to a specific 631 * account, including sync information that an account may need. 632 * 633 * @see RawContacts 634 * @see Groups 635 */ 636 protected interface SyncColumns extends BaseSyncColumns { 637 /** 638 * The name of the account instance to which this row belongs, which when paired with 639 * {@link #ACCOUNT_TYPE} identifies a specific account. 640 * <P>Type: TEXT</P> 641 */ 642 public static final String ACCOUNT_NAME = "account_name"; 643 644 /** 645 * The type of account to which this row belongs, which when paired with 646 * {@link #ACCOUNT_NAME} identifies a specific account. 647 * <P>Type: TEXT</P> 648 */ 649 public static final String ACCOUNT_TYPE = "account_type"; 650 651 /** 652 * String that uniquely identifies this row to its source account. 653 * <P>Type: TEXT</P> 654 */ 655 public static final String SOURCE_ID = "sourceid"; 656 657 /** 658 * Version number that is updated whenever this row or its related data 659 * changes. 660 * <P>Type: INTEGER</P> 661 */ 662 public static final String VERSION = "version"; 663 664 /** 665 * Flag indicating that {@link #VERSION} has changed, and this row needs 666 * to be synchronized by its owning account. 667 * <P>Type: INTEGER (boolean)</P> 668 */ 669 public static final String DIRTY = "dirty"; 670 } 671 672 /** 673 * Columns of {@link ContactsContract.Contacts} that track the user's 674 * preferences for, or interactions with, the contact. 675 * 676 * @see Contacts 677 * @see RawContacts 678 * @see ContactsContract.Data 679 * @see PhoneLookup 680 * @see ContactsContract.Contacts.AggregationSuggestions 681 */ 682 protected interface ContactOptionsColumns { 683 /** 684 * The number of times a contact has been contacted 685 * <P>Type: INTEGER</P> 686 */ 687 public static final String TIMES_CONTACTED = "times_contacted"; 688 689 /** 690 * The last time a contact was contacted. 691 * <P>Type: INTEGER</P> 692 */ 693 public static final String LAST_TIME_CONTACTED = "last_time_contacted"; 694 695 /** 696 * Is the contact starred? 697 * <P>Type: INTEGER (boolean)</P> 698 */ 699 public static final String STARRED = "starred"; 700 701 /** 702 * URI for a custom ringtone associated with the contact. If null or missing, 703 * the default ringtone is used. 704 * <P>Type: TEXT (URI to the ringtone)</P> 705 */ 706 public static final String CUSTOM_RINGTONE = "custom_ringtone"; 707 708 /** 709 * Whether the contact should always be sent to voicemail. If missing, 710 * defaults to false. 711 * <P>Type: INTEGER (0 for false, 1 for true)</P> 712 */ 713 public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; 714 } 715 716 /** 717 * Columns of {@link ContactsContract.Contacts} that refer to intrinsic 718 * properties of the contact, as opposed to the user-specified options 719 * found in {@link ContactOptionsColumns}. 720 * 721 * @see Contacts 722 * @see ContactsContract.Data 723 * @see PhoneLookup 724 * @see ContactsContract.Contacts.AggregationSuggestions 725 */ 726 protected interface ContactsColumns { 727 /** 728 * The display name for the contact. 729 * <P>Type: TEXT</P> 730 */ 731 public static final String DISPLAY_NAME = ContactNameColumns.DISPLAY_NAME_PRIMARY; 732 733 /** 734 * Reference to the row in the RawContacts table holding the contact name. 735 * <P>Type: INTEGER REFERENCES raw_contacts(_id)</P> 736 * @hide 737 */ 738 public static final String NAME_RAW_CONTACT_ID = "name_raw_contact_id"; 739 740 /** 741 * Reference to the row in the data table holding the photo. A photo can 742 * be referred to either by ID (this field) or by URI (see {@link #PHOTO_THUMBNAIL_URI} 743 * and {@link #PHOTO_URI}). 744 * If PHOTO_ID is null, consult {@link #PHOTO_URI} or {@link #PHOTO_THUMBNAIL_URI}, 745 * which is a more generic mechanism for referencing the contact photo, especially for 746 * contacts returned by non-local directories (see {@link Directory}). 747 * 748 * <P>Type: INTEGER REFERENCES data(_id)</P> 749 */ 750 public static final String PHOTO_ID = "photo_id"; 751 752 /** 753 * A URI that can be used to retrieve the contact's full-size photo. 754 * A photo can be referred to either by a URI (this field) or by ID 755 * (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and 756 * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa). 757 * Thus using PHOTO_URI is a more robust method of retrieving contact photos. 758 * 759 * <P>Type: TEXT</P> 760 */ 761 public static final String PHOTO_URI = "photo_uri"; 762 763 /** 764 * A URI that can be used to retrieve a thumbnail of the contact's photo. 765 * A photo can be referred to either by a URI (this field or {@link #PHOTO_URI}) 766 * or by ID (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and 767 * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa). 768 * If the content provider does not differentiate between full-size photos 769 * and thumbnail photos, PHOTO_THUMBNAIL_URI and {@link #PHOTO_URI} can contain 770 * the same value, but either both shell be null or both not null. 771 * 772 * <P>Type: TEXT</P> 773 */ 774 public static final String PHOTO_THUMBNAIL_URI = "photo_thumb_uri"; 775 776 /** 777 * Flag that reflects the {@link Groups#GROUP_VISIBLE} state of any 778 * {@link CommonDataKinds.GroupMembership} for this contact. 779 */ 780 public static final String IN_VISIBLE_GROUP = "in_visible_group"; 781 782 /** 783 * Flag that reflects whether this contact represents the user's 784 * personal profile entry. 785 */ 786 public static final String IS_USER_PROFILE = "is_user_profile"; 787 788 /** 789 * An indicator of whether this contact has at least one phone number. "1" if there is 790 * at least one phone number, "0" otherwise. 791 * <P>Type: INTEGER</P> 792 */ 793 public static final String HAS_PHONE_NUMBER = "has_phone_number"; 794 795 /** 796 * An opaque value that contains hints on how to find the contact if 797 * its row id changed as a result of a sync or aggregation. 798 */ 799 public static final String LOOKUP_KEY = "lookup"; 800 } 801 802 /** 803 * @see Contacts 804 */ 805 protected interface ContactStatusColumns { 806 /** 807 * Contact presence status. See {@link StatusUpdates} for individual status 808 * definitions. 809 * <p>Type: NUMBER</p> 810 */ 811 public static final String CONTACT_PRESENCE = "contact_presence"; 812 813 /** 814 * Contact Chat Capabilities. See {@link StatusUpdates} for individual 815 * definitions. 816 * <p>Type: NUMBER</p> 817 */ 818 public static final String CONTACT_CHAT_CAPABILITY = "contact_chat_capability"; 819 820 /** 821 * Contact's latest status update. 822 * <p>Type: TEXT</p> 823 */ 824 public static final String CONTACT_STATUS = "contact_status"; 825 826 /** 827 * The absolute time in milliseconds when the latest status was 828 * inserted/updated. 829 * <p>Type: NUMBER</p> 830 */ 831 public static final String CONTACT_STATUS_TIMESTAMP = "contact_status_ts"; 832 833 /** 834 * The package containing resources for this status: label and icon. 835 * <p>Type: TEXT</p> 836 */ 837 public static final String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package"; 838 839 /** 840 * The resource ID of the label describing the source of contact 841 * status, e.g. "Google Talk". This resource is scoped by the 842 * {@link #CONTACT_STATUS_RES_PACKAGE}. 843 * <p>Type: NUMBER</p> 844 */ 845 public static final String CONTACT_STATUS_LABEL = "contact_status_label"; 846 847 /** 848 * The resource ID of the icon for the source of contact status. This 849 * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}. 850 * <p>Type: NUMBER</p> 851 */ 852 public static final String CONTACT_STATUS_ICON = "contact_status_icon"; 853 } 854 855 /** 856 * Constants for various styles of combining given name, family name etc into 857 * a full name. For example, the western tradition follows the pattern 858 * 'given name' 'middle name' 'family name' with the alternative pattern being 859 * 'family name', 'given name' 'middle name'. The CJK tradition is 860 * 'family name' 'middle name' 'given name', with Japanese favoring a space between 861 * the names and Chinese omitting the space. 862 */ 863 public interface FullNameStyle { 864 public static final int UNDEFINED = 0; 865 public static final int WESTERN = 1; 866 867 /** 868 * Used if the name is written in Hanzi/Kanji/Hanja and we could not determine 869 * which specific language it belongs to: Chinese, Japanese or Korean. 870 */ 871 public static final int CJK = 2; 872 873 public static final int CHINESE = 3; 874 public static final int JAPANESE = 4; 875 public static final int KOREAN = 5; 876 } 877 878 /** 879 * Constants for various styles of capturing the pronunciation of a person's name. 880 */ 881 public interface PhoneticNameStyle { 882 public static final int UNDEFINED = 0; 883 884 /** 885 * Pinyin is a phonetic method of entering Chinese characters. Typically not explicitly 886 * shown in UIs, but used for searches and sorting. 887 */ 888 public static final int PINYIN = 3; 889 890 /** 891 * Hiragana and Katakana are two common styles of writing out the pronunciation 892 * of a Japanese names. 893 */ 894 public static final int JAPANESE = 4; 895 896 /** 897 * Hangul is the Korean phonetic alphabet. 898 */ 899 public static final int KOREAN = 5; 900 } 901 902 /** 903 * Types of data used to produce the display name for a contact. In the order 904 * of increasing priority: {@link #EMAIL}, {@link #PHONE}, 905 * {@link #ORGANIZATION}, {@link #NICKNAME}, {@link #STRUCTURED_NAME}. 906 */ 907 public interface DisplayNameSources { 908 public static final int UNDEFINED = 0; 909 public static final int EMAIL = 10; 910 public static final int PHONE = 20; 911 public static final int ORGANIZATION = 30; 912 public static final int NICKNAME = 35; 913 public static final int STRUCTURED_NAME = 40; 914 } 915 916 /** 917 * Contact name and contact name metadata columns in the RawContacts table. 918 * 919 * @see Contacts 920 * @see RawContacts 921 */ 922 protected interface ContactNameColumns { 923 924 /** 925 * The kind of data that is used as the display name for the contact, such as 926 * structured name or email address. See {@link DisplayNameSources}. 927 */ 928 public static final String DISPLAY_NAME_SOURCE = "display_name_source"; 929 930 /** 931 * <p> 932 * The standard text shown as the contact's display name, based on the best 933 * available information for the contact (for example, it might be the email address 934 * if the name is not available). 935 * The information actually used to compute the name is stored in 936 * {@link #DISPLAY_NAME_SOURCE}. 937 * </p> 938 * <p> 939 * A contacts provider is free to choose whatever representation makes most 940 * sense for its target market. 941 * For example in the default Android Open Source Project implementation, 942 * if the display name is 943 * based on the structured name and the structured name follows 944 * the Western full-name style, then this field contains the "given name first" 945 * version of the full name. 946 * <p> 947 * 948 * @see ContactsContract.ContactNameColumns#DISPLAY_NAME_ALTERNATIVE 949 */ 950 public static final String DISPLAY_NAME_PRIMARY = "display_name"; 951 952 /** 953 * <p> 954 * An alternative representation of the display name, such as "family name first" 955 * instead of "given name first" for Western names. If an alternative is not 956 * available, the values should be the same as {@link #DISPLAY_NAME_PRIMARY}. 957 * </p> 958 * <p> 959 * A contacts provider is free to provide alternatives as necessary for 960 * its target market. 961 * For example the default Android Open Source Project contacts provider 962 * currently provides an 963 * alternative in a single case: if the display name is 964 * based on the structured name and the structured name follows 965 * the Western full name style, then the field contains the "family name first" 966 * version of the full name. 967 * Other cases may be added later. 968 * </p> 969 */ 970 public static final String DISPLAY_NAME_ALTERNATIVE = "display_name_alt"; 971 972 /** 973 * The phonetic alphabet used to represent the {@link #PHONETIC_NAME}. See 974 * {@link PhoneticNameStyle}. 975 */ 976 public static final String PHONETIC_NAME_STYLE = "phonetic_name_style"; 977 978 /** 979 * <p> 980 * Pronunciation of the full name in the phonetic alphabet specified by 981 * {@link #PHONETIC_NAME_STYLE}. 982 * </p> 983 * <p> 984 * The value may be set manually by the user. This capability is of 985 * interest only in countries with commonly used phonetic alphabets, 986 * such as Japan and Korea. See {@link PhoneticNameStyle}. 987 * </p> 988 */ 989 public static final String PHONETIC_NAME = "phonetic_name"; 990 991 /** 992 * Sort key that takes into account locale-based traditions for sorting 993 * names in address books. The default 994 * sort key is {@link #DISPLAY_NAME_PRIMARY}. For Chinese names 995 * the sort key is the name's Pinyin spelling, and for Japanese names 996 * it is the Hiragana version of the phonetic name. 997 */ 998 public static final String SORT_KEY_PRIMARY = "sort_key"; 999 1000 /** 1001 * Sort key based on the alternative representation of the full name, 1002 * {@link #DISPLAY_NAME_ALTERNATIVE}. Thus for Western names, 1003 * it is the one using the "family name first" format. 1004 */ 1005 public static final String SORT_KEY_ALTERNATIVE = "sort_key_alt"; 1006 } 1007 1008 /** 1009 * URI parameter and cursor extras that return counts of rows grouped by the 1010 * address book index, which is usually the first letter of the sort key. 1011 * When this parameter is supplied, the row counts are returned in the 1012 * cursor extras bundle. 1013 * 1014 * @hide 1015 */ 1016 public final static class ContactCounts { 1017 1018 /** 1019 * Add this query parameter to a URI to get back row counts grouped by 1020 * the address book index as cursor extras. For most languages it is the 1021 * first letter of the sort key. This parameter does not affect the main 1022 * content of the cursor. 1023 * 1024 * @hide 1025 */ 1026 public static final String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras"; 1027 1028 /** 1029 * The array of address book index titles, which are returned in the 1030 * same order as the data in the cursor. 1031 * <p>TYPE: String[]</p> 1032 * 1033 * @hide 1034 */ 1035 public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles"; 1036 1037 /** 1038 * The array of group counts for the corresponding group. Contains the same number 1039 * of elements as the EXTRA_ADDRESS_BOOK_INDEX_TITLES array. 1040 * <p>TYPE: int[]</p> 1041 * 1042 * @hide 1043 */ 1044 public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts"; 1045 } 1046 1047 /** 1048 * Constants for the contacts table, which contains a record per aggregate 1049 * of raw contacts representing the same person. 1050 * <h3>Operations</h3> 1051 * <dl> 1052 * <dt><b>Insert</b></dt> 1053 * <dd>A Contact cannot be created explicitly. When a raw contact is 1054 * inserted, the provider will first try to find a Contact representing the 1055 * same person. If one is found, the raw contact's 1056 * {@link RawContacts#CONTACT_ID} column gets the _ID of the aggregate 1057 * Contact. If no match is found, the provider automatically inserts a new 1058 * Contact and puts its _ID into the {@link RawContacts#CONTACT_ID} column 1059 * of the newly inserted raw contact.</dd> 1060 * <dt><b>Update</b></dt> 1061 * <dd>Only certain columns of Contact are modifiable: 1062 * {@link #TIMES_CONTACTED}, {@link #LAST_TIME_CONTACTED}, {@link #STARRED}, 1063 * {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of 1064 * these columns on the Contact also changes them on all constituent raw 1065 * contacts.</dd> 1066 * <dt><b>Delete</b></dt> 1067 * <dd>Be careful with deleting Contacts! Deleting an aggregate contact 1068 * deletes all constituent raw contacts. The corresponding sync adapters 1069 * will notice the deletions of their respective raw contacts and remove 1070 * them from their back end storage.</dd> 1071 * <dt><b>Query</b></dt> 1072 * <dd> 1073 * <ul> 1074 * <li>If you need to read an individual contact, consider using 1075 * {@link #CONTENT_LOOKUP_URI} instead of {@link #CONTENT_URI}.</li> 1076 * <li>If you need to look up a contact by the phone number, use 1077 * {@link PhoneLookup#CONTENT_FILTER_URI PhoneLookup.CONTENT_FILTER_URI}, 1078 * which is optimized for this purpose.</li> 1079 * <li>If you need to look up a contact by partial name, e.g. to produce 1080 * filter-as-you-type suggestions, use the {@link #CONTENT_FILTER_URI} URI. 1081 * <li>If you need to look up a contact by some data element like email 1082 * address, nickname, etc, use a query against the {@link ContactsContract.Data} table. 1083 * The result will contain contact ID, name etc. 1084 * </ul> 1085 * </dd> 1086 * </dl> 1087 * <h2>Columns</h2> 1088 * <table class="jd-sumtable"> 1089 * <tr> 1090 * <th colspan='4'>Contacts</th> 1091 * </tr> 1092 * <tr> 1093 * <td>long</td> 1094 * <td>{@link #_ID}</td> 1095 * <td>read-only</td> 1096 * <td>Row ID. Consider using {@link #LOOKUP_KEY} instead.</td> 1097 * </tr> 1098 * <tr> 1099 * <td>String</td> 1100 * <td>{@link #LOOKUP_KEY}</td> 1101 * <td>read-only</td> 1102 * <td>An opaque value that contains hints on how to find the contact if its 1103 * row id changed as a result of a sync or aggregation.</td> 1104 * </tr> 1105 * <tr> 1106 * <td>long</td> 1107 * <td>NAME_RAW_CONTACT_ID</td> 1108 * <td>read-only</td> 1109 * <td>The ID of the raw contact that contributes the display name 1110 * to the aggregate contact. During aggregation one of the constituent 1111 * raw contacts is chosen using a heuristic: a longer name or a name 1112 * with more diacritic marks or more upper case characters is chosen.</td> 1113 * </tr> 1114 * <tr> 1115 * <td>String</td> 1116 * <td>DISPLAY_NAME_PRIMARY</td> 1117 * <td>read-only</td> 1118 * <td>The display name for the contact. It is the display name 1119 * contributed by the raw contact referred to by the NAME_RAW_CONTACT_ID 1120 * column.</td> 1121 * </tr> 1122 * <tr> 1123 * <td>long</td> 1124 * <td>{@link #PHOTO_ID}</td> 1125 * <td>read-only</td> 1126 * <td>Reference to the row in the {@link ContactsContract.Data} table holding the photo. 1127 * That row has the mime type 1128 * {@link CommonDataKinds.Photo#CONTENT_ITEM_TYPE}. The value of this field 1129 * is computed automatically based on the 1130 * {@link CommonDataKinds.Photo#IS_SUPER_PRIMARY} field of the data rows of 1131 * that mime type.</td> 1132 * </tr> 1133 * <tr> 1134 * <td>long</td> 1135 * <td>{@link #PHOTO_URI}</td> 1136 * <td>read-only</td> 1137 * <td>A URI that can be used to retrieve the contact's full-size photo. This 1138 * column is the preferred method of retrieving the contact photo.</td> 1139 * </tr> 1140 * <tr> 1141 * <td>long</td> 1142 * <td>{@link #PHOTO_THUMBNAIL_URI}</td> 1143 * <td>read-only</td> 1144 * <td>A URI that can be used to retrieve the thumbnail of contact's photo. This 1145 * column is the preferred method of retrieving the contact photo.</td> 1146 * </tr> 1147 * <tr> 1148 * <td>int</td> 1149 * <td>{@link #IN_VISIBLE_GROUP}</td> 1150 * <td>read-only</td> 1151 * <td>An indicator of whether this contact is supposed to be visible in the 1152 * UI. "1" if the contact has at least one raw contact that belongs to a 1153 * visible group; "0" otherwise.</td> 1154 * </tr> 1155 * <tr> 1156 * <td>int</td> 1157 * <td>{@link #HAS_PHONE_NUMBER}</td> 1158 * <td>read-only</td> 1159 * <td>An indicator of whether this contact has at least one phone number. 1160 * "1" if there is at least one phone number, "0" otherwise.</td> 1161 * </tr> 1162 * <tr> 1163 * <td>int</td> 1164 * <td>{@link #TIMES_CONTACTED}</td> 1165 * <td>read/write</td> 1166 * <td>The number of times the contact has been contacted. See 1167 * {@link #markAsContacted}. When raw contacts are aggregated, this field is 1168 * computed automatically as the maximum number of times contacted among all 1169 * constituent raw contacts. Setting this field automatically changes the 1170 * corresponding field on all constituent raw contacts.</td> 1171 * </tr> 1172 * <tr> 1173 * <td>long</td> 1174 * <td>{@link #LAST_TIME_CONTACTED}</td> 1175 * <td>read/write</td> 1176 * <td>The timestamp of the last time the contact was contacted. See 1177 * {@link #markAsContacted}. Setting this field also automatically 1178 * increments {@link #TIMES_CONTACTED}. When raw contacts are aggregated, 1179 * this field is computed automatically as the latest time contacted of all 1180 * constituent raw contacts. Setting this field automatically changes the 1181 * corresponding field on all constituent raw contacts.</td> 1182 * </tr> 1183 * <tr> 1184 * <td>int</td> 1185 * <td>{@link #STARRED}</td> 1186 * <td>read/write</td> 1187 * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise. 1188 * When raw contacts are aggregated, this field is automatically computed: 1189 * if any constituent raw contacts are starred, then this field is set to 1190 * '1'. Setting this field automatically changes the corresponding field on 1191 * all constituent raw contacts.</td> 1192 * </tr> 1193 * <tr> 1194 * <td>String</td> 1195 * <td>{@link #CUSTOM_RINGTONE}</td> 1196 * <td>read/write</td> 1197 * <td>A custom ringtone associated with a contact. Typically this is the 1198 * URI returned by an activity launched with the 1199 * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent.</td> 1200 * </tr> 1201 * <tr> 1202 * <td>int</td> 1203 * <td>{@link #SEND_TO_VOICEMAIL}</td> 1204 * <td>read/write</td> 1205 * <td>An indicator of whether calls from this contact should be forwarded 1206 * directly to voice mail ('1') or not ('0'). When raw contacts are 1207 * aggregated, this field is automatically computed: if <i>all</i> 1208 * constituent raw contacts have SEND_TO_VOICEMAIL=1, then this field is set 1209 * to '1'. Setting this field automatically changes the corresponding field 1210 * on all constituent raw contacts.</td> 1211 * </tr> 1212 * <tr> 1213 * <td>int</td> 1214 * <td>{@link #CONTACT_PRESENCE}</td> 1215 * <td>read-only</td> 1216 * <td>Contact IM presence status. See {@link StatusUpdates} for individual 1217 * status definitions. Automatically computed as the highest presence of all 1218 * constituent raw contacts. The provider may choose not to store this value 1219 * in persistent storage. The expectation is that presence status will be 1220 * updated on a regular basic.</td> 1221 * </tr> 1222 * <tr> 1223 * <td>String</td> 1224 * <td>{@link #CONTACT_STATUS}</td> 1225 * <td>read-only</td> 1226 * <td>Contact's latest status update. Automatically computed as the latest 1227 * of all constituent raw contacts' status updates.</td> 1228 * </tr> 1229 * <tr> 1230 * <td>long</td> 1231 * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td> 1232 * <td>read-only</td> 1233 * <td>The absolute time in milliseconds when the latest status was 1234 * inserted/updated.</td> 1235 * </tr> 1236 * <tr> 1237 * <td>String</td> 1238 * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td> 1239 * <td>read-only</td> 1240 * <td> The package containing resources for this status: label and icon.</td> 1241 * </tr> 1242 * <tr> 1243 * <td>long</td> 1244 * <td>{@link #CONTACT_STATUS_LABEL}</td> 1245 * <td>read-only</td> 1246 * <td>The resource ID of the label describing the source of contact status, 1247 * e.g. "Google Talk". This resource is scoped by the 1248 * {@link #CONTACT_STATUS_RES_PACKAGE}.</td> 1249 * </tr> 1250 * <tr> 1251 * <td>long</td> 1252 * <td>{@link #CONTACT_STATUS_ICON}</td> 1253 * <td>read-only</td> 1254 * <td>The resource ID of the icon for the source of contact status. This 1255 * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}.</td> 1256 * </tr> 1257 * </table> 1258 */ 1259 public static class Contacts implements BaseColumns, ContactsColumns, 1260 ContactOptionsColumns, ContactNameColumns, ContactStatusColumns { 1261 /** 1262 * This utility class cannot be instantiated 1263 */ 1264 private Contacts() {} 1265 1266 /** 1267 * The content:// style URI for this table 1268 */ 1269 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts"); 1270 1271 /** 1272 * A content:// style URI for this table that should be used to create 1273 * shortcuts or otherwise create long-term links to contacts. This URI 1274 * should always be followed by a "/" and the contact's {@link #LOOKUP_KEY}. 1275 * It can optionally also have a "/" and last known contact ID appended after 1276 * that. This "complete" format is an important optimization and is highly recommended. 1277 * <p> 1278 * As long as the contact's row ID remains the same, this URI is 1279 * equivalent to {@link #CONTENT_URI}. If the contact's row ID changes 1280 * as a result of a sync or aggregation, this URI will look up the 1281 * contact using indirect information (sync IDs or constituent raw 1282 * contacts). 1283 * <p> 1284 * Lookup key should be appended unencoded - it is stored in the encoded 1285 * form, ready for use in a URI. 1286 */ 1287 public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, 1288 "lookup"); 1289 1290 /** 1291 * Base {@link Uri} for referencing a single {@link Contacts} entry, 1292 * created by appending {@link #LOOKUP_KEY} using 1293 * {@link Uri#withAppendedPath(Uri, String)}. Provides 1294 * {@link OpenableColumns} columns when queried, or returns the 1295 * referenced contact formatted as a vCard when opened through 1296 * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. 1297 */ 1298 public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, 1299 "as_vcard"); 1300 1301 /** 1302 * Boolean parameter that may be used with {@link #CONTENT_VCARD_URI} 1303 * and {@link #CONTENT_MULTI_VCARD_URI} to indicate that the returned 1304 * vcard should not contain a photo. 1305 * 1306 * @hide 1307 */ 1308 public static final String QUERY_PARAMETER_VCARD_NO_PHOTO = "nophoto"; 1309 1310 /** 1311 * Base {@link Uri} for referencing multiple {@link Contacts} entry, 1312 * created by appending {@link #LOOKUP_KEY} using 1313 * {@link Uri#withAppendedPath(Uri, String)}. The lookup keys have to be 1314 * encoded and joined with the colon (":") separator. The resulting string 1315 * has to be encoded again. Provides 1316 * {@link OpenableColumns} columns when queried, or returns the 1317 * referenced contact formatted as a vCard when opened through 1318 * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. 1319 * 1320 * This is private API because we do not have a well-defined way to 1321 * specify several entities yet. The format of this Uri might change in the future 1322 * or the Uri might be completely removed. 1323 * 1324 * @hide 1325 */ 1326 public static final Uri CONTENT_MULTI_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, 1327 "as_multi_vcard"); 1328 1329 /** 1330 * Builds a {@link #CONTENT_LOOKUP_URI} style {@link Uri} describing the 1331 * requested {@link Contacts} entry. 1332 * 1333 * @param contactUri A {@link #CONTENT_URI} row, or an existing 1334 * {@link #CONTENT_LOOKUP_URI} to attempt refreshing. 1335 */ 1336 public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) { 1337 final Cursor c = resolver.query(contactUri, new String[] { 1338 Contacts.LOOKUP_KEY, Contacts._ID 1339 }, null, null, null); 1340 if (c == null) { 1341 return null; 1342 } 1343 1344 try { 1345 if (c.moveToFirst()) { 1346 final String lookupKey = c.getString(0); 1347 final long contactId = c.getLong(1); 1348 return getLookupUri(contactId, lookupKey); 1349 } 1350 } finally { 1351 c.close(); 1352 } 1353 return null; 1354 } 1355 1356 /** 1357 * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the 1358 * given {@link ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}. 1359 */ 1360 public static Uri getLookupUri(long contactId, String lookupKey) { 1361 return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, 1362 lookupKey), contactId); 1363 } 1364 1365 /** 1366 * Computes a content URI (see {@link #CONTENT_URI}) given a lookup URI. 1367 * <p> 1368 * Returns null if the contact cannot be found. 1369 */ 1370 public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) { 1371 if (lookupUri == null) { 1372 return null; 1373 } 1374 1375 Cursor c = resolver.query(lookupUri, new String[]{Contacts._ID}, null, null, null); 1376 if (c == null) { 1377 return null; 1378 } 1379 1380 try { 1381 if (c.moveToFirst()) { 1382 long contactId = c.getLong(0); 1383 return ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1384 } 1385 } finally { 1386 c.close(); 1387 } 1388 return null; 1389 } 1390 1391 /** 1392 * Mark a contact as having been contacted. Updates two fields: 1393 * {@link #TIMES_CONTACTED} and {@link #LAST_TIME_CONTACTED}. The 1394 * TIMES_CONTACTED field is incremented by 1 and the LAST_TIME_CONTACTED 1395 * field is populated with the current system time. 1396 * 1397 * @param resolver the ContentResolver to use 1398 * @param contactId the person who was contacted 1399 */ 1400 public static void markAsContacted(ContentResolver resolver, long contactId) { 1401 Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId); 1402 ContentValues values = new ContentValues(); 1403 // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified. 1404 values.put(LAST_TIME_CONTACTED, System.currentTimeMillis()); 1405 resolver.update(uri, values, null, null); 1406 } 1407 1408 /** 1409 * The content:// style URI used for "type-to-filter" functionality on the 1410 * {@link #CONTENT_URI} URI. The filter string will be used to match 1411 * various parts of the contact name. The filter argument should be passed 1412 * as an additional path segment after this URI. 1413 */ 1414 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath( 1415 CONTENT_URI, "filter"); 1416 1417 /** 1418 * The content:// style URI for this table joined with useful data from 1419 * {@link ContactsContract.Data}, filtered to include only starred contacts 1420 * and the most frequently contacted contacts. 1421 */ 1422 public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath( 1423 CONTENT_URI, "strequent"); 1424 1425 /** 1426 * The content:// style URI used for "type-to-filter" functionality on the 1427 * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match 1428 * various parts of the contact name. The filter argument should be passed 1429 * as an additional path segment after this URI. 1430 */ 1431 public static final Uri CONTENT_STREQUENT_FILTER_URI = Uri.withAppendedPath( 1432 CONTENT_STREQUENT_URI, "filter"); 1433 1434 public static final Uri CONTENT_GROUP_URI = Uri.withAppendedPath( 1435 CONTENT_URI, "group"); 1436 1437 /** 1438 * The MIME type of {@link #CONTENT_URI} providing a directory of 1439 * people. 1440 */ 1441 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact"; 1442 1443 /** 1444 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 1445 * person. 1446 */ 1447 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact"; 1448 1449 /** 1450 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 1451 * person. 1452 */ 1453 public static final String CONTENT_VCARD_TYPE = "text/x-vcard"; 1454 1455 /** 1456 * A sub-directory of a single contact that contains all of the constituent raw contact 1457 * {@link ContactsContract.Data} rows. This directory can be used either 1458 * with a {@link #CONTENT_URI} or {@link #CONTENT_LOOKUP_URI}. 1459 */ 1460 public static final class Data implements BaseColumns, DataColumns { 1461 /** 1462 * no public constructor since this is a utility class 1463 */ 1464 private Data() {} 1465 1466 /** 1467 * The directory twig for this sub-table 1468 */ 1469 public static final String CONTENT_DIRECTORY = "data"; 1470 } 1471 1472 /** 1473 * <p> 1474 * A sub-directory of a contact that contains all of its 1475 * {@link ContactsContract.RawContacts} as well as 1476 * {@link ContactsContract.Data} rows. To access this directory append 1477 * {@link #CONTENT_DIRECTORY} to the contact URI. 1478 * </p> 1479 * <p> 1480 * Entity has three ID fields: {@link #CONTACT_ID} for the contact, 1481 * {@link #RAW_CONTACT_ID} for the raw contact and {@link #DATA_ID} for 1482 * the data rows. Entity always contains at least one row per 1483 * constituent raw contact, even if there are no actual data rows. In 1484 * this case the {@link #DATA_ID} field will be null. 1485 * </p> 1486 * <p> 1487 * Entity reads all data for the entire contact in one transaction, to 1488 * guarantee consistency. There is significant data duplication 1489 * in the Entity (each row repeats all Contact columns and all RawContact 1490 * columns), so the benefits of transactional consistency should be weighed 1491 * against the cost of transferring large amounts of denormalized data 1492 * from the Provider. 1493 * </p> 1494 * <p> 1495 * To reduce the amount of data duplication the contacts provider and directory 1496 * providers implementing this protocol are allowed to provide common Contacts 1497 * and RawContacts fields in the first row returned for each raw contact only and 1498 * leave them as null in subsequent rows. 1499 * </p> 1500 */ 1501 public static final class Entity implements BaseColumns, ContactsColumns, 1502 ContactNameColumns, RawContactsColumns, BaseSyncColumns, SyncColumns, DataColumns, 1503 StatusColumns, ContactOptionsColumns, ContactStatusColumns { 1504 /** 1505 * no public constructor since this is a utility class 1506 */ 1507 private Entity() { 1508 } 1509 1510 /** 1511 * The directory twig for this sub-table 1512 */ 1513 public static final String CONTENT_DIRECTORY = "entities"; 1514 1515 /** 1516 * The ID of the raw contact row. 1517 * <P>Type: INTEGER</P> 1518 */ 1519 public static final String RAW_CONTACT_ID = "raw_contact_id"; 1520 1521 /** 1522 * The ID of the data row. The value will be null if this raw contact has no 1523 * data rows. 1524 * <P>Type: INTEGER</P> 1525 */ 1526 public static final String DATA_ID = "data_id"; 1527 } 1528 1529 /** 1530 * <p> 1531 * A <i>read-only</i> sub-directory of a single contact aggregate that 1532 * contains all aggregation suggestions (other contacts). The 1533 * aggregation suggestions are computed based on approximate data 1534 * matches with this contact. 1535 * </p> 1536 * <p> 1537 * <i>Note: this query may be expensive! If you need to use it in bulk, 1538 * make sure the user experience is acceptable when the query runs for a 1539 * long time.</i> 1540 * <p> 1541 * Usage example: 1542 * 1543 * <pre> 1544 * Uri uri = Contacts.CONTENT_URI.buildUpon() 1545 * .appendEncodedPath(String.valueOf(contactId)) 1546 * .appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY) 1547 * .appendQueryParameter("limit", "3") 1548 * .build() 1549 * Cursor cursor = getContentResolver().query(suggestionsUri, 1550 * new String[] {Contacts.DISPLAY_NAME, Contacts._ID, Contacts.LOOKUP_KEY}, 1551 * null, null, null); 1552 * </pre> 1553 * 1554 * </p> 1555 * <p> 1556 * This directory can be used either with a {@link #CONTENT_URI} or 1557 * {@link #CONTENT_LOOKUP_URI}. 1558 * </p> 1559 */ 1560 public static final class AggregationSuggestions implements BaseColumns, ContactsColumns, 1561 ContactOptionsColumns, ContactStatusColumns { 1562 /** 1563 * No public constructor since this is a utility class 1564 */ 1565 private AggregationSuggestions() {} 1566 1567 /** 1568 * The directory twig for this sub-table. The URI can be followed by an optional 1569 * type-to-filter, similar to 1570 * {@link android.provider.ContactsContract.Contacts#CONTENT_FILTER_URI}. 1571 */ 1572 public static final String CONTENT_DIRECTORY = "suggestions"; 1573 1574 /** 1575 * Used with {@link Builder#addParameter} to specify what kind of data is 1576 * supplied for the suggestion query. 1577 * 1578 * @hide 1579 */ 1580 public static final String PARAMETER_MATCH_NAME = "name"; 1581 1582 /** 1583 * Used with {@link Builder#addParameter} to specify what kind of data is 1584 * supplied for the suggestion query. 1585 * 1586 * @hide 1587 */ 1588 public static final String PARAMETER_MATCH_EMAIL = "email"; 1589 1590 /** 1591 * Used with {@link Builder#addParameter} to specify what kind of data is 1592 * supplied for the suggestion query. 1593 * 1594 * @hide 1595 */ 1596 public static final String PARAMETER_MATCH_PHONE = "phone"; 1597 1598 /** 1599 * Used with {@link Builder#addParameter} to specify what kind of data is 1600 * supplied for the suggestion query. 1601 * 1602 * @hide 1603 */ 1604 public static final String PARAMETER_MATCH_NICKNAME = "nickname"; 1605 1606 /** 1607 * A convenience builder for aggregation suggestion content URIs. 1608 * 1609 * TODO: change documentation for this class to use the builder. 1610 * @hide 1611 */ 1612 public static final class Builder { 1613 private long mContactId; 1614 private ArrayList<String> mKinds = new ArrayList<String>(); 1615 private ArrayList<String> mValues = new ArrayList<String>(); 1616 private int mLimit; 1617 1618 /** 1619 * Optional existing contact ID. If it is not provided, the search 1620 * will be based exclusively on the values supplied with {@link #addParameter}. 1621 */ 1622 public Builder setContactId(long contactId) { 1623 this.mContactId = contactId; 1624 return this; 1625 } 1626 1627 /** 1628 * A value that can be used when searching for an aggregation 1629 * suggestion. 1630 * 1631 * @param kind can be one of 1632 * {@link AggregationSuggestions#PARAMETER_MATCH_NAME}, 1633 * {@link AggregationSuggestions#PARAMETER_MATCH_EMAIL}, 1634 * {@link AggregationSuggestions#PARAMETER_MATCH_NICKNAME}, 1635 * {@link AggregationSuggestions#PARAMETER_MATCH_PHONE} 1636 */ 1637 public Builder addParameter(String kind, String value) { 1638 if (!TextUtils.isEmpty(value)) { 1639 mKinds.add(kind); 1640 mValues.add(value); 1641 } 1642 return this; 1643 } 1644 1645 public Builder setLimit(int limit) { 1646 mLimit = limit; 1647 return this; 1648 } 1649 1650 public Uri build() { 1651 android.net.Uri.Builder builder = Contacts.CONTENT_URI.buildUpon(); 1652 builder.appendEncodedPath(String.valueOf(mContactId)); 1653 builder.appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY); 1654 if (mLimit != 0) { 1655 builder.appendQueryParameter("limit", String.valueOf(mLimit)); 1656 } 1657 1658 int count = mKinds.size(); 1659 for (int i = 0; i < count; i++) { 1660 builder.appendQueryParameter("query", mKinds.get(i) + ":" + mValues.get(i)); 1661 } 1662 1663 return builder.build(); 1664 } 1665 } 1666 1667 /** 1668 * @hide 1669 */ 1670 public static final Builder builder() { 1671 return new Builder(); 1672 } 1673 } 1674 1675 /** 1676 * A <i>read-only</i> sub-directory of a single contact that contains 1677 * the contact's primary photo. 1678 * <p> 1679 * Usage example: 1680 * 1681 * <pre> 1682 * public InputStream openPhoto(long contactId) { 1683 * Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1684 * Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); 1685 * Cursor cursor = getContentResolver().query(photoUri, 1686 * new String[] {Contacts.Photo.PHOTO}, null, null, null); 1687 * if (cursor == null) { 1688 * return null; 1689 * } 1690 * try { 1691 * if (cursor.moveToFirst()) { 1692 * byte[] data = cursor.getBlob(0); 1693 * if (data != null) { 1694 * return new ByteArrayInputStream(data); 1695 * } 1696 * } 1697 * } finally { 1698 * cursor.close(); 1699 * } 1700 * return null; 1701 * } 1702 * </pre> 1703 * 1704 * </p> 1705 * <p>You should also consider using the convenience method 1706 * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)} 1707 * </p> 1708 * <p> 1709 * This directory can be used either with a {@link #CONTENT_URI} or 1710 * {@link #CONTENT_LOOKUP_URI}. 1711 * </p> 1712 */ 1713 public static final class Photo implements BaseColumns, DataColumnsWithJoins { 1714 /** 1715 * no public constructor since this is a utility class 1716 */ 1717 private Photo() {} 1718 1719 /** 1720 * The directory twig for this sub-table 1721 */ 1722 public static final String CONTENT_DIRECTORY = "photo"; 1723 1724 /** 1725 * Thumbnail photo of the raw contact. This is the raw bytes of an image 1726 * that could be inflated using {@link android.graphics.BitmapFactory}. 1727 * <p> 1728 * Type: BLOB 1729 */ 1730 public static final String PHOTO = DATA15; 1731 } 1732 1733 /** 1734 * Opens an InputStream for the contacts's default photo and returns the 1735 * photo as a byte stream. If there is not photo null will be returned. 1736 * 1737 * @param contactUri the contact whose photo should be used. This can be used with 1738 * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI. 1739 * </p> 1740 1741 * @return an InputStream of the photo, or null if no photo is present 1742 */ 1743 public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { 1744 Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY); 1745 if (photoUri == null) { 1746 return null; 1747 } 1748 Cursor cursor = cr.query(photoUri, 1749 new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); 1750 try { 1751 if (cursor == null || !cursor.moveToNext()) { 1752 return null; 1753 } 1754 byte[] data = cursor.getBlob(0); 1755 if (data == null) { 1756 return null; 1757 } 1758 return new ByteArrayInputStream(data); 1759 } finally { 1760 if (cursor != null) { 1761 cursor.close(); 1762 } 1763 } 1764 } 1765 } 1766 1767 /** 1768 * <p> 1769 * Constants for the user's profile data, which is represented as a single contact on 1770 * the device that represents the user. The profile contact is not aggregated 1771 * together automatically in the same way that normal contacts are; instead, each 1772 * account on the device may contribute a single raw contact representing the user's 1773 * personal profile data from that source. 1774 * </p> 1775 * <p> 1776 * Access to the profile entry through these URIs (or incidental access to parts of 1777 * the profile if retrieved directly via ID) requires additional permissions beyond 1778 * the read/write contact permissions required by the provider. Querying for profile 1779 * data requires android.permission.READ_PROFILE permission, and inserting or 1780 * updating profile data requires android.permission.WRITE_PROFILE permission. 1781 * </p> 1782 * <h3>Operations</h3> 1783 * <dl> 1784 * <dt><b>Insert</b></dt> 1785 * <dd>The user's profile entry cannot be created explicitly (attempting to do so 1786 * will throw an exception). When a raw contact is inserted into the profile, the 1787 * provider will check for the existence of a profile on the device. If one is 1788 * found, the raw contact's {@link RawContacts#CONTACT_ID} column gets the _ID of 1789 * the profile Contact. If no match is found, the profile Contact is created and 1790 * its _ID is put into the {@link RawContacts#CONTACT_ID} column of the newly 1791 * inserted raw contact.</dd> 1792 * <dt><b>Update</b></dt> 1793 * <dd>The profile Contact has the same update restrictions as Contacts in general, 1794 * but requires the android.permission.WRITE_PROFILE permission.</dd> 1795 * <dt><b>Delete</b></dt> 1796 * <dd>The profile Contact cannot be explicitly deleted. It will be removed 1797 * automatically if all of its constituent raw contact entries are deleted.</dd> 1798 * <dt><b>Query</b></dt> 1799 * <dd> 1800 * <ul> 1801 * <li>The {@link #CONTENT_URI} for profiles behaves in much the same way as 1802 * retrieving a contact by ID, except that it will only ever return the user's 1803 * profile contact. 1804 * </li> 1805 * <li> 1806 * The profile contact supports all of the same sub-paths as an individual contact 1807 * does - the content of the profile contact can be retrieved as entities or 1808 * data rows. Similarly, specific raw contact entries can be retrieved by appending 1809 * the desired raw contact ID within the profile. 1810 * </li> 1811 * </ul> 1812 * </dd> 1813 * </dl> 1814 */ 1815 public static final class Profile implements BaseColumns, ContactsColumns, 1816 ContactOptionsColumns, ContactNameColumns, ContactStatusColumns { 1817 /** 1818 * This utility class cannot be instantiated 1819 */ 1820 private Profile() { 1821 } 1822 1823 /** 1824 * The content:// style URI for this table, which requests the contact entry 1825 * representing the user's personal profile data. 1826 */ 1827 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "profile"); 1828 1829 /** 1830 * {@link Uri} for referencing the user's profile {@link Contacts} entry, 1831 * Provides {@link OpenableColumns} columns when queried, or returns the 1832 * user's profile contact formatted as a vCard when opened through 1833 * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. 1834 */ 1835 public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, 1836 "as_vcard"); 1837 1838 /** 1839 * {@link Uri} for referencing the raw contacts that make up the user's profile 1840 * {@link Contacts} entry. An individual raw contact entry within the profile 1841 * can be addressed by appending the raw contact ID. The entities or data within 1842 * that specific raw contact can be requested by appending the entity or data 1843 * path as well. 1844 */ 1845 public static final Uri CONTENT_RAW_CONTACTS_URI = Uri.withAppendedPath(CONTENT_URI, 1846 "raw_contacts"); 1847 } 1848 1849 protected interface RawContactsColumns { 1850 /** 1851 * A reference to the {@link ContactsContract.Contacts#_ID} that this 1852 * data belongs to. 1853 * <P>Type: INTEGER</P> 1854 */ 1855 public static final String CONTACT_ID = "contact_id"; 1856 1857 /** 1858 * Flag indicating that this {@link RawContacts} entry and its children have 1859 * been restricted to specific platform apps. 1860 * <P>Type: INTEGER (boolean)</P> 1861 * 1862 * @hide until finalized in future platform release 1863 */ 1864 public static final String IS_RESTRICTED = "is_restricted"; 1865 1866 /** 1867 * The aggregation mode for this contact. 1868 * <P>Type: INTEGER</P> 1869 */ 1870 public static final String AGGREGATION_MODE = "aggregation_mode"; 1871 1872 /** 1873 * The "deleted" flag: "0" by default, "1" if the row has been marked 1874 * for deletion. When {@link android.content.ContentResolver#delete} is 1875 * called on a raw contact, it is marked for deletion and removed from its 1876 * aggregate contact. The sync adaptor deletes the raw contact on the server and 1877 * then calls ContactResolver.delete once more, this time passing the 1878 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 1879 * the data removal. 1880 * <P>Type: INTEGER</P> 1881 */ 1882 public static final String DELETED = "deleted"; 1883 1884 /** 1885 * The "name_verified" flag: "1" means that the name fields on this raw 1886 * contact can be trusted and therefore should be used for the entire 1887 * aggregated contact. 1888 * <p> 1889 * If an aggregated contact contains more than one raw contact with a 1890 * verified name, one of those verified names is chosen at random. 1891 * If an aggregated contact contains no verified names, the 1892 * name is chosen randomly from the constituent raw contacts. 1893 * </p> 1894 * <p> 1895 * Updating this flag from "0" to "1" automatically resets it to "0" on 1896 * all other raw contacts in the same aggregated contact. 1897 * </p> 1898 * <p> 1899 * Sync adapters should only specify a value for this column when 1900 * inserting a raw contact and leave it out when doing an update. 1901 * </p> 1902 * <p> 1903 * The default value is "0" 1904 * </p> 1905 * <p>Type: INTEGER</p> 1906 * 1907 * @hide 1908 */ 1909 public static final String NAME_VERIFIED = "name_verified"; 1910 1911 /** 1912 * The "read-only" flag: "0" by default, "1" if the row cannot be modified or 1913 * deleted except by a sync adapter. See {@link ContactsContract#CALLER_IS_SYNCADAPTER}. 1914 * <P>Type: INTEGER</P> 1915 */ 1916 public static final String RAW_CONTACT_IS_READ_ONLY = "raw_contact_is_read_only"; 1917 1918 /** 1919 * Flag that reflects whether this raw contact belongs to the user's 1920 * personal profile entry. 1921 */ 1922 public static final String RAW_CONTACT_IS_USER_PROFILE = "raw_contact_is_user_profile"; 1923 } 1924 1925 /** 1926 * Constants for the raw contacts table, which contains one row of contact 1927 * information for each person in each synced account. Sync adapters and 1928 * contact management apps 1929 * are the primary consumers of this API. 1930 * 1931 * <h3>Aggregation</h3> 1932 * <p> 1933 * As soon as a raw contact is inserted or whenever its constituent data 1934 * changes, the provider will check if the raw contact matches other 1935 * existing raw contacts and if so will aggregate it with those. The 1936 * aggregation is reflected in the {@link RawContacts} table by the change of the 1937 * {@link #CONTACT_ID} field, which is the reference to the aggregate contact. 1938 * </p> 1939 * <p> 1940 * Changes to the structured name, organization, phone number, email address, 1941 * or nickname trigger a re-aggregation. 1942 * </p> 1943 * <p> 1944 * See also {@link AggregationExceptions} for a mechanism to control 1945 * aggregation programmatically. 1946 * </p> 1947 * 1948 * <h3>Operations</h3> 1949 * <dl> 1950 * <dt><b>Insert</b></dt> 1951 * <dd> 1952 * <p> 1953 * Raw contacts can be inserted incrementally or in a batch. 1954 * The incremental method is more traditional but less efficient. 1955 * It should be used 1956 * only if no {@link Data} values are available at the time the raw contact is created: 1957 * <pre> 1958 * ContentValues values = new ContentValues(); 1959 * values.put(RawContacts.ACCOUNT_TYPE, accountType); 1960 * values.put(RawContacts.ACCOUNT_NAME, accountName); 1961 * Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values); 1962 * long rawContactId = ContentUris.parseId(rawContactUri); 1963 * </pre> 1964 * </p> 1965 * <p> 1966 * Once {@link Data} values become available, insert those. 1967 * For example, here's how you would insert a name: 1968 * 1969 * <pre> 1970 * values.clear(); 1971 * values.put(Data.RAW_CONTACT_ID, rawContactId); 1972 * values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 1973 * values.put(StructuredName.DISPLAY_NAME, "Mike Sullivan"); 1974 * getContentResolver().insert(Data.CONTENT_URI, values); 1975 * </pre> 1976 * </p> 1977 * <p> 1978 * The batch method is by far preferred. It inserts the raw contact and its 1979 * constituent data rows in a single database transaction 1980 * and causes at most one aggregation pass. 1981 * <pre> 1982 * ArrayList<ContentProviderOperation> ops = 1983 * new ArrayList<ContentProviderOperation>(); 1984 * ... 1985 * int rawContactInsertIndex = ops.size(); 1986 * ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI) 1987 * .withValue(RawContacts.ACCOUNT_TYPE, accountType) 1988 * .withValue(RawContacts.ACCOUNT_NAME, accountName) 1989 * .build()); 1990 * 1991 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 1992 * .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex) 1993 * .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 1994 * .withValue(StructuredName.DISPLAY_NAME, "Mike Sullivan") 1995 * .build()); 1996 * 1997 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 1998 * </pre> 1999 * </p> 2000 * <p> 2001 * Note the use of {@link ContentProviderOperation.Builder#withValueBackReference(String, int)} 2002 * to refer to the as-yet-unknown index value of the raw contact inserted in the 2003 * first operation. 2004 * </p> 2005 * 2006 * <dt><b>Update</b></dt> 2007 * <dd><p> 2008 * Raw contacts can be updated incrementally or in a batch. 2009 * Batch mode should be used whenever possible. 2010 * The procedures and considerations are analogous to those documented above for inserts. 2011 * </p></dd> 2012 * <dt><b>Delete</b></dt> 2013 * <dd><p>When a raw contact is deleted, all of its Data rows as well as StatusUpdates, 2014 * AggregationExceptions, PhoneLookup rows are deleted automatically. When all raw 2015 * contacts associated with a {@link Contacts} row are deleted, the {@link Contacts} row 2016 * itself is also deleted automatically. 2017 * </p> 2018 * <p> 2019 * The invocation of {@code resolver.delete(...)}, does not immediately delete 2020 * a raw contacts row. 2021 * Instead, it sets the {@link #DELETED} flag on the raw contact and 2022 * removes the raw contact from its aggregate contact. 2023 * The sync adapter then deletes the raw contact from the server and 2024 * finalizes phone-side deletion by calling {@code resolver.delete(...)} 2025 * again and passing the {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter.<p> 2026 * <p>Some sync adapters are read-only, meaning that they only sync server-side 2027 * changes to the phone, but not the reverse. If one of those raw contacts 2028 * is marked for deletion, it will remain on the phone. However it will be 2029 * effectively invisible, because it will not be part of any aggregate contact. 2030 * </dd> 2031 * 2032 * <dt><b>Query</b></dt> 2033 * <dd> 2034 * <p> 2035 * It is easy to find all raw contacts in a Contact: 2036 * <pre> 2037 * Cursor c = getContentResolver().query(RawContacts.CONTENT_URI, 2038 * new String[]{RawContacts._ID}, 2039 * RawContacts.CONTACT_ID + "=?", 2040 * new String[]{String.valueOf(contactId)}, null); 2041 * </pre> 2042 * </p> 2043 * <p> 2044 * To find raw contacts within a specific account, 2045 * you can either put the account name and type in the selection or pass them as query 2046 * parameters. The latter approach is preferable, especially when you can reuse the 2047 * URI: 2048 * <pre> 2049 * Uri rawContactUri = RawContacts.URI.buildUpon() 2050 * .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName) 2051 * .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType) 2052 * .build(); 2053 * Cursor c1 = getContentResolver().query(rawContactUri, 2054 * RawContacts.STARRED + "<>0", null, null, null); 2055 * ... 2056 * Cursor c2 = getContentResolver().query(rawContactUri, 2057 * RawContacts.DELETED + "<>0", null, null, null); 2058 * </pre> 2059 * </p> 2060 * <p>The best way to read a raw contact along with all the data associated with it is 2061 * by using the {@link Entity} directory. If the raw contact has data rows, 2062 * the Entity cursor will contain a row for each data row. If the raw contact has no 2063 * data rows, the cursor will still contain one row with the raw contact-level information. 2064 * <pre> 2065 * Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 2066 * Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY); 2067 * Cursor c = getContentResolver().query(entityUri, 2068 * new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1}, 2069 * null, null, null); 2070 * try { 2071 * while (c.moveToNext()) { 2072 * String sourceId = c.getString(0); 2073 * if (!c.isNull(1)) { 2074 * String mimeType = c.getString(2); 2075 * String data = c.getString(3); 2076 * ... 2077 * } 2078 * } 2079 * } finally { 2080 * c.close(); 2081 * } 2082 * </pre> 2083 * </p> 2084 * </dd> 2085 * </dl> 2086 * <h2>Columns</h2> 2087 * 2088 * <table class="jd-sumtable"> 2089 * <tr> 2090 * <th colspan='4'>RawContacts</th> 2091 * </tr> 2092 * <tr> 2093 * <td>long</td> 2094 * <td>{@link #_ID}</td> 2095 * <td>read-only</td> 2096 * <td>Row ID. Sync adapters should try to preserve row IDs during updates. In other words, 2097 * it is much better for a sync adapter to update a raw contact rather than to delete and 2098 * re-insert it.</td> 2099 * </tr> 2100 * <tr> 2101 * <td>long</td> 2102 * <td>{@link #CONTACT_ID}</td> 2103 * <td>read-only</td> 2104 * <td>The ID of the row in the {@link ContactsContract.Contacts} table 2105 * that this raw contact belongs 2106 * to. Raw contacts are linked to contacts by the aggregation process, which can be controlled 2107 * by the {@link #AGGREGATION_MODE} field and {@link AggregationExceptions}.</td> 2108 * </tr> 2109 * <tr> 2110 * <td>int</td> 2111 * <td>{@link #AGGREGATION_MODE}</td> 2112 * <td>read/write</td> 2113 * <td>A mechanism that allows programmatic control of the aggregation process. The allowed 2114 * values are {@link #AGGREGATION_MODE_DEFAULT}, {@link #AGGREGATION_MODE_DISABLED} 2115 * and {@link #AGGREGATION_MODE_SUSPENDED}. See also {@link AggregationExceptions}.</td> 2116 * </tr> 2117 * <tr> 2118 * <td>int</td> 2119 * <td>{@link #DELETED}</td> 2120 * <td>read/write</td> 2121 * <td>The "deleted" flag: "0" by default, "1" if the row has been marked 2122 * for deletion. When {@link android.content.ContentResolver#delete} is 2123 * called on a raw contact, it is marked for deletion and removed from its 2124 * aggregate contact. The sync adaptor deletes the raw contact on the server and 2125 * then calls ContactResolver.delete once more, this time passing the 2126 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 2127 * the data removal.</td> 2128 * </tr> 2129 * <tr> 2130 * <td>int</td> 2131 * <td>{@link #TIMES_CONTACTED}</td> 2132 * <td>read/write</td> 2133 * <td>The number of times the contact has been contacted. To have an effect 2134 * on the corresponding value of the aggregate contact, this field 2135 * should be set at the time the raw contact is inserted. 2136 * After that, this value is typically updated via 2137 * {@link ContactsContract.Contacts#markAsContacted}.</td> 2138 * </tr> 2139 * <tr> 2140 * <td>long</td> 2141 * <td>{@link #LAST_TIME_CONTACTED}</td> 2142 * <td>read/write</td> 2143 * <td>The timestamp of the last time the contact was contacted. To have an effect 2144 * on the corresponding value of the aggregate contact, this field 2145 * should be set at the time the raw contact is inserted. 2146 * After that, this value is typically updated via 2147 * {@link ContactsContract.Contacts#markAsContacted}. 2148 * </td> 2149 * </tr> 2150 * <tr> 2151 * <td>int</td> 2152 * <td>{@link #STARRED}</td> 2153 * <td>read/write</td> 2154 * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise. 2155 * Changing this field immediately affects the corresponding aggregate contact: 2156 * if any raw contacts in that aggregate contact are starred, then the contact 2157 * itself is marked as starred.</td> 2158 * </tr> 2159 * <tr> 2160 * <td>String</td> 2161 * <td>{@link #CUSTOM_RINGTONE}</td> 2162 * <td>read/write</td> 2163 * <td>A custom ringtone associated with a raw contact. Typically this is the 2164 * URI returned by an activity launched with the 2165 * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent. 2166 * To have an effect on the corresponding value of the aggregate contact, this field 2167 * should be set at the time the raw contact is inserted. To set a custom 2168 * ringtone on a contact, use the field {@link ContactsContract.Contacts#CUSTOM_RINGTONE 2169 * Contacts.CUSTOM_RINGTONE} 2170 * instead.</td> 2171 * </tr> 2172 * <tr> 2173 * <td>int</td> 2174 * <td>{@link #SEND_TO_VOICEMAIL}</td> 2175 * <td>read/write</td> 2176 * <td>An indicator of whether calls from this raw contact should be forwarded 2177 * directly to voice mail ('1') or not ('0'). To have an effect 2178 * on the corresponding value of the aggregate contact, this field 2179 * should be set at the time the raw contact is inserted.</td> 2180 * </tr> 2181 * <tr> 2182 * <td>String</td> 2183 * <td>{@link #ACCOUNT_NAME}</td> 2184 * <td>read/write-once</td> 2185 * <td>The name of the account instance to which this row belongs, which when paired with 2186 * {@link #ACCOUNT_TYPE} identifies a specific account. 2187 * For example, this will be the Gmail address if it is a Google account. 2188 * It should be set at the time 2189 * the raw contact is inserted and never changed afterwards.</td> 2190 * </tr> 2191 * <tr> 2192 * <td>String</td> 2193 * <td>{@link #ACCOUNT_TYPE}</td> 2194 * <td>read/write-once</td> 2195 * <td> 2196 * <p> 2197 * The type of account to which this row belongs, which when paired with 2198 * {@link #ACCOUNT_NAME} identifies a specific account. 2199 * It should be set at the time 2200 * the raw contact is inserted and never changed afterwards. 2201 * </p> 2202 * <p> 2203 * To ensure uniqueness, new account types should be chosen according to the 2204 * Java package naming convention. Thus a Google account is of type "com.google". 2205 * </p> 2206 * </td> 2207 * </tr> 2208 * <tr> 2209 * <td>String</td> 2210 * <td>{@link #SOURCE_ID}</td> 2211 * <td>read/write</td> 2212 * <td>String that uniquely identifies this row to its source account. 2213 * Typically it is set at the time the raw contact is inserted and never 2214 * changed afterwards. The one notable exception is a new raw contact: it 2215 * will have an account name and type, but no source id. This 2216 * indicates to the sync adapter that a new contact needs to be created 2217 * server-side and its ID stored in the corresponding SOURCE_ID field on 2218 * the phone. 2219 * </td> 2220 * </tr> 2221 * <tr> 2222 * <td>int</td> 2223 * <td>{@link #VERSION}</td> 2224 * <td>read-only</td> 2225 * <td>Version number that is updated whenever this row or its related data 2226 * changes. This field can be used for optimistic locking of a raw contact. 2227 * </td> 2228 * </tr> 2229 * <tr> 2230 * <td>int</td> 2231 * <td>{@link #DIRTY}</td> 2232 * <td>read/write</td> 2233 * <td>Flag indicating that {@link #VERSION} has changed, and this row needs 2234 * to be synchronized by its owning account. The value is set to "1" automatically 2235 * whenever the raw contact changes, unless the URI has the 2236 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter specified. 2237 * The sync adapter should always supply this query parameter to prevent 2238 * unnecessary synchronization: user changes some data on the server, 2239 * the sync adapter updates the contact on the phone (without the 2240 * CALLER_IS_SYNCADAPTER flag) flag, which sets the DIRTY flag, 2241 * which triggers a sync to bring the changes to the server. 2242 * </td> 2243 * </tr> 2244 * <tr> 2245 * <td>String</td> 2246 * <td>{@link #SYNC1}</td> 2247 * <td>read/write</td> 2248 * <td>Generic column provided for arbitrary use by sync adapters. 2249 * The content provider 2250 * stores this information on behalf of the sync adapter but does not 2251 * interpret it in any way. 2252 * </td> 2253 * </tr> 2254 * <tr> 2255 * <td>String</td> 2256 * <td>{@link #SYNC2}</td> 2257 * <td>read/write</td> 2258 * <td>Generic column for use by sync adapters. 2259 * </td> 2260 * </tr> 2261 * <tr> 2262 * <td>String</td> 2263 * <td>{@link #SYNC3}</td> 2264 * <td>read/write</td> 2265 * <td>Generic column for use by sync adapters. 2266 * </td> 2267 * </tr> 2268 * <tr> 2269 * <td>String</td> 2270 * <td>{@link #SYNC4}</td> 2271 * <td>read/write</td> 2272 * <td>Generic column for use by sync adapters. 2273 * </td> 2274 * </tr> 2275 * </table> 2276 */ 2277 public static final class RawContacts implements BaseColumns, RawContactsColumns, 2278 ContactOptionsColumns, ContactNameColumns, SyncColumns { 2279 /** 2280 * This utility class cannot be instantiated 2281 */ 2282 private RawContacts() { 2283 } 2284 2285 /** 2286 * The content:// style URI for this table, which requests a directory of 2287 * raw contact rows matching the selection criteria. 2288 */ 2289 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts"); 2290 2291 /** 2292 * The MIME type of the results from {@link #CONTENT_URI} when a specific 2293 * ID value is not provided, and multiple raw contacts may be returned. 2294 */ 2295 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact"; 2296 2297 /** 2298 * The MIME type of the results when a raw contact ID is appended to {@link #CONTENT_URI}, 2299 * yielding a subdirectory of a single person. 2300 */ 2301 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact"; 2302 2303 /** 2304 * Aggregation mode: aggregate immediately after insert or update operation(s) are complete. 2305 */ 2306 public static final int AGGREGATION_MODE_DEFAULT = 0; 2307 2308 /** 2309 * Aggregation mode: aggregate at the time the raw contact is inserted/updated. 2310 * @deprecated Aggregation is synchronous, this historic value is a no-op 2311 */ 2312 @Deprecated 2313 public static final int AGGREGATION_MODE_IMMEDIATE = 1; 2314 2315 /** 2316 * <p> 2317 * Aggregation mode: aggregation suspended temporarily, and is likely to be resumed later. 2318 * Changes to the raw contact will update the associated aggregate contact but will not 2319 * result in any change in how the contact is aggregated. Similar to 2320 * {@link #AGGREGATION_MODE_DISABLED}, but maintains a link to the corresponding 2321 * {@link Contacts} aggregate. 2322 * </p> 2323 * <p> 2324 * This can be used to postpone aggregation until after a series of updates, for better 2325 * performance and/or user experience. 2326 * </p> 2327 * <p> 2328 * Note that changing 2329 * {@link #AGGREGATION_MODE} from {@link #AGGREGATION_MODE_SUSPENDED} to 2330 * {@link #AGGREGATION_MODE_DEFAULT} does not trigger an aggregation pass, but any 2331 * subsequent 2332 * change to the raw contact's data will. 2333 * </p> 2334 */ 2335 public static final int AGGREGATION_MODE_SUSPENDED = 2; 2336 2337 /** 2338 * <p> 2339 * Aggregation mode: never aggregate this raw contact. The raw contact will not 2340 * have a corresponding {@link Contacts} aggregate and therefore will not be included in 2341 * {@link Contacts} query results. 2342 * </p> 2343 * <p> 2344 * For example, this mode can be used for a raw contact that is marked for deletion while 2345 * waiting for the deletion to occur on the server side. 2346 * </p> 2347 * 2348 * @see #AGGREGATION_MODE_SUSPENDED 2349 */ 2350 public static final int AGGREGATION_MODE_DISABLED = 3; 2351 2352 /** 2353 * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 2354 * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} 2355 * entry of the given {@link RawContacts} entry. 2356 */ 2357 public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) { 2358 // TODO: use a lighter query by joining rawcontacts with contacts in provider 2359 final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY); 2360 final Cursor cursor = resolver.query(dataUri, new String[] { 2361 RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY 2362 }, null, null, null); 2363 2364 Uri lookupUri = null; 2365 try { 2366 if (cursor != null && cursor.moveToFirst()) { 2367 final long contactId = cursor.getLong(0); 2368 final String lookupKey = cursor.getString(1); 2369 return Contacts.getLookupUri(contactId, lookupKey); 2370 } 2371 } finally { 2372 if (cursor != null) cursor.close(); 2373 } 2374 return lookupUri; 2375 } 2376 2377 /** 2378 * A sub-directory of a single raw contact that contains all of its 2379 * {@link ContactsContract.Data} rows. To access this directory 2380 * append {@link Data#CONTENT_DIRECTORY} to the raw contact URI. 2381 */ 2382 public static final class Data implements BaseColumns, DataColumns { 2383 /** 2384 * no public constructor since this is a utility class 2385 */ 2386 private Data() { 2387 } 2388 2389 /** 2390 * The directory twig for this sub-table 2391 */ 2392 public static final String CONTENT_DIRECTORY = "data"; 2393 } 2394 2395 /** 2396 * <p> 2397 * A sub-directory of a single raw contact that contains all of its 2398 * {@link ContactsContract.Data} rows. To access this directory append 2399 * {@link RawContacts.Entity#CONTENT_DIRECTORY} to the raw contact URI. See 2400 * {@link RawContactsEntity} for a stand-alone table containing the same 2401 * data. 2402 * </p> 2403 * <p> 2404 * Entity has two ID fields: {@link #_ID} for the raw contact 2405 * and {@link #DATA_ID} for the data rows. 2406 * Entity always contains at least one row, even if there are no 2407 * actual data rows. In this case the {@link #DATA_ID} field will be 2408 * null. 2409 * </p> 2410 * <p> 2411 * Using Entity should be preferred to using two separate queries: 2412 * RawContacts followed by Data. The reason is that Entity reads all 2413 * data for a raw contact in one transaction, so there is no possibility 2414 * of the data changing between the two queries. 2415 */ 2416 public static final class Entity implements BaseColumns, DataColumns { 2417 /** 2418 * no public constructor since this is a utility class 2419 */ 2420 private Entity() { 2421 } 2422 2423 /** 2424 * The directory twig for this sub-table 2425 */ 2426 public static final String CONTENT_DIRECTORY = "entity"; 2427 2428 /** 2429 * The ID of the data row. The value will be null if this raw contact has no 2430 * data rows. 2431 * <P>Type: INTEGER</P> 2432 */ 2433 public static final String DATA_ID = "data_id"; 2434 } 2435 2436 /** 2437 * TODO: javadoc 2438 * @param cursor 2439 * @return 2440 */ 2441 public static EntityIterator newEntityIterator(Cursor cursor) { 2442 return new EntityIteratorImpl(cursor); 2443 } 2444 2445 private static class EntityIteratorImpl extends CursorEntityIterator { 2446 private static final String[] DATA_KEYS = new String[]{ 2447 Data.DATA1, 2448 Data.DATA2, 2449 Data.DATA3, 2450 Data.DATA4, 2451 Data.DATA5, 2452 Data.DATA6, 2453 Data.DATA7, 2454 Data.DATA8, 2455 Data.DATA9, 2456 Data.DATA10, 2457 Data.DATA11, 2458 Data.DATA12, 2459 Data.DATA13, 2460 Data.DATA14, 2461 Data.DATA15, 2462 Data.SYNC1, 2463 Data.SYNC2, 2464 Data.SYNC3, 2465 Data.SYNC4}; 2466 2467 public EntityIteratorImpl(Cursor cursor) { 2468 super(cursor); 2469 } 2470 2471 @Override 2472 public android.content.Entity getEntityAndIncrementCursor(Cursor cursor) 2473 throws RemoteException { 2474 final int columnRawContactId = cursor.getColumnIndexOrThrow(RawContacts._ID); 2475 final long rawContactId = cursor.getLong(columnRawContactId); 2476 2477 // we expect the cursor is already at the row we need to read from 2478 ContentValues cv = new ContentValues(); 2479 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_NAME); 2480 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_TYPE); 2481 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, _ID); 2482 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DIRTY); 2483 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, VERSION); 2484 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SOURCE_ID); 2485 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC1); 2486 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC2); 2487 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC3); 2488 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC4); 2489 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DELETED); 2490 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID); 2491 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED); 2492 DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, IS_RESTRICTED); 2493 DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, NAME_VERIFIED); 2494 android.content.Entity contact = new android.content.Entity(cv); 2495 2496 // read data rows until the contact id changes 2497 do { 2498 if (rawContactId != cursor.getLong(columnRawContactId)) { 2499 break; 2500 } 2501 // add the data to to the contact 2502 cv = new ContentValues(); 2503 cv.put(Data._ID, cursor.getLong(cursor.getColumnIndexOrThrow(Entity.DATA_ID))); 2504 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 2505 Data.RES_PACKAGE); 2506 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Data.MIMETYPE); 2507 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.IS_PRIMARY); 2508 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, 2509 Data.IS_SUPER_PRIMARY); 2510 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.DATA_VERSION); 2511 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 2512 CommonDataKinds.GroupMembership.GROUP_SOURCE_ID); 2513 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 2514 Data.DATA_VERSION); 2515 for (String key : DATA_KEYS) { 2516 final int columnIndex = cursor.getColumnIndexOrThrow(key); 2517 switch (cursor.getType(columnIndex)) { 2518 case Cursor.FIELD_TYPE_NULL: 2519 // don't put anything 2520 break; 2521 case Cursor.FIELD_TYPE_INTEGER: 2522 case Cursor.FIELD_TYPE_FLOAT: 2523 case Cursor.FIELD_TYPE_STRING: 2524 cv.put(key, cursor.getString(columnIndex)); 2525 break; 2526 case Cursor.FIELD_TYPE_BLOB: 2527 cv.put(key, cursor.getBlob(columnIndex)); 2528 break; 2529 default: 2530 throw new IllegalStateException("Invalid or unhandled data type"); 2531 } 2532 } 2533 contact.addSubValue(ContactsContract.Data.CONTENT_URI, cv); 2534 } while (cursor.moveToNext()); 2535 2536 return contact; 2537 } 2538 2539 } 2540 } 2541 2542 /** 2543 * Social status update columns. 2544 * 2545 * @see StatusUpdates 2546 * @see ContactsContract.Data 2547 */ 2548 protected interface StatusColumns { 2549 /** 2550 * Contact's latest presence level. 2551 * <P>Type: INTEGER (one of the values below)</P> 2552 */ 2553 public static final String PRESENCE = "mode"; 2554 2555 /** 2556 * @deprecated use {@link #PRESENCE} 2557 */ 2558 @Deprecated 2559 public static final String PRESENCE_STATUS = PRESENCE; 2560 2561 /** 2562 * An allowed value of {@link #PRESENCE}. 2563 */ 2564 int OFFLINE = 0; 2565 2566 /** 2567 * An allowed value of {@link #PRESENCE}. 2568 */ 2569 int INVISIBLE = 1; 2570 2571 /** 2572 * An allowed value of {@link #PRESENCE}. 2573 */ 2574 int AWAY = 2; 2575 2576 /** 2577 * An allowed value of {@link #PRESENCE}. 2578 */ 2579 int IDLE = 3; 2580 2581 /** 2582 * An allowed value of {@link #PRESENCE}. 2583 */ 2584 int DO_NOT_DISTURB = 4; 2585 2586 /** 2587 * An allowed value of {@link #PRESENCE}. 2588 */ 2589 int AVAILABLE = 5; 2590 2591 /** 2592 * Contact latest status update. 2593 * <p>Type: TEXT</p> 2594 */ 2595 public static final String STATUS = "status"; 2596 2597 /** 2598 * @deprecated use {@link #STATUS} 2599 */ 2600 @Deprecated 2601 public static final String PRESENCE_CUSTOM_STATUS = STATUS; 2602 2603 /** 2604 * The absolute time in milliseconds when the latest status was inserted/updated. 2605 * <p>Type: NUMBER</p> 2606 */ 2607 public static final String STATUS_TIMESTAMP = "status_ts"; 2608 2609 /** 2610 * The package containing resources for this status: label and icon. 2611 * <p>Type: NUMBER</p> 2612 */ 2613 public static final String STATUS_RES_PACKAGE = "status_res_package"; 2614 2615 /** 2616 * The resource ID of the label describing the source of the status update, e.g. "Google 2617 * Talk". This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. 2618 * <p>Type: NUMBER</p> 2619 */ 2620 public static final String STATUS_LABEL = "status_label"; 2621 2622 /** 2623 * The resource ID of the icon for the source of the status update. 2624 * This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. 2625 * <p>Type: NUMBER</p> 2626 */ 2627 public static final String STATUS_ICON = "status_icon"; 2628 2629 /** 2630 * Contact's audio/video chat capability level. 2631 * <P>Type: INTEGER (one of the values below)</P> 2632 */ 2633 public static final String CHAT_CAPABILITY = "chat_capability"; 2634 2635 /** 2636 * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates audio-chat capability (microphone 2637 * and speaker) 2638 */ 2639 public static final int CAPABILITY_HAS_VOICE = 1; 2640 2641 /** 2642 * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates that the contact's device can 2643 * display a video feed. 2644 */ 2645 public static final int CAPABILITY_HAS_VIDEO = 2; 2646 2647 /** 2648 * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates that the contact's device has a 2649 * camera that can be used for video chat (e.g. a front-facing camera on a phone). 2650 */ 2651 public static final int CAPABILITY_HAS_CAMERA = 4; 2652 } 2653 2654 /** 2655 * Columns in the Data table. 2656 * 2657 * @see ContactsContract.Data 2658 */ 2659 protected interface DataColumns { 2660 /** 2661 * The package name to use when creating {@link Resources} objects for 2662 * this data row. This value is only designed for use when building user 2663 * interfaces, and should not be used to infer the owner. 2664 * 2665 * @hide 2666 */ 2667 public static final String RES_PACKAGE = "res_package"; 2668 2669 /** 2670 * The MIME type of the item represented by this row. 2671 */ 2672 public static final String MIMETYPE = "mimetype"; 2673 2674 /** 2675 * A reference to the {@link RawContacts#_ID} 2676 * that this data belongs to. 2677 */ 2678 public static final String RAW_CONTACT_ID = "raw_contact_id"; 2679 2680 /** 2681 * Whether this is the primary entry of its kind for the raw contact it belongs to. 2682 * <P>Type: INTEGER (if set, non-0 means true)</P> 2683 */ 2684 public static final String IS_PRIMARY = "is_primary"; 2685 2686 /** 2687 * Whether this is the primary entry of its kind for the aggregate 2688 * contact it belongs to. Any data record that is "super primary" must 2689 * also be "primary". 2690 * <P>Type: INTEGER (if set, non-0 means true)</P> 2691 */ 2692 public static final String IS_SUPER_PRIMARY = "is_super_primary"; 2693 2694 /** 2695 * The "read-only" flag: "0" by default, "1" if the row cannot be modified or 2696 * deleted except by a sync adapter. See {@link ContactsContract#CALLER_IS_SYNCADAPTER}. 2697 * <P>Type: INTEGER</P> 2698 */ 2699 public static final String IS_READ_ONLY = "is_read_only"; 2700 2701 /** 2702 * The version of this data record. This is a read-only value. The data column is 2703 * guaranteed to not change without the version going up. This value is monotonically 2704 * increasing. 2705 * <P>Type: INTEGER</P> 2706 */ 2707 public static final String DATA_VERSION = "data_version"; 2708 2709 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2710 public static final String DATA1 = "data1"; 2711 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2712 public static final String DATA2 = "data2"; 2713 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2714 public static final String DATA3 = "data3"; 2715 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2716 public static final String DATA4 = "data4"; 2717 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2718 public static final String DATA5 = "data5"; 2719 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2720 public static final String DATA6 = "data6"; 2721 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2722 public static final String DATA7 = "data7"; 2723 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2724 public static final String DATA8 = "data8"; 2725 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2726 public static final String DATA9 = "data9"; 2727 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2728 public static final String DATA10 = "data10"; 2729 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2730 public static final String DATA11 = "data11"; 2731 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2732 public static final String DATA12 = "data12"; 2733 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2734 public static final String DATA13 = "data13"; 2735 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 2736 public static final String DATA14 = "data14"; 2737 /** 2738 * Generic data column, the meaning is {@link #MIMETYPE} specific. By convention, 2739 * this field is used to store BLOBs (binary data). 2740 */ 2741 public static final String DATA15 = "data15"; 2742 2743 /** Generic column for use by sync adapters. */ 2744 public static final String SYNC1 = "data_sync1"; 2745 /** Generic column for use by sync adapters. */ 2746 public static final String SYNC2 = "data_sync2"; 2747 /** Generic column for use by sync adapters. */ 2748 public static final String SYNC3 = "data_sync3"; 2749 /** Generic column for use by sync adapters. */ 2750 public static final String SYNC4 = "data_sync4"; 2751 } 2752 2753 /** 2754 * Combines all columns returned by {@link ContactsContract.Data} table queries. 2755 * 2756 * @see ContactsContract.Data 2757 */ 2758 protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns, 2759 RawContactsColumns, ContactsColumns, ContactNameColumns, ContactOptionsColumns, 2760 ContactStatusColumns { 2761 } 2762 2763 /** 2764 * <p> 2765 * Constants for the data table, which contains data points tied to a raw 2766 * contact. Each row of the data table is typically used to store a single 2767 * piece of contact 2768 * information (such as a phone number) and its 2769 * associated metadata (such as whether it is a work or home number). 2770 * </p> 2771 * <h3>Data kinds</h3> 2772 * <p> 2773 * Data is a generic table that can hold any kind of contact data. 2774 * The kind of data stored in a given row is specified by the row's 2775 * {@link #MIMETYPE} value, which determines the meaning of the 2776 * generic columns {@link #DATA1} through 2777 * {@link #DATA15}. 2778 * For example, if the data kind is 2779 * {@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}, then the column 2780 * {@link #DATA1} stores the 2781 * phone number, but if the data kind is 2782 * {@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}, then {@link #DATA1} 2783 * stores the email address. 2784 * Sync adapters and applications can introduce their own data kinds. 2785 * </p> 2786 * <p> 2787 * ContactsContract defines a small number of pre-defined data kinds, e.g. 2788 * {@link CommonDataKinds.Phone}, {@link CommonDataKinds.Email} etc. As a 2789 * convenience, these classes define data kind specific aliases for DATA1 etc. 2790 * For example, {@link CommonDataKinds.Phone Phone.NUMBER} is the same as 2791 * {@link ContactsContract.Data Data.DATA1}. 2792 * </p> 2793 * <p> 2794 * {@link #DATA1} is an indexed column and should be used for the data element that is 2795 * expected to be most frequently used in query selections. For example, in the 2796 * case of a row representing email addresses {@link #DATA1} should probably 2797 * be used for the email address itself, while {@link #DATA2} etc can be 2798 * used for auxiliary information like type of email address. 2799 * <p> 2800 * <p> 2801 * By convention, {@link #DATA15} is used for storing BLOBs (binary data). 2802 * </p> 2803 * <p> 2804 * The sync adapter for a given account type must correctly handle every data type 2805 * used in the corresponding raw contacts. Otherwise it could result in lost or 2806 * corrupted data. 2807 * </p> 2808 * <p> 2809 * Similarly, you should refrain from introducing new kinds of data for an other 2810 * party's account types. For example, if you add a data row for 2811 * "favorite song" to a raw contact owned by a Google account, it will not 2812 * get synced to the server, because the Google sync adapter does not know 2813 * how to handle this data kind. Thus new data kinds are typically 2814 * introduced along with new account types, i.e. new sync adapters. 2815 * </p> 2816 * <h3>Batch operations</h3> 2817 * <p> 2818 * Data rows can be inserted/updated/deleted using the traditional 2819 * {@link ContentResolver#insert}, {@link ContentResolver#update} and 2820 * {@link ContentResolver#delete} methods, however the newer mechanism based 2821 * on a batch of {@link ContentProviderOperation} will prove to be a better 2822 * choice in almost all cases. All operations in a batch are executed in a 2823 * single transaction, which ensures that the phone-side and server-side 2824 * state of a raw contact are always consistent. Also, the batch-based 2825 * approach is far more efficient: not only are the database operations 2826 * faster when executed in a single transaction, but also sending a batch of 2827 * commands to the content provider saves a lot of time on context switching 2828 * between your process and the process in which the content provider runs. 2829 * </p> 2830 * <p> 2831 * The flip side of using batched operations is that a large batch may lock 2832 * up the database for a long time preventing other applications from 2833 * accessing data and potentially causing ANRs ("Application Not Responding" 2834 * dialogs.) 2835 * </p> 2836 * <p> 2837 * To avoid such lockups of the database, make sure to insert "yield points" 2838 * in the batch. A yield point indicates to the content provider that before 2839 * executing the next operation it can commit the changes that have already 2840 * been made, yield to other requests, open another transaction and continue 2841 * processing operations. A yield point will not automatically commit the 2842 * transaction, but only if there is another request waiting on the 2843 * database. Normally a sync adapter should insert a yield point at the 2844 * beginning of each raw contact operation sequence in the batch. See 2845 * {@link ContentProviderOperation.Builder#withYieldAllowed(boolean)}. 2846 * </p> 2847 * <h3>Operations</h3> 2848 * <dl> 2849 * <dt><b>Insert</b></dt> 2850 * <dd> 2851 * <p> 2852 * An individual data row can be inserted using the traditional 2853 * {@link ContentResolver#insert(Uri, ContentValues)} method. Multiple rows 2854 * should always be inserted as a batch. 2855 * </p> 2856 * <p> 2857 * An example of a traditional insert: 2858 * <pre> 2859 * ContentValues values = new ContentValues(); 2860 * values.put(Data.RAW_CONTACT_ID, rawContactId); 2861 * values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 2862 * values.put(Phone.NUMBER, "1-800-GOOG-411"); 2863 * values.put(Phone.TYPE, Phone.TYPE_CUSTOM); 2864 * values.put(Phone.LABEL, "free directory assistance"); 2865 * Uri dataUri = getContentResolver().insert(Data.CONTENT_URI, values); 2866 * </pre> 2867 * <p> 2868 * The same done using ContentProviderOperations: 2869 * <pre> 2870 * ArrayList<ContentProviderOperation> ops = 2871 * new ArrayList<ContentProviderOperation>(); 2872 * 2873 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 2874 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 2875 * .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE) 2876 * .withValue(Phone.NUMBER, "1-800-GOOG-411") 2877 * .withValue(Phone.TYPE, Phone.TYPE_CUSTOM) 2878 * .withValue(Phone.LABEL, "free directory assistance") 2879 * .build()); 2880 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 2881 * </pre> 2882 * </p> 2883 * <dt><b>Update</b></dt> 2884 * <dd> 2885 * <p> 2886 * Just as with insert, update can be done incrementally or as a batch, 2887 * the batch mode being the preferred method: 2888 * <pre> 2889 * ArrayList<ContentProviderOperation> ops = 2890 * new ArrayList<ContentProviderOperation>(); 2891 * 2892 * ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI) 2893 * .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}) 2894 * .withValue(Email.DATA, "somebody@android.com") 2895 * .build()); 2896 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 2897 * </pre> 2898 * </p> 2899 * </dd> 2900 * <dt><b>Delete</b></dt> 2901 * <dd> 2902 * <p> 2903 * Just as with insert and update, deletion can be done either using the 2904 * {@link ContentResolver#delete} method or using a ContentProviderOperation: 2905 * <pre> 2906 * ArrayList<ContentProviderOperation> ops = 2907 * new ArrayList<ContentProviderOperation>(); 2908 * 2909 * ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI) 2910 * .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}) 2911 * .build()); 2912 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 2913 * </pre> 2914 * </p> 2915 * </dd> 2916 * <dt><b>Query</b></dt> 2917 * <dd> 2918 * <p> 2919 * <dl> 2920 * <dt>Finding all Data of a given type for a given contact</dt> 2921 * <dd> 2922 * <pre> 2923 * Cursor c = getContentResolver().query(Data.CONTENT_URI, 2924 * new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL}, 2925 * Data.CONTACT_ID + "=?" + " AND " 2926 * + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", 2927 * new String[] {String.valueOf(contactId)}, null); 2928 * </pre> 2929 * </p> 2930 * <p> 2931 * </dd> 2932 * <dt>Finding all Data of a given type for a given raw contact</dt> 2933 * <dd> 2934 * <pre> 2935 * Cursor c = getContentResolver().query(Data.CONTENT_URI, 2936 * new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL}, 2937 * Data.RAW_CONTACT_ID + "=?" + " AND " 2938 * + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", 2939 * new String[] {String.valueOf(rawContactId)}, null); 2940 * </pre> 2941 * </dd> 2942 * <dt>Finding all Data for a given raw contact</dt> 2943 * <dd> 2944 * Most sync adapters will want to read all data rows for a raw contact 2945 * along with the raw contact itself. For that you should use the 2946 * {@link RawContactsEntity}. See also {@link RawContacts}. 2947 * </dd> 2948 * </dl> 2949 * </p> 2950 * </dd> 2951 * </dl> 2952 * <h2>Columns</h2> 2953 * <p> 2954 * Many columns are available via a {@link Data#CONTENT_URI} query. For best performance you 2955 * should explicitly specify a projection to only those columns that you need. 2956 * </p> 2957 * <table class="jd-sumtable"> 2958 * <tr> 2959 * <th colspan='4'>Data</th> 2960 * </tr> 2961 * <tr> 2962 * <td style="width: 7em;">long</td> 2963 * <td style="width: 20em;">{@link #_ID}</td> 2964 * <td style="width: 5em;">read-only</td> 2965 * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words, 2966 * it would be a bad idea to delete and reinsert a data row. A sync adapter should 2967 * always do an update instead.</td> 2968 * </tr> 2969 * <tr> 2970 * <td>String</td> 2971 * <td>{@link #MIMETYPE}</td> 2972 * <td>read/write-once</td> 2973 * <td> 2974 * <p>The MIME type of the item represented by this row. Examples of common 2975 * MIME types are: 2976 * <ul> 2977 * <li>{@link CommonDataKinds.StructuredName StructuredName.CONTENT_ITEM_TYPE}</li> 2978 * <li>{@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}</li> 2979 * <li>{@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}</li> 2980 * <li>{@link CommonDataKinds.Photo Photo.CONTENT_ITEM_TYPE}</li> 2981 * <li>{@link CommonDataKinds.Organization Organization.CONTENT_ITEM_TYPE}</li> 2982 * <li>{@link CommonDataKinds.Im Im.CONTENT_ITEM_TYPE}</li> 2983 * <li>{@link CommonDataKinds.Nickname Nickname.CONTENT_ITEM_TYPE}</li> 2984 * <li>{@link CommonDataKinds.Note Note.CONTENT_ITEM_TYPE}</li> 2985 * <li>{@link CommonDataKinds.StructuredPostal StructuredPostal.CONTENT_ITEM_TYPE}</li> 2986 * <li>{@link CommonDataKinds.GroupMembership GroupMembership.CONTENT_ITEM_TYPE}</li> 2987 * <li>{@link CommonDataKinds.Website Website.CONTENT_ITEM_TYPE}</li> 2988 * <li>{@link CommonDataKinds.Event Event.CONTENT_ITEM_TYPE}</li> 2989 * <li>{@link CommonDataKinds.Relation Relation.CONTENT_ITEM_TYPE}</li> 2990 * <li>{@link CommonDataKinds.SipAddress SipAddress.CONTENT_ITEM_TYPE}</li> 2991 * </ul> 2992 * </p> 2993 * </td> 2994 * </tr> 2995 * <tr> 2996 * <td>long</td> 2997 * <td>{@link #RAW_CONTACT_ID}</td> 2998 * <td>read/write-once</td> 2999 * <td>The id of the row in the {@link RawContacts} table that this data belongs to.</td> 3000 * </tr> 3001 * <tr> 3002 * <td>int</td> 3003 * <td>{@link #IS_PRIMARY}</td> 3004 * <td>read/write</td> 3005 * <td>Whether this is the primary entry of its kind for the raw contact it belongs to. 3006 * "1" if true, "0" if false. 3007 * </td> 3008 * </tr> 3009 * <tr> 3010 * <td>int</td> 3011 * <td>{@link #IS_SUPER_PRIMARY}</td> 3012 * <td>read/write</td> 3013 * <td>Whether this is the primary entry of its kind for the aggregate 3014 * contact it belongs to. Any data record that is "super primary" must 3015 * also be "primary". For example, the super-primary entry may be 3016 * interpreted as the default contact value of its kind (for example, 3017 * the default phone number to use for the contact).</td> 3018 * </tr> 3019 * <tr> 3020 * <td>int</td> 3021 * <td>{@link #DATA_VERSION}</td> 3022 * <td>read-only</td> 3023 * <td>The version of this data record. Whenever the data row changes 3024 * the version goes up. This value is monotonically increasing.</td> 3025 * </tr> 3026 * <tr> 3027 * <td>Any type</td> 3028 * <td> 3029 * {@link #DATA1}<br> 3030 * {@link #DATA2}<br> 3031 * {@link #DATA3}<br> 3032 * {@link #DATA4}<br> 3033 * {@link #DATA5}<br> 3034 * {@link #DATA6}<br> 3035 * {@link #DATA7}<br> 3036 * {@link #DATA8}<br> 3037 * {@link #DATA9}<br> 3038 * {@link #DATA10}<br> 3039 * {@link #DATA11}<br> 3040 * {@link #DATA12}<br> 3041 * {@link #DATA13}<br> 3042 * {@link #DATA14}<br> 3043 * {@link #DATA15} 3044 * </td> 3045 * <td>read/write</td> 3046 * <td> 3047 * <p> 3048 * Generic data columns. The meaning of each column is determined by the 3049 * {@link #MIMETYPE}. By convention, {@link #DATA15} is used for storing 3050 * BLOBs (binary data). 3051 * </p> 3052 * <p> 3053 * Data columns whose meaning is not explicitly defined for a given MIMETYPE 3054 * should not be used. There is no guarantee that any sync adapter will 3055 * preserve them. Sync adapters themselves should not use such columns either, 3056 * but should instead use {@link #SYNC1}-{@link #SYNC4}. 3057 * </p> 3058 * </td> 3059 * </tr> 3060 * <tr> 3061 * <td>Any type</td> 3062 * <td> 3063 * {@link #SYNC1}<br> 3064 * {@link #SYNC2}<br> 3065 * {@link #SYNC3}<br> 3066 * {@link #SYNC4} 3067 * </td> 3068 * <td>read/write</td> 3069 * <td>Generic columns for use by sync adapters. For example, a Photo row 3070 * may store the image URL in SYNC1, a status (not loaded, loading, loaded, error) 3071 * in SYNC2, server-side version number in SYNC3 and error code in SYNC4.</td> 3072 * </tr> 3073 * </table> 3074 * 3075 * <p> 3076 * Some columns from the most recent associated status update are also available 3077 * through an implicit join. 3078 * </p> 3079 * <table class="jd-sumtable"> 3080 * <tr> 3081 * <th colspan='4'>Join with {@link StatusUpdates}</th> 3082 * </tr> 3083 * <tr> 3084 * <td style="width: 7em;">int</td> 3085 * <td style="width: 20em;">{@link #PRESENCE}</td> 3086 * <td style="width: 5em;">read-only</td> 3087 * <td>IM presence status linked to this data row. Compare with 3088 * {@link #CONTACT_PRESENCE}, which contains the contact's presence across 3089 * all IM rows. See {@link StatusUpdates} for individual status definitions. 3090 * The provider may choose not to store this value 3091 * in persistent storage. The expectation is that presence status will be 3092 * updated on a regular basic. 3093 * </td> 3094 * </tr> 3095 * <tr> 3096 * <td>String</td> 3097 * <td>{@link #STATUS}</td> 3098 * <td>read-only</td> 3099 * <td>Latest status update linked with this data row.</td> 3100 * </tr> 3101 * <tr> 3102 * <td>long</td> 3103 * <td>{@link #STATUS_TIMESTAMP}</td> 3104 * <td>read-only</td> 3105 * <td>The absolute time in milliseconds when the latest status was 3106 * inserted/updated for this data row.</td> 3107 * </tr> 3108 * <tr> 3109 * <td>String</td> 3110 * <td>{@link #STATUS_RES_PACKAGE}</td> 3111 * <td>read-only</td> 3112 * <td>The package containing resources for this status: label and icon.</td> 3113 * </tr> 3114 * <tr> 3115 * <td>long</td> 3116 * <td>{@link #STATUS_LABEL}</td> 3117 * <td>read-only</td> 3118 * <td>The resource ID of the label describing the source of status update linked 3119 * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 3120 * </tr> 3121 * <tr> 3122 * <td>long</td> 3123 * <td>{@link #STATUS_ICON}</td> 3124 * <td>read-only</td> 3125 * <td>The resource ID of the icon for the source of the status update linked 3126 * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 3127 * </tr> 3128 * </table> 3129 * 3130 * <p> 3131 * Some columns from the associated raw contact are also available through an 3132 * implicit join. The other columns are excluded as uninteresting in this 3133 * context. 3134 * </p> 3135 * 3136 * <table class="jd-sumtable"> 3137 * <tr> 3138 * <th colspan='4'>Join with {@link ContactsContract.RawContacts}</th> 3139 * </tr> 3140 * <tr> 3141 * <td style="width: 7em;">long</td> 3142 * <td style="width: 20em;">{@link #CONTACT_ID}</td> 3143 * <td style="width: 5em;">read-only</td> 3144 * <td>The id of the row in the {@link Contacts} table that this data belongs 3145 * to.</td> 3146 * </tr> 3147 * <tr> 3148 * <td>int</td> 3149 * <td>{@link #AGGREGATION_MODE}</td> 3150 * <td>read-only</td> 3151 * <td>See {@link RawContacts}.</td> 3152 * </tr> 3153 * <tr> 3154 * <td>int</td> 3155 * <td>{@link #DELETED}</td> 3156 * <td>read-only</td> 3157 * <td>See {@link RawContacts}.</td> 3158 * </tr> 3159 * </table> 3160 * 3161 * <p> 3162 * The ID column for the associated aggregated contact table 3163 * {@link ContactsContract.Contacts} is available 3164 * via the implicit join to the {@link RawContacts} table, see above. 3165 * The remaining columns from this table are also 3166 * available, through an implicit join. This 3167 * facilitates lookup by 3168 * the value of a single data element, such as the email address. 3169 * </p> 3170 * 3171 * <table class="jd-sumtable"> 3172 * <tr> 3173 * <th colspan='4'>Join with {@link ContactsContract.Contacts}</th> 3174 * </tr> 3175 * <tr> 3176 * <td style="width: 7em;">String</td> 3177 * <td style="width: 20em;">{@link #LOOKUP_KEY}</td> 3178 * <td style="width: 5em;">read-only</td> 3179 * <td>See {@link ContactsContract.Contacts}</td> 3180 * </tr> 3181 * <tr> 3182 * <td>String</td> 3183 * <td>{@link #DISPLAY_NAME}</td> 3184 * <td>read-only</td> 3185 * <td>See {@link ContactsContract.Contacts}</td> 3186 * </tr> 3187 * <tr> 3188 * <td>long</td> 3189 * <td>{@link #PHOTO_ID}</td> 3190 * <td>read-only</td> 3191 * <td>See {@link ContactsContract.Contacts}.</td> 3192 * </tr> 3193 * <tr> 3194 * <td>int</td> 3195 * <td>{@link #IN_VISIBLE_GROUP}</td> 3196 * <td>read-only</td> 3197 * <td>See {@link ContactsContract.Contacts}.</td> 3198 * </tr> 3199 * <tr> 3200 * <td>int</td> 3201 * <td>{@link #HAS_PHONE_NUMBER}</td> 3202 * <td>read-only</td> 3203 * <td>See {@link ContactsContract.Contacts}.</td> 3204 * </tr> 3205 * <tr> 3206 * <td>int</td> 3207 * <td>{@link #TIMES_CONTACTED}</td> 3208 * <td>read-only</td> 3209 * <td>See {@link ContactsContract.Contacts}.</td> 3210 * </tr> 3211 * <tr> 3212 * <td>long</td> 3213 * <td>{@link #LAST_TIME_CONTACTED}</td> 3214 * <td>read-only</td> 3215 * <td>See {@link ContactsContract.Contacts}.</td> 3216 * </tr> 3217 * <tr> 3218 * <td>int</td> 3219 * <td>{@link #STARRED}</td> 3220 * <td>read-only</td> 3221 * <td>See {@link ContactsContract.Contacts}.</td> 3222 * </tr> 3223 * <tr> 3224 * <td>String</td> 3225 * <td>{@link #CUSTOM_RINGTONE}</td> 3226 * <td>read-only</td> 3227 * <td>See {@link ContactsContract.Contacts}.</td> 3228 * </tr> 3229 * <tr> 3230 * <td>int</td> 3231 * <td>{@link #SEND_TO_VOICEMAIL}</td> 3232 * <td>read-only</td> 3233 * <td>See {@link ContactsContract.Contacts}.</td> 3234 * </tr> 3235 * <tr> 3236 * <td>int</td> 3237 * <td>{@link #CONTACT_PRESENCE}</td> 3238 * <td>read-only</td> 3239 * <td>See {@link ContactsContract.Contacts}.</td> 3240 * </tr> 3241 * <tr> 3242 * <td>String</td> 3243 * <td>{@link #CONTACT_STATUS}</td> 3244 * <td>read-only</td> 3245 * <td>See {@link ContactsContract.Contacts}.</td> 3246 * </tr> 3247 * <tr> 3248 * <td>long</td> 3249 * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td> 3250 * <td>read-only</td> 3251 * <td>See {@link ContactsContract.Contacts}.</td> 3252 * </tr> 3253 * <tr> 3254 * <td>String</td> 3255 * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td> 3256 * <td>read-only</td> 3257 * <td>See {@link ContactsContract.Contacts}.</td> 3258 * </tr> 3259 * <tr> 3260 * <td>long</td> 3261 * <td>{@link #CONTACT_STATUS_LABEL}</td> 3262 * <td>read-only</td> 3263 * <td>See {@link ContactsContract.Contacts}.</td> 3264 * </tr> 3265 * <tr> 3266 * <td>long</td> 3267 * <td>{@link #CONTACT_STATUS_ICON}</td> 3268 * <td>read-only</td> 3269 * <td>See {@link ContactsContract.Contacts}.</td> 3270 * </tr> 3271 * </table> 3272 */ 3273 public final static class Data implements DataColumnsWithJoins { 3274 /** 3275 * This utility class cannot be instantiated 3276 */ 3277 private Data() {} 3278 3279 /** 3280 * The content:// style URI for this table, which requests a directory 3281 * of data rows matching the selection criteria. 3282 */ 3283 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data"); 3284 3285 /** 3286 * The MIME type of the results from {@link #CONTENT_URI}. 3287 */ 3288 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; 3289 3290 /** 3291 * <p> 3292 * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward 3293 * Data.CONTENT_URI contains only exportable data. 3294 * </p> 3295 * <p> 3296 * This flag is useful (currently) only for vCard exporter in Contacts app, which 3297 * needs to exclude "un-exportable" data from available data to export, while 3298 * Contacts app itself has priviledge to access all data including "un-exportable" 3299 * ones and providers return all of them regardless of the callers' intention. 3300 * </p> 3301 * <p> 3302 * Type: INTEGER 3303 * </p> 3304 * 3305 * @hide Maybe available only in Eclair and not really ready for public use. 3306 * TODO: remove, or implement this feature completely. As of now (Eclair), 3307 * we only use this flag in queryEntities(), not query(). 3308 */ 3309 public static final String FOR_EXPORT_ONLY = "for_export_only"; 3310 3311 /** 3312 * <p> 3313 * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 3314 * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} 3315 * entry of the given {@link ContactsContract.Data} entry. 3316 * </p> 3317 * <p> 3318 * Returns the Uri for the contact in the first entry returned by 3319 * {@link ContentResolver#query(Uri, String[], String, String[], String)} 3320 * for the provided {@code dataUri}. If the query returns null or empty 3321 * results, silently returns null. 3322 * </p> 3323 */ 3324 public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { 3325 final Cursor cursor = resolver.query(dataUri, new String[] { 3326 RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY 3327 }, null, null, null); 3328 3329 Uri lookupUri = null; 3330 try { 3331 if (cursor != null && cursor.moveToFirst()) { 3332 final long contactId = cursor.getLong(0); 3333 final String lookupKey = cursor.getString(1); 3334 return Contacts.getLookupUri(contactId, lookupKey); 3335 } 3336 } finally { 3337 if (cursor != null) cursor.close(); 3338 } 3339 return lookupUri; 3340 } 3341 } 3342 3343 /** 3344 * <p> 3345 * Constants for the raw contacts entities table, which can be thought of as 3346 * an outer join of the raw_contacts table with the data table. It is a strictly 3347 * read-only table. 3348 * </p> 3349 * <p> 3350 * If a raw contact has data rows, the RawContactsEntity cursor will contain 3351 * a one row for each data row. If the raw contact has no data rows, the 3352 * cursor will still contain one row with the raw contact-level information 3353 * and nulls for data columns. 3354 * 3355 * <pre> 3356 * Uri entityUri = ContentUris.withAppendedId(RawContactsEntity.CONTENT_URI, rawContactId); 3357 * Cursor c = getContentResolver().query(entityUri, 3358 * new String[]{ 3359 * RawContactsEntity.SOURCE_ID, 3360 * RawContactsEntity.DATA_ID, 3361 * RawContactsEntity.MIMETYPE, 3362 * RawContactsEntity.DATA1 3363 * }, null, null, null); 3364 * try { 3365 * while (c.moveToNext()) { 3366 * String sourceId = c.getString(0); 3367 * if (!c.isNull(1)) { 3368 * String mimeType = c.getString(2); 3369 * String data = c.getString(3); 3370 * ... 3371 * } 3372 * } 3373 * } finally { 3374 * c.close(); 3375 * } 3376 * </pre> 3377 * 3378 * <h3>Columns</h3> 3379 * RawContactsEntity has a combination of RawContact and Data columns. 3380 * 3381 * <table class="jd-sumtable"> 3382 * <tr> 3383 * <th colspan='4'>RawContacts</th> 3384 * </tr> 3385 * <tr> 3386 * <td style="width: 7em;">long</td> 3387 * <td style="width: 20em;">{@link #_ID}</td> 3388 * <td style="width: 5em;">read-only</td> 3389 * <td>Raw contact row ID. See {@link RawContacts}.</td> 3390 * </tr> 3391 * <tr> 3392 * <td>long</td> 3393 * <td>{@link #CONTACT_ID}</td> 3394 * <td>read-only</td> 3395 * <td>See {@link RawContacts}.</td> 3396 * </tr> 3397 * <tr> 3398 * <td>int</td> 3399 * <td>{@link #AGGREGATION_MODE}</td> 3400 * <td>read-only</td> 3401 * <td>See {@link RawContacts}.</td> 3402 * </tr> 3403 * <tr> 3404 * <td>int</td> 3405 * <td>{@link #DELETED}</td> 3406 * <td>read-only</td> 3407 * <td>See {@link RawContacts}.</td> 3408 * </tr> 3409 * </table> 3410 * 3411 * <table class="jd-sumtable"> 3412 * <tr> 3413 * <th colspan='4'>Data</th> 3414 * </tr> 3415 * <tr> 3416 * <td style="width: 7em;">long</td> 3417 * <td style="width: 20em;">{@link #DATA_ID}</td> 3418 * <td style="width: 5em;">read-only</td> 3419 * <td>Data row ID. It will be null if the raw contact has no data rows.</td> 3420 * </tr> 3421 * <tr> 3422 * <td>String</td> 3423 * <td>{@link #MIMETYPE}</td> 3424 * <td>read-only</td> 3425 * <td>See {@link ContactsContract.Data}.</td> 3426 * </tr> 3427 * <tr> 3428 * <td>int</td> 3429 * <td>{@link #IS_PRIMARY}</td> 3430 * <td>read-only</td> 3431 * <td>See {@link ContactsContract.Data}.</td> 3432 * </tr> 3433 * <tr> 3434 * <td>int</td> 3435 * <td>{@link #IS_SUPER_PRIMARY}</td> 3436 * <td>read-only</td> 3437 * <td>See {@link ContactsContract.Data}.</td> 3438 * </tr> 3439 * <tr> 3440 * <td>int</td> 3441 * <td>{@link #DATA_VERSION}</td> 3442 * <td>read-only</td> 3443 * <td>See {@link ContactsContract.Data}.</td> 3444 * </tr> 3445 * <tr> 3446 * <td>Any type</td> 3447 * <td> 3448 * {@link #DATA1}<br> 3449 * {@link #DATA2}<br> 3450 * {@link #DATA3}<br> 3451 * {@link #DATA4}<br> 3452 * {@link #DATA5}<br> 3453 * {@link #DATA6}<br> 3454 * {@link #DATA7}<br> 3455 * {@link #DATA8}<br> 3456 * {@link #DATA9}<br> 3457 * {@link #DATA10}<br> 3458 * {@link #DATA11}<br> 3459 * {@link #DATA12}<br> 3460 * {@link #DATA13}<br> 3461 * {@link #DATA14}<br> 3462 * {@link #DATA15} 3463 * </td> 3464 * <td>read-only</td> 3465 * <td>See {@link ContactsContract.Data}.</td> 3466 * </tr> 3467 * <tr> 3468 * <td>Any type</td> 3469 * <td> 3470 * {@link #SYNC1}<br> 3471 * {@link #SYNC2}<br> 3472 * {@link #SYNC3}<br> 3473 * {@link #SYNC4} 3474 * </td> 3475 * <td>read-only</td> 3476 * <td>See {@link ContactsContract.Data}.</td> 3477 * </tr> 3478 * </table> 3479 */ 3480 public final static class RawContactsEntity 3481 implements BaseColumns, DataColumns, RawContactsColumns { 3482 /** 3483 * This utility class cannot be instantiated 3484 */ 3485 private RawContactsEntity() {} 3486 3487 /** 3488 * The content:// style URI for this table 3489 */ 3490 public static final Uri CONTENT_URI = 3491 Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities"); 3492 3493 /** 3494 * The MIME type of {@link #CONTENT_URI} providing a directory of raw contact entities. 3495 */ 3496 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity"; 3497 3498 /** 3499 * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward 3500 * Data.CONTENT_URI contains only exportable data. 3501 * 3502 * This flag is useful (currently) only for vCard exporter in Contacts app, which 3503 * needs to exclude "un-exportable" data from available data to export, while 3504 * Contacts app itself has priviledge to access all data including "un-expotable" 3505 * ones and providers return all of them regardless of the callers' intention. 3506 * <P>Type: INTEGER</p> 3507 * 3508 * @hide Maybe available only in Eclair and not really ready for public use. 3509 * TODO: remove, or implement this feature completely. As of now (Eclair), 3510 * we only use this flag in queryEntities(), not query(). 3511 */ 3512 public static final String FOR_EXPORT_ONLY = "for_export_only"; 3513 3514 /** 3515 * The ID of the data column. The value will be null if this raw contact has no data rows. 3516 * <P>Type: INTEGER</P> 3517 */ 3518 public static final String DATA_ID = "data_id"; 3519 } 3520 3521 /** 3522 * @see PhoneLookup 3523 */ 3524 protected interface PhoneLookupColumns { 3525 /** 3526 * The phone number as the user entered it. 3527 * <P>Type: TEXT</P> 3528 */ 3529 public static final String NUMBER = "number"; 3530 3531 /** 3532 * The type of phone number, for example Home or Work. 3533 * <P>Type: INTEGER</P> 3534 */ 3535 public static final String TYPE = "type"; 3536 3537 /** 3538 * The user defined label for the phone number. 3539 * <P>Type: TEXT</P> 3540 */ 3541 public static final String LABEL = "label"; 3542 3543 /** 3544 * The phone number's E164 representation. 3545 * <P>Type: TEXT</P> 3546 * 3547 * @hide 3548 */ 3549 public static final String NORMALIZED_NUMBER = "normalized_number"; 3550 } 3551 3552 /** 3553 * A table that represents the result of looking up a phone number, for 3554 * example for caller ID. To perform a lookup you must append the number you 3555 * want to find to {@link #CONTENT_FILTER_URI}. This query is highly 3556 * optimized. 3557 * <pre> 3558 * Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); 3559 * resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,... 3560 * </pre> 3561 * 3562 * <h3>Columns</h3> 3563 * 3564 * <table class="jd-sumtable"> 3565 * <tr> 3566 * <th colspan='4'>PhoneLookup</th> 3567 * </tr> 3568 * <tr> 3569 * <td>String</td> 3570 * <td>{@link #NUMBER}</td> 3571 * <td>read-only</td> 3572 * <td>Phone number.</td> 3573 * </tr> 3574 * <tr> 3575 * <td>String</td> 3576 * <td>{@link #TYPE}</td> 3577 * <td>read-only</td> 3578 * <td>Phone number type. See {@link CommonDataKinds.Phone}.</td> 3579 * </tr> 3580 * <tr> 3581 * <td>String</td> 3582 * <td>{@link #LABEL}</td> 3583 * <td>read-only</td> 3584 * <td>Custom label for the phone number. See {@link CommonDataKinds.Phone}.</td> 3585 * </tr> 3586 * </table> 3587 * <p> 3588 * Columns from the Contacts table are also available through a join. 3589 * </p> 3590 * <table class="jd-sumtable"> 3591 * <tr> 3592 * <th colspan='4'>Join with {@link Contacts}</th> 3593 * </tr> 3594 * <tr> 3595 * <td>long</td> 3596 * <td>{@link #_ID}</td> 3597 * <td>read-only</td> 3598 * <td>Contact ID.</td> 3599 * </tr> 3600 * <tr> 3601 * <td>String</td> 3602 * <td>{@link #LOOKUP_KEY}</td> 3603 * <td>read-only</td> 3604 * <td>See {@link ContactsContract.Contacts}</td> 3605 * </tr> 3606 * <tr> 3607 * <td>String</td> 3608 * <td>{@link #DISPLAY_NAME}</td> 3609 * <td>read-only</td> 3610 * <td>See {@link ContactsContract.Contacts}</td> 3611 * </tr> 3612 * <tr> 3613 * <td>long</td> 3614 * <td>{@link #PHOTO_ID}</td> 3615 * <td>read-only</td> 3616 * <td>See {@link ContactsContract.Contacts}.</td> 3617 * </tr> 3618 * <tr> 3619 * <td>int</td> 3620 * <td>{@link #IN_VISIBLE_GROUP}</td> 3621 * <td>read-only</td> 3622 * <td>See {@link ContactsContract.Contacts}.</td> 3623 * </tr> 3624 * <tr> 3625 * <td>int</td> 3626 * <td>{@link #HAS_PHONE_NUMBER}</td> 3627 * <td>read-only</td> 3628 * <td>See {@link ContactsContract.Contacts}.</td> 3629 * </tr> 3630 * <tr> 3631 * <td>int</td> 3632 * <td>{@link #TIMES_CONTACTED}</td> 3633 * <td>read-only</td> 3634 * <td>See {@link ContactsContract.Contacts}.</td> 3635 * </tr> 3636 * <tr> 3637 * <td>long</td> 3638 * <td>{@link #LAST_TIME_CONTACTED}</td> 3639 * <td>read-only</td> 3640 * <td>See {@link ContactsContract.Contacts}.</td> 3641 * </tr> 3642 * <tr> 3643 * <td>int</td> 3644 * <td>{@link #STARRED}</td> 3645 * <td>read-only</td> 3646 * <td>See {@link ContactsContract.Contacts}.</td> 3647 * </tr> 3648 * <tr> 3649 * <td>String</td> 3650 * <td>{@link #CUSTOM_RINGTONE}</td> 3651 * <td>read-only</td> 3652 * <td>See {@link ContactsContract.Contacts}.</td> 3653 * </tr> 3654 * <tr> 3655 * <td>int</td> 3656 * <td>{@link #SEND_TO_VOICEMAIL}</td> 3657 * <td>read-only</td> 3658 * <td>See {@link ContactsContract.Contacts}.</td> 3659 * </tr> 3660 * </table> 3661 */ 3662 public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns, 3663 ContactsColumns, ContactOptionsColumns { 3664 /** 3665 * This utility class cannot be instantiated 3666 */ 3667 private PhoneLookup() {} 3668 3669 /** 3670 * The content:// style URI for this table. Append the phone number you want to lookup 3671 * to this URI and query it to perform a lookup. For example: 3672 * <pre> 3673 * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, Uri.encode(phoneNumber)); 3674 * </pre> 3675 */ 3676 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI, 3677 "phone_lookup"); 3678 3679 /** 3680 * The MIME type of {@link #CONTENT_FILTER_URI} providing a directory of phone lookup rows. 3681 * 3682 * @hide 3683 */ 3684 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_lookup"; 3685 } 3686 3687 /** 3688 * Additional data mixed in with {@link StatusColumns} to link 3689 * back to specific {@link ContactsContract.Data#_ID} entries. 3690 * 3691 * @see StatusUpdates 3692 */ 3693 protected interface PresenceColumns { 3694 3695 /** 3696 * Reference to the {@link Data#_ID} entry that owns this presence. 3697 * <P>Type: INTEGER</P> 3698 */ 3699 public static final String DATA_ID = "presence_data_id"; 3700 3701 /** 3702 * See {@link CommonDataKinds.Im} for a list of defined protocol constants. 3703 * <p>Type: NUMBER</p> 3704 */ 3705 public static final String PROTOCOL = "protocol"; 3706 3707 /** 3708 * Name of the custom protocol. Should be supplied along with the {@link #PROTOCOL} value 3709 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. Should be null or 3710 * omitted if {@link #PROTOCOL} value is not 3711 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. 3712 * 3713 * <p>Type: NUMBER</p> 3714 */ 3715 public static final String CUSTOM_PROTOCOL = "custom_protocol"; 3716 3717 /** 3718 * The IM handle the presence item is for. The handle is scoped to 3719 * {@link #PROTOCOL}. 3720 * <P>Type: TEXT</P> 3721 */ 3722 public static final String IM_HANDLE = "im_handle"; 3723 3724 /** 3725 * The IM account for the local user that the presence data came from. 3726 * <P>Type: TEXT</P> 3727 */ 3728 public static final String IM_ACCOUNT = "im_account"; 3729 } 3730 3731 /** 3732 * <p> 3733 * A status update is linked to a {@link ContactsContract.Data} row and captures 3734 * the user's latest status update via the corresponding source, e.g. 3735 * "Having lunch" via "Google Talk". 3736 * </p> 3737 * <p> 3738 * There are two ways a status update can be inserted: by explicitly linking 3739 * it to a Data row using {@link #DATA_ID} or indirectly linking it to a data row 3740 * using a combination of {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and 3741 * {@link #IM_HANDLE}. There is no difference between insert and update, you can use 3742 * either. 3743 * </p> 3744 * <p> 3745 * You cannot use {@link ContentResolver#update} to change a status, but 3746 * {@link ContentResolver#insert} will replace the latests status if it already 3747 * exists. 3748 * </p> 3749 * <p> 3750 * Use {@link ContentResolver#bulkInsert(Uri, ContentValues[])} to insert/update statuses 3751 * for multiple contacts at once. 3752 * </p> 3753 * 3754 * <h3>Columns</h3> 3755 * <table class="jd-sumtable"> 3756 * <tr> 3757 * <th colspan='4'>StatusUpdates</th> 3758 * </tr> 3759 * <tr> 3760 * <td>long</td> 3761 * <td>{@link #DATA_ID}</td> 3762 * <td>read/write</td> 3763 * <td>Reference to the {@link Data#_ID} entry that owns this presence. If this 3764 * field is <i>not</i> specified, the provider will attempt to find a data row 3765 * that matches the {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and 3766 * {@link #IM_HANDLE} columns. 3767 * </td> 3768 * </tr> 3769 * <tr> 3770 * <td>long</td> 3771 * <td>{@link #PROTOCOL}</td> 3772 * <td>read/write</td> 3773 * <td>See {@link CommonDataKinds.Im} for a list of defined protocol constants.</td> 3774 * </tr> 3775 * <tr> 3776 * <td>String</td> 3777 * <td>{@link #CUSTOM_PROTOCOL}</td> 3778 * <td>read/write</td> 3779 * <td>Name of the custom protocol. Should be supplied along with the {@link #PROTOCOL} value 3780 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. Should be null or 3781 * omitted if {@link #PROTOCOL} value is not 3782 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.</td> 3783 * </tr> 3784 * <tr> 3785 * <td>String</td> 3786 * <td>{@link #IM_HANDLE}</td> 3787 * <td>read/write</td> 3788 * <td> The IM handle the presence item is for. The handle is scoped to 3789 * {@link #PROTOCOL}.</td> 3790 * </tr> 3791 * <tr> 3792 * <td>String</td> 3793 * <td>{@link #IM_ACCOUNT}</td> 3794 * <td>read/write</td> 3795 * <td>The IM account for the local user that the presence data came from.</td> 3796 * </tr> 3797 * <tr> 3798 * <td>int</td> 3799 * <td>{@link #PRESENCE}</td> 3800 * <td>read/write</td> 3801 * <td>Contact IM presence status. The allowed values are: 3802 * <p> 3803 * <ul> 3804 * <li>{@link #OFFLINE}</li> 3805 * <li>{@link #INVISIBLE}</li> 3806 * <li>{@link #AWAY}</li> 3807 * <li>{@link #IDLE}</li> 3808 * <li>{@link #DO_NOT_DISTURB}</li> 3809 * <li>{@link #AVAILABLE}</li> 3810 * </ul> 3811 * </p> 3812 * <p> 3813 * Since presence status is inherently volatile, the content provider 3814 * may choose not to store this field in long-term storage. 3815 * </p> 3816 * </td> 3817 * </tr> 3818 * <tr> 3819 * <td>int</td> 3820 * <td>{@link #CHAT_CAPABILITY}</td> 3821 * <td>read/write</td> 3822 * <td>Contact IM chat compatibility value. The allowed values combinations of the following 3823 * flags. If None of these flags is set, the device can only do text messaging. 3824 * <p> 3825 * <ul> 3826 * <li>{@link #CAPABILITY_HAS_VIDEO}</li> 3827 * <li>{@link #CAPABILITY_HAS_VOICE}</li> 3828 * <li>{@link #CAPABILITY_HAS_CAMERA}</li> 3829 * </ul> 3830 * </p> 3831 * <p> 3832 * Since chat compatibility is inherently volatile as the contact's availability moves from 3833 * one device to another, the content provider may choose not to store this field in long-term 3834 * storage. 3835 * </p> 3836 * </td> 3837 * </tr> 3838 * <tr> 3839 * <td>String</td> 3840 * <td>{@link #STATUS}</td> 3841 * <td>read/write</td> 3842 * <td>Contact's latest status update, e.g. "having toast for breakfast"</td> 3843 * </tr> 3844 * <tr> 3845 * <td>long</td> 3846 * <td>{@link #STATUS_TIMESTAMP}</td> 3847 * <td>read/write</td> 3848 * <td>The absolute time in milliseconds when the status was 3849 * entered by the user. If this value is not provided, the provider will follow 3850 * this logic: if there was no prior status update, the value will be left as null. 3851 * If there was a prior status update, the provider will default this field 3852 * to the current time.</td> 3853 * </tr> 3854 * <tr> 3855 * <td>String</td> 3856 * <td>{@link #STATUS_RES_PACKAGE}</td> 3857 * <td>read/write</td> 3858 * <td> The package containing resources for this status: label and icon.</td> 3859 * </tr> 3860 * <tr> 3861 * <td>long</td> 3862 * <td>{@link #STATUS_LABEL}</td> 3863 * <td>read/write</td> 3864 * <td>The resource ID of the label describing the source of contact status, 3865 * e.g. "Google Talk". This resource is scoped by the 3866 * {@link #STATUS_RES_PACKAGE}.</td> 3867 * </tr> 3868 * <tr> 3869 * <td>long</td> 3870 * <td>{@link #STATUS_ICON}</td> 3871 * <td>read/write</td> 3872 * <td>The resource ID of the icon for the source of contact status. This 3873 * resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 3874 * </tr> 3875 * </table> 3876 */ 3877 public static class StatusUpdates implements StatusColumns, PresenceColumns { 3878 3879 /** 3880 * This utility class cannot be instantiated 3881 */ 3882 private StatusUpdates() {} 3883 3884 /** 3885 * The content:// style URI for this table 3886 */ 3887 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "status_updates"); 3888 3889 /** 3890 * Gets the resource ID for the proper presence icon. 3891 * 3892 * @param status the status to get the icon for 3893 * @return the resource ID for the proper presence icon 3894 */ 3895 public static final int getPresenceIconResourceId(int status) { 3896 switch (status) { 3897 case AVAILABLE: 3898 return android.R.drawable.presence_online; 3899 case IDLE: 3900 case AWAY: 3901 return android.R.drawable.presence_away; 3902 case DO_NOT_DISTURB: 3903 return android.R.drawable.presence_busy; 3904 case INVISIBLE: 3905 return android.R.drawable.presence_invisible; 3906 case OFFLINE: 3907 default: 3908 return android.R.drawable.presence_offline; 3909 } 3910 } 3911 3912 /** 3913 * Returns the precedence of the status code the higher number being the higher precedence. 3914 * 3915 * @param status The status code. 3916 * @return An integer representing the precedence, 0 being the lowest. 3917 */ 3918 public static final int getPresencePrecedence(int status) { 3919 // Keep this function here incase we want to enforce a different precedence than the 3920 // natural order of the status constants. 3921 return status; 3922 } 3923 3924 /** 3925 * The MIME type of {@link #CONTENT_URI} providing a directory of 3926 * status update details. 3927 */ 3928 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/status-update"; 3929 3930 /** 3931 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 3932 * status update detail. 3933 */ 3934 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update"; 3935 } 3936 3937 /** 3938 * @deprecated This old name was never meant to be made public. Do not use. 3939 */ 3940 @Deprecated 3941 public static final class Presence extends StatusUpdates { 3942 3943 } 3944 3945 /** 3946 * Additional column returned by the {@link Contacts#CONTENT_FILTER_URI} providing the 3947 * explanation of why the filter matched the contact. Specifically, it contains the 3948 * data elements that matched the query. The overall number of words in the snippet 3949 * can be capped. 3950 * 3951 * @hide 3952 */ 3953 public static class SearchSnippetColumns { 3954 3955 /** 3956 * The search snippet constructed according to the SQLite rules, see 3957 * http://www.sqlite.org/fts3.html#snippet 3958 * <p> 3959 * The snippet may contain (parts of) several data elements comprising 3960 * the contact. 3961 * 3962 * @hide 3963 */ 3964 public static final String SNIPPET = "snippet"; 3965 3966 3967 /** 3968 * Comma-separated parameters for the generation of the snippet: 3969 * <ul> 3970 * <li>The "start match" text. Default is <b></li> 3971 * <li>The "end match" text. Default is </b></li> 3972 * <li>The "ellipsis" text. Default is <b>...</b></li> 3973 * <li>Maximum number of tokens to include in the snippet. Can be either 3974 * a positive or a negative number: A positive number indicates how many 3975 * tokens can be returned in total. A negative number indicates how many 3976 * tokens can be returned per occurrence of the search terms.</li> 3977 * </ul> 3978 * 3979 * @hide 3980 */ 3981 public static final String SNIPPET_ARGS_PARAM_KEY = "snippet_args"; 3982 } 3983 3984 /** 3985 * Container for definitions of common data types stored in the {@link ContactsContract.Data} 3986 * table. 3987 */ 3988 public static final class CommonDataKinds { 3989 /** 3990 * This utility class cannot be instantiated 3991 */ 3992 private CommonDataKinds() {} 3993 3994 /** 3995 * The {@link Data#RES_PACKAGE} value for common data that should be 3996 * shown using a default style. 3997 * 3998 * @hide RES_PACKAGE is hidden 3999 */ 4000 public static final String PACKAGE_COMMON = "common"; 4001 4002 /** 4003 * The base types that all "Typed" data kinds support. 4004 */ 4005 public interface BaseTypes { 4006 /** 4007 * A custom type. The custom label should be supplied by user. 4008 */ 4009 public static int TYPE_CUSTOM = 0; 4010 } 4011 4012 /** 4013 * Columns common across the specific types. 4014 */ 4015 protected interface CommonColumns extends BaseTypes { 4016 /** 4017 * The data for the contact method. 4018 * <P>Type: TEXT</P> 4019 */ 4020 public static final String DATA = DataColumns.DATA1; 4021 4022 /** 4023 * The type of data, for example Home or Work. 4024 * <P>Type: INTEGER</P> 4025 */ 4026 public static final String TYPE = DataColumns.DATA2; 4027 4028 /** 4029 * The user defined label for the the contact method. 4030 * <P>Type: TEXT</P> 4031 */ 4032 public static final String LABEL = DataColumns.DATA3; 4033 } 4034 4035 /** 4036 * A data kind representing the contact's proper name. You can use all 4037 * columns defined for {@link ContactsContract.Data} as well as the following aliases. 4038 * 4039 * <h2>Column aliases</h2> 4040 * <table class="jd-sumtable"> 4041 * <tr> 4042 * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th> 4043 * </tr> 4044 * <tr> 4045 * <td>String</td> 4046 * <td>{@link #DISPLAY_NAME}</td> 4047 * <td>{@link #DATA1}</td> 4048 * <td></td> 4049 * </tr> 4050 * <tr> 4051 * <td>String</td> 4052 * <td>{@link #GIVEN_NAME}</td> 4053 * <td>{@link #DATA2}</td> 4054 * <td></td> 4055 * </tr> 4056 * <tr> 4057 * <td>String</td> 4058 * <td>{@link #FAMILY_NAME}</td> 4059 * <td>{@link #DATA3}</td> 4060 * <td></td> 4061 * </tr> 4062 * <tr> 4063 * <td>String</td> 4064 * <td>{@link #PREFIX}</td> 4065 * <td>{@link #DATA4}</td> 4066 * <td>Common prefixes in English names are "Mr", "Ms", "Dr" etc.</td> 4067 * </tr> 4068 * <tr> 4069 * <td>String</td> 4070 * <td>{@link #MIDDLE_NAME}</td> 4071 * <td>{@link #DATA5}</td> 4072 * <td></td> 4073 * </tr> 4074 * <tr> 4075 * <td>String</td> 4076 * <td>{@link #SUFFIX}</td> 4077 * <td>{@link #DATA6}</td> 4078 * <td>Common suffixes in English names are "Sr", "Jr", "III" etc.</td> 4079 * </tr> 4080 * <tr> 4081 * <td>String</td> 4082 * <td>{@link #PHONETIC_GIVEN_NAME}</td> 4083 * <td>{@link #DATA7}</td> 4084 * <td>Used for phonetic spelling of the name, e.g. Pinyin, Katakana, Hiragana</td> 4085 * </tr> 4086 * <tr> 4087 * <td>String</td> 4088 * <td>{@link #PHONETIC_MIDDLE_NAME}</td> 4089 * <td>{@link #DATA8}</td> 4090 * <td></td> 4091 * </tr> 4092 * <tr> 4093 * <td>String</td> 4094 * <td>{@link #PHONETIC_FAMILY_NAME}</td> 4095 * <td>{@link #DATA9}</td> 4096 * <td></td> 4097 * </tr> 4098 * </table> 4099 */ 4100 public static final class StructuredName implements DataColumnsWithJoins { 4101 /** 4102 * This utility class cannot be instantiated 4103 */ 4104 private StructuredName() {} 4105 4106 /** MIME type used when storing this in data table. */ 4107 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name"; 4108 4109 /** 4110 * The name that should be used to display the contact. 4111 * <i>Unstructured component of the name should be consistent with 4112 * its structured representation.</i> 4113 * <p> 4114 * Type: TEXT 4115 */ 4116 public static final String DISPLAY_NAME = DATA1; 4117 4118 /** 4119 * The given name for the contact. 4120 * <P>Type: TEXT</P> 4121 */ 4122 public static final String GIVEN_NAME = DATA2; 4123 4124 /** 4125 * The family name for the contact. 4126 * <P>Type: TEXT</P> 4127 */ 4128 public static final String FAMILY_NAME = DATA3; 4129 4130 /** 4131 * The contact's honorific prefix, e.g. "Sir" 4132 * <P>Type: TEXT</P> 4133 */ 4134 public static final String PREFIX = DATA4; 4135 4136 /** 4137 * The contact's middle name 4138 * <P>Type: TEXT</P> 4139 */ 4140 public static final String MIDDLE_NAME = DATA5; 4141 4142 /** 4143 * The contact's honorific suffix, e.g. "Jr" 4144 */ 4145 public static final String SUFFIX = DATA6; 4146 4147 /** 4148 * The phonetic version of the given name for the contact. 4149 * <P>Type: TEXT</P> 4150 */ 4151 public static final String PHONETIC_GIVEN_NAME = DATA7; 4152 4153 /** 4154 * The phonetic version of the additional name for the contact. 4155 * <P>Type: TEXT</P> 4156 */ 4157 public static final String PHONETIC_MIDDLE_NAME = DATA8; 4158 4159 /** 4160 * The phonetic version of the family name for the contact. 4161 * <P>Type: TEXT</P> 4162 */ 4163 public static final String PHONETIC_FAMILY_NAME = DATA9; 4164 4165 /** 4166 * The style used for combining given/middle/family name into a full name. 4167 * See {@link ContactsContract.FullNameStyle}. 4168 * 4169 * @hide 4170 */ 4171 public static final String FULL_NAME_STYLE = DATA10; 4172 4173 /** 4174 * The alphabet used for capturing the phonetic name. 4175 * See ContactsContract.PhoneticNameStyle. 4176 * @hide 4177 */ 4178 public static final String PHONETIC_NAME_STYLE = DATA11; 4179 } 4180 4181 /** 4182 * <p>A data kind representing the contact's nickname. For example, for 4183 * Bob Parr ("Mr. Incredible"): 4184 * <pre> 4185 * ArrayList<ContentProviderOperation> ops = 4186 * new ArrayList<ContentProviderOperation>(); 4187 * 4188 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 4189 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 4190 * .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 4191 * .withValue(StructuredName.DISPLAY_NAME, "Bob Parr") 4192 * .build()); 4193 * 4194 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 4195 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 4196 * .withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE) 4197 * .withValue(Nickname.NAME, "Mr. Incredible") 4198 * .withValue(Nickname.TYPE, Nickname.TYPE_CUSTOM) 4199 * .withValue(Nickname.LABEL, "Superhero") 4200 * .build()); 4201 * 4202 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 4203 * </pre> 4204 * </p> 4205 * <p> 4206 * You can use all columns defined for {@link ContactsContract.Data} as well as the 4207 * following aliases. 4208 * </p> 4209 * 4210 * <h2>Column aliases</h2> 4211 * <table class="jd-sumtable"> 4212 * <tr> 4213 * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th> 4214 * </tr> 4215 * <tr> 4216 * <td>String</td> 4217 * <td>{@link #NAME}</td> 4218 * <td>{@link #DATA1}</td> 4219 * <td></td> 4220 * </tr> 4221 * <tr> 4222 * <td>int</td> 4223 * <td>{@link #TYPE}</td> 4224 * <td>{@link #DATA2}</td> 4225 * <td> 4226 * Allowed values are: 4227 * <p> 4228 * <ul> 4229 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4230 * <li>{@link #TYPE_DEFAULT}</li> 4231 * <li>{@link #TYPE_OTHER_NAME}</li> 4232 * <li>{@link #TYPE_MAIDEN_NAME}</li> 4233 * <li>{@link #TYPE_SHORT_NAME}</li> 4234 * <li>{@link #TYPE_INITIALS}</li> 4235 * </ul> 4236 * </p> 4237 * </td> 4238 * </tr> 4239 * <tr> 4240 * <td>String</td> 4241 * <td>{@link #LABEL}</td> 4242 * <td>{@link #DATA3}</td> 4243 * <td></td> 4244 * </tr> 4245 * </table> 4246 */ 4247 public static final class Nickname implements DataColumnsWithJoins, CommonColumns { 4248 /** 4249 * This utility class cannot be instantiated 4250 */ 4251 private Nickname() {} 4252 4253 /** MIME type used when storing this in data table. */ 4254 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname"; 4255 4256 public static final int TYPE_DEFAULT = 1; 4257 public static final int TYPE_OTHER_NAME = 2; 4258 public static final int TYPE_MAIDEN_NAME = 3; 4259 /** @deprecated Use TYPE_MAIDEN_NAME instead. */ 4260 @Deprecated 4261 public static final int TYPE_MAINDEN_NAME = 3; 4262 public static final int TYPE_SHORT_NAME = 4; 4263 public static final int TYPE_INITIALS = 5; 4264 4265 /** 4266 * The name itself 4267 */ 4268 public static final String NAME = DATA; 4269 } 4270 4271 /** 4272 * <p> 4273 * A data kind representing a telephone number. 4274 * </p> 4275 * <p> 4276 * You can use all columns defined for {@link ContactsContract.Data} as 4277 * well as the following aliases. 4278 * </p> 4279 * <h2>Column aliases</h2> 4280 * <table class="jd-sumtable"> 4281 * <tr> 4282 * <th>Type</th> 4283 * <th>Alias</th><th colspan='2'>Data column</th> 4284 * </tr> 4285 * <tr> 4286 * <td>String</td> 4287 * <td>{@link #NUMBER}</td> 4288 * <td>{@link #DATA1}</td> 4289 * <td></td> 4290 * </tr> 4291 * <tr> 4292 * <td>int</td> 4293 * <td>{@link #TYPE}</td> 4294 * <td>{@link #DATA2}</td> 4295 * <td>Allowed values are: 4296 * <p> 4297 * <ul> 4298 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4299 * <li>{@link #TYPE_HOME}</li> 4300 * <li>{@link #TYPE_MOBILE}</li> 4301 * <li>{@link #TYPE_WORK}</li> 4302 * <li>{@link #TYPE_FAX_WORK}</li> 4303 * <li>{@link #TYPE_FAX_HOME}</li> 4304 * <li>{@link #TYPE_PAGER}</li> 4305 * <li>{@link #TYPE_OTHER}</li> 4306 * <li>{@link #TYPE_CALLBACK}</li> 4307 * <li>{@link #TYPE_CAR}</li> 4308 * <li>{@link #TYPE_COMPANY_MAIN}</li> 4309 * <li>{@link #TYPE_ISDN}</li> 4310 * <li>{@link #TYPE_MAIN}</li> 4311 * <li>{@link #TYPE_OTHER_FAX}</li> 4312 * <li>{@link #TYPE_RADIO}</li> 4313 * <li>{@link #TYPE_TELEX}</li> 4314 * <li>{@link #TYPE_TTY_TDD}</li> 4315 * <li>{@link #TYPE_WORK_MOBILE}</li> 4316 * <li>{@link #TYPE_WORK_PAGER}</li> 4317 * <li>{@link #TYPE_ASSISTANT}</li> 4318 * <li>{@link #TYPE_MMS}</li> 4319 * </ul> 4320 * </p> 4321 * </td> 4322 * </tr> 4323 * <tr> 4324 * <td>String</td> 4325 * <td>{@link #LABEL}</td> 4326 * <td>{@link #DATA3}</td> 4327 * <td></td> 4328 * </tr> 4329 * </table> 4330 */ 4331 public static final class Phone implements DataColumnsWithJoins, CommonColumns { 4332 /** 4333 * This utility class cannot be instantiated 4334 */ 4335 private Phone() {} 4336 4337 /** MIME type used when storing this in data table. */ 4338 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2"; 4339 4340 /** 4341 * The MIME type of {@link #CONTENT_URI} providing a directory of 4342 * phones. 4343 */ 4344 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2"; 4345 4346 /** 4347 * The content:// style URI for all data records of the 4348 * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the 4349 * associated raw contact and aggregate contact data. 4350 */ 4351 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 4352 "phones"); 4353 4354 /** 4355 * The content:// style URL for phone lookup using a filter. The filter returns 4356 * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied 4357 * to display names as well as phone numbers. The filter argument should be passed 4358 * as an additional path segment after this URI. 4359 */ 4360 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, 4361 "filter"); 4362 4363 public static final int TYPE_HOME = 1; 4364 public static final int TYPE_MOBILE = 2; 4365 public static final int TYPE_WORK = 3; 4366 public static final int TYPE_FAX_WORK = 4; 4367 public static final int TYPE_FAX_HOME = 5; 4368 public static final int TYPE_PAGER = 6; 4369 public static final int TYPE_OTHER = 7; 4370 public static final int TYPE_CALLBACK = 8; 4371 public static final int TYPE_CAR = 9; 4372 public static final int TYPE_COMPANY_MAIN = 10; 4373 public static final int TYPE_ISDN = 11; 4374 public static final int TYPE_MAIN = 12; 4375 public static final int TYPE_OTHER_FAX = 13; 4376 public static final int TYPE_RADIO = 14; 4377 public static final int TYPE_TELEX = 15; 4378 public static final int TYPE_TTY_TDD = 16; 4379 public static final int TYPE_WORK_MOBILE = 17; 4380 public static final int TYPE_WORK_PAGER = 18; 4381 public static final int TYPE_ASSISTANT = 19; 4382 public static final int TYPE_MMS = 20; 4383 4384 /** 4385 * The phone number as the user entered it. 4386 * <P>Type: TEXT</P> 4387 */ 4388 public static final String NUMBER = DATA; 4389 4390 /** 4391 * The phone number's E164 representation. 4392 * <P>Type: TEXT</P> 4393 * 4394 * @hide 4395 */ 4396 public static final String NORMALIZED_NUMBER = DATA4; 4397 4398 /** 4399 * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. 4400 * @hide 4401 */ 4402 @Deprecated 4403 public static final CharSequence getDisplayLabel(Context context, int type, 4404 CharSequence label, CharSequence[] labelArray) { 4405 return getTypeLabel(context.getResources(), type, label); 4406 } 4407 4408 /** 4409 * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. 4410 * @hide 4411 */ 4412 @Deprecated 4413 public static final CharSequence getDisplayLabel(Context context, int type, 4414 CharSequence label) { 4415 return getTypeLabel(context.getResources(), type, label); 4416 } 4417 4418 /** 4419 * Return the string resource that best describes the given 4420 * {@link #TYPE}. Will always return a valid resource. 4421 */ 4422 public static final int getTypeLabelResource(int type) { 4423 switch (type) { 4424 case TYPE_HOME: return com.android.internal.R.string.phoneTypeHome; 4425 case TYPE_MOBILE: return com.android.internal.R.string.phoneTypeMobile; 4426 case TYPE_WORK: return com.android.internal.R.string.phoneTypeWork; 4427 case TYPE_FAX_WORK: return com.android.internal.R.string.phoneTypeFaxWork; 4428 case TYPE_FAX_HOME: return com.android.internal.R.string.phoneTypeFaxHome; 4429 case TYPE_PAGER: return com.android.internal.R.string.phoneTypePager; 4430 case TYPE_OTHER: return com.android.internal.R.string.phoneTypeOther; 4431 case TYPE_CALLBACK: return com.android.internal.R.string.phoneTypeCallback; 4432 case TYPE_CAR: return com.android.internal.R.string.phoneTypeCar; 4433 case TYPE_COMPANY_MAIN: return com.android.internal.R.string.phoneTypeCompanyMain; 4434 case TYPE_ISDN: return com.android.internal.R.string.phoneTypeIsdn; 4435 case TYPE_MAIN: return com.android.internal.R.string.phoneTypeMain; 4436 case TYPE_OTHER_FAX: return com.android.internal.R.string.phoneTypeOtherFax; 4437 case TYPE_RADIO: return com.android.internal.R.string.phoneTypeRadio; 4438 case TYPE_TELEX: return com.android.internal.R.string.phoneTypeTelex; 4439 case TYPE_TTY_TDD: return com.android.internal.R.string.phoneTypeTtyTdd; 4440 case TYPE_WORK_MOBILE: return com.android.internal.R.string.phoneTypeWorkMobile; 4441 case TYPE_WORK_PAGER: return com.android.internal.R.string.phoneTypeWorkPager; 4442 case TYPE_ASSISTANT: return com.android.internal.R.string.phoneTypeAssistant; 4443 case TYPE_MMS: return com.android.internal.R.string.phoneTypeMms; 4444 default: return com.android.internal.R.string.phoneTypeCustom; 4445 } 4446 } 4447 4448 /** 4449 * Return a {@link CharSequence} that best describes the given type, 4450 * possibly substituting the given {@link #LABEL} value 4451 * for {@link #TYPE_CUSTOM}. 4452 */ 4453 public static final CharSequence getTypeLabel(Resources res, int type, 4454 CharSequence label) { 4455 if ((type == TYPE_CUSTOM || type == TYPE_ASSISTANT) && !TextUtils.isEmpty(label)) { 4456 return label; 4457 } else { 4458 final int labelRes = getTypeLabelResource(type); 4459 return res.getText(labelRes); 4460 } 4461 } 4462 } 4463 4464 /** 4465 * <p> 4466 * A data kind representing an email address. 4467 * </p> 4468 * <p> 4469 * You can use all columns defined for {@link ContactsContract.Data} as 4470 * well as the following aliases. 4471 * </p> 4472 * <h2>Column aliases</h2> 4473 * <table class="jd-sumtable"> 4474 * <tr> 4475 * <th>Type</th> 4476 * <th>Alias</th><th colspan='2'>Data column</th> 4477 * </tr> 4478 * <tr> 4479 * <td>String</td> 4480 * <td>{@link #ADDRESS}</td> 4481 * <td>{@link #DATA1}</td> 4482 * <td>Email address itself.</td> 4483 * </tr> 4484 * <tr> 4485 * <td>int</td> 4486 * <td>{@link #TYPE}</td> 4487 * <td>{@link #DATA2}</td> 4488 * <td>Allowed values are: 4489 * <p> 4490 * <ul> 4491 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4492 * <li>{@link #TYPE_HOME}</li> 4493 * <li>{@link #TYPE_WORK}</li> 4494 * <li>{@link #TYPE_OTHER}</li> 4495 * <li>{@link #TYPE_MOBILE}</li> 4496 * </ul> 4497 * </p> 4498 * </td> 4499 * </tr> 4500 * <tr> 4501 * <td>String</td> 4502 * <td>{@link #LABEL}</td> 4503 * <td>{@link #DATA3}</td> 4504 * <td></td> 4505 * </tr> 4506 * </table> 4507 */ 4508 public static final class Email implements DataColumnsWithJoins, CommonColumns { 4509 /** 4510 * This utility class cannot be instantiated 4511 */ 4512 private Email() {} 4513 4514 /** MIME type used when storing this in data table. */ 4515 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2"; 4516 4517 /** 4518 * The MIME type of {@link #CONTENT_URI} providing a directory of email addresses. 4519 */ 4520 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2"; 4521 4522 /** 4523 * The content:// style URI for all data records of the 4524 * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the 4525 * associated raw contact and aggregate contact data. 4526 */ 4527 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 4528 "emails"); 4529 4530 /** 4531 * <p> 4532 * The content:// style URL for looking up data rows by email address. The 4533 * lookup argument, an email address, should be passed as an additional path segment 4534 * after this URI. 4535 * </p> 4536 * <p>Example: 4537 * <pre> 4538 * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(email)); 4539 * Cursor c = getContentResolver().query(uri, 4540 * new String[]{Email.CONTACT_ID, Email.DISPLAY_NAME, Email.DATA}, 4541 * null, null, null); 4542 * </pre> 4543 * </p> 4544 */ 4545 public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, 4546 "lookup"); 4547 4548 /** 4549 * <p> 4550 * The content:// style URL for email lookup using a filter. The filter returns 4551 * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied 4552 * to display names as well as email addresses. The filter argument should be passed 4553 * as an additional path segment after this URI. 4554 * </p> 4555 * <p>The query in the following example will return "Robert Parr (bob@incredibles.com)" 4556 * as well as "Bob Parr (incredible@android.com)". 4557 * <pre> 4558 * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode("bob")); 4559 * Cursor c = getContentResolver().query(uri, 4560 * new String[]{Email.DISPLAY_NAME, Email.DATA}, 4561 * null, null, null); 4562 * </pre> 4563 * </p> 4564 */ 4565 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, 4566 "filter"); 4567 4568 /** 4569 * The email address. 4570 * <P>Type: TEXT</P> 4571 */ 4572 public static final String ADDRESS = DATA1; 4573 4574 public static final int TYPE_HOME = 1; 4575 public static final int TYPE_WORK = 2; 4576 public static final int TYPE_OTHER = 3; 4577 public static final int TYPE_MOBILE = 4; 4578 4579 /** 4580 * The display name for the email address 4581 * <P>Type: TEXT</P> 4582 */ 4583 public static final String DISPLAY_NAME = DATA4; 4584 4585 /** 4586 * Return the string resource that best describes the given 4587 * {@link #TYPE}. Will always return a valid resource. 4588 */ 4589 public static final int getTypeLabelResource(int type) { 4590 switch (type) { 4591 case TYPE_HOME: return com.android.internal.R.string.emailTypeHome; 4592 case TYPE_WORK: return com.android.internal.R.string.emailTypeWork; 4593 case TYPE_OTHER: return com.android.internal.R.string.emailTypeOther; 4594 case TYPE_MOBILE: return com.android.internal.R.string.emailTypeMobile; 4595 default: return com.android.internal.R.string.emailTypeCustom; 4596 } 4597 } 4598 4599 /** 4600 * Return a {@link CharSequence} that best describes the given type, 4601 * possibly substituting the given {@link #LABEL} value 4602 * for {@link #TYPE_CUSTOM}. 4603 */ 4604 public static final CharSequence getTypeLabel(Resources res, int type, 4605 CharSequence label) { 4606 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 4607 return label; 4608 } else { 4609 final int labelRes = getTypeLabelResource(type); 4610 return res.getText(labelRes); 4611 } 4612 } 4613 } 4614 4615 /** 4616 * <p> 4617 * A data kind representing a postal addresses. 4618 * </p> 4619 * <p> 4620 * You can use all columns defined for {@link ContactsContract.Data} as 4621 * well as the following aliases. 4622 * </p> 4623 * <h2>Column aliases</h2> 4624 * <table class="jd-sumtable"> 4625 * <tr> 4626 * <th>Type</th> 4627 * <th>Alias</th><th colspan='2'>Data column</th> 4628 * </tr> 4629 * <tr> 4630 * <td>String</td> 4631 * <td>{@link #FORMATTED_ADDRESS}</td> 4632 * <td>{@link #DATA1}</td> 4633 * <td></td> 4634 * </tr> 4635 * <tr> 4636 * <td>int</td> 4637 * <td>{@link #TYPE}</td> 4638 * <td>{@link #DATA2}</td> 4639 * <td>Allowed values are: 4640 * <p> 4641 * <ul> 4642 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4643 * <li>{@link #TYPE_HOME}</li> 4644 * <li>{@link #TYPE_WORK}</li> 4645 * <li>{@link #TYPE_OTHER}</li> 4646 * </ul> 4647 * </p> 4648 * </td> 4649 * </tr> 4650 * <tr> 4651 * <td>String</td> 4652 * <td>{@link #LABEL}</td> 4653 * <td>{@link #DATA3}</td> 4654 * <td></td> 4655 * </tr> 4656 * <tr> 4657 * <td>String</td> 4658 * <td>{@link #STREET}</td> 4659 * <td>{@link #DATA4}</td> 4660 * <td></td> 4661 * </tr> 4662 * <tr> 4663 * <td>String</td> 4664 * <td>{@link #POBOX}</td> 4665 * <td>{@link #DATA5}</td> 4666 * <td>Post Office Box number</td> 4667 * </tr> 4668 * <tr> 4669 * <td>String</td> 4670 * <td>{@link #NEIGHBORHOOD}</td> 4671 * <td>{@link #DATA6}</td> 4672 * <td></td> 4673 * </tr> 4674 * <tr> 4675 * <td>String</td> 4676 * <td>{@link #CITY}</td> 4677 * <td>{@link #DATA7}</td> 4678 * <td></td> 4679 * </tr> 4680 * <tr> 4681 * <td>String</td> 4682 * <td>{@link #REGION}</td> 4683 * <td>{@link #DATA8}</td> 4684 * <td></td> 4685 * </tr> 4686 * <tr> 4687 * <td>String</td> 4688 * <td>{@link #POSTCODE}</td> 4689 * <td>{@link #DATA9}</td> 4690 * <td></td> 4691 * </tr> 4692 * <tr> 4693 * <td>String</td> 4694 * <td>{@link #COUNTRY}</td> 4695 * <td>{@link #DATA10}</td> 4696 * <td></td> 4697 * </tr> 4698 * </table> 4699 */ 4700 public static final class StructuredPostal implements DataColumnsWithJoins, CommonColumns { 4701 /** 4702 * This utility class cannot be instantiated 4703 */ 4704 private StructuredPostal() { 4705 } 4706 4707 /** MIME type used when storing this in data table. */ 4708 public static final String CONTENT_ITEM_TYPE = 4709 "vnd.android.cursor.item/postal-address_v2"; 4710 4711 /** 4712 * The MIME type of {@link #CONTENT_URI} providing a directory of 4713 * postal addresses. 4714 */ 4715 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2"; 4716 4717 /** 4718 * The content:// style URI for all data records of the 4719 * {@link StructuredPostal#CONTENT_ITEM_TYPE} MIME type. 4720 */ 4721 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 4722 "postals"); 4723 4724 public static final int TYPE_HOME = 1; 4725 public static final int TYPE_WORK = 2; 4726 public static final int TYPE_OTHER = 3; 4727 4728 /** 4729 * The full, unstructured postal address. <i>This field must be 4730 * consistent with any structured data.</i> 4731 * <p> 4732 * Type: TEXT 4733 */ 4734 public static final String FORMATTED_ADDRESS = DATA; 4735 4736 /** 4737 * Can be street, avenue, road, etc. This element also includes the 4738 * house number and room/apartment/flat/floor number. 4739 * <p> 4740 * Type: TEXT 4741 */ 4742 public static final String STREET = DATA4; 4743 4744 /** 4745 * Covers actual P.O. boxes, drawers, locked bags, etc. This is 4746 * usually but not always mutually exclusive with street. 4747 * <p> 4748 * Type: TEXT 4749 */ 4750 public static final String POBOX = DATA5; 4751 4752 /** 4753 * This is used to disambiguate a street address when a city 4754 * contains more than one street with the same name, or to specify a 4755 * small place whose mail is routed through a larger postal town. In 4756 * China it could be a county or a minor city. 4757 * <p> 4758 * Type: TEXT 4759 */ 4760 public static final String NEIGHBORHOOD = DATA6; 4761 4762 /** 4763 * Can be city, village, town, borough, etc. This is the postal town 4764 * and not necessarily the place of residence or place of business. 4765 * <p> 4766 * Type: TEXT 4767 */ 4768 public static final String CITY = DATA7; 4769 4770 /** 4771 * A state, province, county (in Ireland), Land (in Germany), 4772 * departement (in France), etc. 4773 * <p> 4774 * Type: TEXT 4775 */ 4776 public static final String REGION = DATA8; 4777 4778 /** 4779 * Postal code. Usually country-wide, but sometimes specific to the 4780 * city (e.g. "2" in "Dublin 2, Ireland" addresses). 4781 * <p> 4782 * Type: TEXT 4783 */ 4784 public static final String POSTCODE = DATA9; 4785 4786 /** 4787 * The name or code of the country. 4788 * <p> 4789 * Type: TEXT 4790 */ 4791 public static final String COUNTRY = DATA10; 4792 4793 /** 4794 * Return the string resource that best describes the given 4795 * {@link #TYPE}. Will always return a valid resource. 4796 */ 4797 public static final int getTypeLabelResource(int type) { 4798 switch (type) { 4799 case TYPE_HOME: return com.android.internal.R.string.postalTypeHome; 4800 case TYPE_WORK: return com.android.internal.R.string.postalTypeWork; 4801 case TYPE_OTHER: return com.android.internal.R.string.postalTypeOther; 4802 default: return com.android.internal.R.string.postalTypeCustom; 4803 } 4804 } 4805 4806 /** 4807 * Return a {@link CharSequence} that best describes the given type, 4808 * possibly substituting the given {@link #LABEL} value 4809 * for {@link #TYPE_CUSTOM}. 4810 */ 4811 public static final CharSequence getTypeLabel(Resources res, int type, 4812 CharSequence label) { 4813 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 4814 return label; 4815 } else { 4816 final int labelRes = getTypeLabelResource(type); 4817 return res.getText(labelRes); 4818 } 4819 } 4820 } 4821 4822 /** 4823 * <p> 4824 * A data kind representing an IM address 4825 * </p> 4826 * <p> 4827 * You can use all columns defined for {@link ContactsContract.Data} as 4828 * well as the following aliases. 4829 * </p> 4830 * <h2>Column aliases</h2> 4831 * <table class="jd-sumtable"> 4832 * <tr> 4833 * <th>Type</th> 4834 * <th>Alias</th><th colspan='2'>Data column</th> 4835 * </tr> 4836 * <tr> 4837 * <td>String</td> 4838 * <td>{@link #DATA}</td> 4839 * <td>{@link #DATA1}</td> 4840 * <td></td> 4841 * </tr> 4842 * <tr> 4843 * <td>int</td> 4844 * <td>{@link #TYPE}</td> 4845 * <td>{@link #DATA2}</td> 4846 * <td>Allowed values are: 4847 * <p> 4848 * <ul> 4849 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 4850 * <li>{@link #TYPE_HOME}</li> 4851 * <li>{@link #TYPE_WORK}</li> 4852 * <li>{@link #TYPE_OTHER}</li> 4853 * </ul> 4854 * </p> 4855 * </td> 4856 * </tr> 4857 * <tr> 4858 * <td>String</td> 4859 * <td>{@link #LABEL}</td> 4860 * <td>{@link #DATA3}</td> 4861 * <td></td> 4862 * </tr> 4863 * <tr> 4864 * <td>String</td> 4865 * <td>{@link #PROTOCOL}</td> 4866 * <td>{@link #DATA5}</td> 4867 * <td> 4868 * <p> 4869 * Allowed values: 4870 * <ul> 4871 * <li>{@link #PROTOCOL_CUSTOM}. Also provide the actual protocol name 4872 * as {@link #CUSTOM_PROTOCOL}.</li> 4873 * <li>{@link #PROTOCOL_AIM}</li> 4874 * <li>{@link #PROTOCOL_MSN}</li> 4875 * <li>{@link #PROTOCOL_YAHOO}</li> 4876 * <li>{@link #PROTOCOL_SKYPE}</li> 4877 * <li>{@link #PROTOCOL_QQ}</li> 4878 * <li>{@link #PROTOCOL_GOOGLE_TALK}</li> 4879 * <li>{@link #PROTOCOL_ICQ}</li> 4880 * <li>{@link #PROTOCOL_JABBER}</li> 4881 * <li>{@link #PROTOCOL_NETMEETING}</li> 4882 * </ul> 4883 * </p> 4884 * </td> 4885 * </tr> 4886 * <tr> 4887 * <td>String</td> 4888 * <td>{@link #CUSTOM_PROTOCOL}</td> 4889 * <td>{@link #DATA6}</td> 4890 * <td></td> 4891 * </tr> 4892 * </table> 4893 */ 4894 public static final class Im implements DataColumnsWithJoins, CommonColumns { 4895 /** 4896 * This utility class cannot be instantiated 4897 */ 4898 private Im() {} 4899 4900 /** MIME type used when storing this in data table. */ 4901 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im"; 4902 4903 public static final int TYPE_HOME = 1; 4904 public static final int TYPE_WORK = 2; 4905 public static final int TYPE_OTHER = 3; 4906 4907 /** 4908 * This column should be populated with one of the defined 4909 * constants, e.g. {@link #PROTOCOL_YAHOO}. If the value of this 4910 * column is {@link #PROTOCOL_CUSTOM}, the {@link #CUSTOM_PROTOCOL} 4911 * should contain the name of the custom protocol. 4912 */ 4913 public static final String PROTOCOL = DATA5; 4914 4915 public static final String CUSTOM_PROTOCOL = DATA6; 4916 4917 /* 4918 * The predefined IM protocol types. 4919 */ 4920 public static final int PROTOCOL_CUSTOM = -1; 4921 public static final int PROTOCOL_AIM = 0; 4922 public static final int PROTOCOL_MSN = 1; 4923 public static final int PROTOCOL_YAHOO = 2; 4924 public static final int PROTOCOL_SKYPE = 3; 4925 public static final int PROTOCOL_QQ = 4; 4926 public static final int PROTOCOL_GOOGLE_TALK = 5; 4927 public static final int PROTOCOL_ICQ = 6; 4928 public static final int PROTOCOL_JABBER = 7; 4929 public static final int PROTOCOL_NETMEETING = 8; 4930 4931 /** 4932 * Return the string resource that best describes the given 4933 * {@link #TYPE}. Will always return a valid resource. 4934 */ 4935 public static final int getTypeLabelResource(int type) { 4936 switch (type) { 4937 case TYPE_HOME: return com.android.internal.R.string.imTypeHome; 4938 case TYPE_WORK: return com.android.internal.R.string.imTypeWork; 4939 case TYPE_OTHER: return com.android.internal.R.string.imTypeOther; 4940 default: return com.android.internal.R.string.imTypeCustom; 4941 } 4942 } 4943 4944 /** 4945 * Return a {@link CharSequence} that best describes the given type, 4946 * possibly substituting the given {@link #LABEL} value 4947 * for {@link #TYPE_CUSTOM}. 4948 */ 4949 public static final CharSequence getTypeLabel(Resources res, int type, 4950 CharSequence label) { 4951 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 4952 return label; 4953 } else { 4954 final int labelRes = getTypeLabelResource(type); 4955 return res.getText(labelRes); 4956 } 4957 } 4958 4959 /** 4960 * Return the string resource that best describes the given 4961 * {@link #PROTOCOL}. Will always return a valid resource. 4962 */ 4963 public static final int getProtocolLabelResource(int type) { 4964 switch (type) { 4965 case PROTOCOL_AIM: return com.android.internal.R.string.imProtocolAim; 4966 case PROTOCOL_MSN: return com.android.internal.R.string.imProtocolMsn; 4967 case PROTOCOL_YAHOO: return com.android.internal.R.string.imProtocolYahoo; 4968 case PROTOCOL_SKYPE: return com.android.internal.R.string.imProtocolSkype; 4969 case PROTOCOL_QQ: return com.android.internal.R.string.imProtocolQq; 4970 case PROTOCOL_GOOGLE_TALK: return com.android.internal.R.string.imProtocolGoogleTalk; 4971 case PROTOCOL_ICQ: return com.android.internal.R.string.imProtocolIcq; 4972 case PROTOCOL_JABBER: return com.android.internal.R.string.imProtocolJabber; 4973 case PROTOCOL_NETMEETING: return com.android.internal.R.string.imProtocolNetMeeting; 4974 default: return com.android.internal.R.string.imProtocolCustom; 4975 } 4976 } 4977 4978 /** 4979 * Return a {@link CharSequence} that best describes the given 4980 * protocol, possibly substituting the given 4981 * {@link #CUSTOM_PROTOCOL} value for {@link #PROTOCOL_CUSTOM}. 4982 */ 4983 public static final CharSequence getProtocolLabel(Resources res, int type, 4984 CharSequence label) { 4985 if (type == PROTOCOL_CUSTOM && !TextUtils.isEmpty(label)) { 4986 return label; 4987 } else { 4988 final int labelRes = getProtocolLabelResource(type); 4989 return res.getText(labelRes); 4990 } 4991 } 4992 } 4993 4994 /** 4995 * <p> 4996 * A data kind representing an organization. 4997 * </p> 4998 * <p> 4999 * You can use all columns defined for {@link ContactsContract.Data} as 5000 * well as the following aliases. 5001 * </p> 5002 * <h2>Column aliases</h2> 5003 * <table class="jd-sumtable"> 5004 * <tr> 5005 * <th>Type</th> 5006 * <th>Alias</th><th colspan='2'>Data column</th> 5007 * </tr> 5008 * <tr> 5009 * <td>String</td> 5010 * <td>{@link #COMPANY}</td> 5011 * <td>{@link #DATA1}</td> 5012 * <td></td> 5013 * </tr> 5014 * <tr> 5015 * <td>int</td> 5016 * <td>{@link #TYPE}</td> 5017 * <td>{@link #DATA2}</td> 5018 * <td>Allowed values are: 5019 * <p> 5020 * <ul> 5021 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 5022 * <li>{@link #TYPE_WORK}</li> 5023 * <li>{@link #TYPE_OTHER}</li> 5024 * </ul> 5025 * </p> 5026 * </td> 5027 * </tr> 5028 * <tr> 5029 * <td>String</td> 5030 * <td>{@link #LABEL}</td> 5031 * <td>{@link #DATA3}</td> 5032 * <td></td> 5033 * </tr> 5034 * <tr> 5035 * <td>String</td> 5036 * <td>{@link #TITLE}</td> 5037 * <td>{@link #DATA4}</td> 5038 * <td></td> 5039 * </tr> 5040 * <tr> 5041 * <td>String</td> 5042 * <td>{@link #DEPARTMENT}</td> 5043 * <td>{@link #DATA5}</td> 5044 * <td></td> 5045 * </tr> 5046 * <tr> 5047 * <td>String</td> 5048 * <td>{@link #JOB_DESCRIPTION}</td> 5049 * <td>{@link #DATA6}</td> 5050 * <td></td> 5051 * </tr> 5052 * <tr> 5053 * <td>String</td> 5054 * <td>{@link #SYMBOL}</td> 5055 * <td>{@link #DATA7}</td> 5056 * <td></td> 5057 * </tr> 5058 * <tr> 5059 * <td>String</td> 5060 * <td>{@link #PHONETIC_NAME}</td> 5061 * <td>{@link #DATA8}</td> 5062 * <td></td> 5063 * </tr> 5064 * <tr> 5065 * <td>String</td> 5066 * <td>{@link #OFFICE_LOCATION}</td> 5067 * <td>{@link #DATA9}</td> 5068 * <td></td> 5069 * </tr> 5070 * <tr> 5071 * <td>String</td> 5072 * <td>PHONETIC_NAME_STYLE</td> 5073 * <td>{@link #DATA10}</td> 5074 * <td></td> 5075 * </tr> 5076 * </table> 5077 */ 5078 public static final class Organization implements DataColumnsWithJoins, CommonColumns { 5079 /** 5080 * This utility class cannot be instantiated 5081 */ 5082 private Organization() {} 5083 5084 /** MIME type used when storing this in data table. */ 5085 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization"; 5086 5087 public static final int TYPE_WORK = 1; 5088 public static final int TYPE_OTHER = 2; 5089 5090 /** 5091 * The company as the user entered it. 5092 * <P>Type: TEXT</P> 5093 */ 5094 public static final String COMPANY = DATA; 5095 5096 /** 5097 * The position title at this company as the user entered it. 5098 * <P>Type: TEXT</P> 5099 */ 5100 public static final String TITLE = DATA4; 5101 5102 /** 5103 * The department at this company as the user entered it. 5104 * <P>Type: TEXT</P> 5105 */ 5106 public static final String DEPARTMENT = DATA5; 5107 5108 /** 5109 * The job description at this company as the user entered it. 5110 * <P>Type: TEXT</P> 5111 */ 5112 public static final String JOB_DESCRIPTION = DATA6; 5113 5114 /** 5115 * The symbol of this company as the user entered it. 5116 * <P>Type: TEXT</P> 5117 */ 5118 public static final String SYMBOL = DATA7; 5119 5120 /** 5121 * The phonetic name of this company as the user entered it. 5122 * <P>Type: TEXT</P> 5123 */ 5124 public static final String PHONETIC_NAME = DATA8; 5125 5126 /** 5127 * The office location of this organization. 5128 * <P>Type: TEXT</P> 5129 */ 5130 public static final String OFFICE_LOCATION = DATA9; 5131 5132 /** 5133 * The alphabet used for capturing the phonetic name. 5134 * See {@link ContactsContract.PhoneticNameStyle}. 5135 * @hide 5136 */ 5137 public static final String PHONETIC_NAME_STYLE = DATA10; 5138 5139 /** 5140 * Return the string resource that best describes the given 5141 * {@link #TYPE}. Will always return a valid resource. 5142 */ 5143 public static final int getTypeLabelResource(int type) { 5144 switch (type) { 5145 case TYPE_WORK: return com.android.internal.R.string.orgTypeWork; 5146 case TYPE_OTHER: return com.android.internal.R.string.orgTypeOther; 5147 default: return com.android.internal.R.string.orgTypeCustom; 5148 } 5149 } 5150 5151 /** 5152 * Return a {@link CharSequence} that best describes the given type, 5153 * possibly substituting the given {@link #LABEL} value 5154 * for {@link #TYPE_CUSTOM}. 5155 */ 5156 public static final CharSequence getTypeLabel(Resources res, int type, 5157 CharSequence label) { 5158 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 5159 return label; 5160 } else { 5161 final int labelRes = getTypeLabelResource(type); 5162 return res.getText(labelRes); 5163 } 5164 } 5165 } 5166 5167 /** 5168 * <p> 5169 * A data kind representing a relation. 5170 * </p> 5171 * <p> 5172 * You can use all columns defined for {@link ContactsContract.Data} as 5173 * well as the following aliases. 5174 * </p> 5175 * <h2>Column aliases</h2> 5176 * <table class="jd-sumtable"> 5177 * <tr> 5178 * <th>Type</th> 5179 * <th>Alias</th><th colspan='2'>Data column</th> 5180 * </tr> 5181 * <tr> 5182 * <td>String</td> 5183 * <td>{@link #NAME}</td> 5184 * <td>{@link #DATA1}</td> 5185 * <td></td> 5186 * </tr> 5187 * <tr> 5188 * <td>int</td> 5189 * <td>{@link #TYPE}</td> 5190 * <td>{@link #DATA2}</td> 5191 * <td>Allowed values are: 5192 * <p> 5193 * <ul> 5194 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 5195 * <li>{@link #TYPE_ASSISTANT}</li> 5196 * <li>{@link #TYPE_BROTHER}</li> 5197 * <li>{@link #TYPE_CHILD}</li> 5198 * <li>{@link #TYPE_DOMESTIC_PARTNER}</li> 5199 * <li>{@link #TYPE_FATHER}</li> 5200 * <li>{@link #TYPE_FRIEND}</li> 5201 * <li>{@link #TYPE_MANAGER}</li> 5202 * <li>{@link #TYPE_MOTHER}</li> 5203 * <li>{@link #TYPE_PARENT}</li> 5204 * <li>{@link #TYPE_PARTNER}</li> 5205 * <li>{@link #TYPE_REFERRED_BY}</li> 5206 * <li>{@link #TYPE_RELATIVE}</li> 5207 * <li>{@link #TYPE_SISTER}</li> 5208 * <li>{@link #TYPE_SPOUSE}</li> 5209 * </ul> 5210 * </p> 5211 * </td> 5212 * </tr> 5213 * <tr> 5214 * <td>String</td> 5215 * <td>{@link #LABEL}</td> 5216 * <td>{@link #DATA3}</td> 5217 * <td></td> 5218 * </tr> 5219 * </table> 5220 */ 5221 public static final class Relation implements DataColumnsWithJoins, CommonColumns { 5222 /** 5223 * This utility class cannot be instantiated 5224 */ 5225 private Relation() {} 5226 5227 /** MIME type used when storing this in data table. */ 5228 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation"; 5229 5230 public static final int TYPE_ASSISTANT = 1; 5231 public static final int TYPE_BROTHER = 2; 5232 public static final int TYPE_CHILD = 3; 5233 public static final int TYPE_DOMESTIC_PARTNER = 4; 5234 public static final int TYPE_FATHER = 5; 5235 public static final int TYPE_FRIEND = 6; 5236 public static final int TYPE_MANAGER = 7; 5237 public static final int TYPE_MOTHER = 8; 5238 public static final int TYPE_PARENT = 9; 5239 public static final int TYPE_PARTNER = 10; 5240 public static final int TYPE_REFERRED_BY = 11; 5241 public static final int TYPE_RELATIVE = 12; 5242 public static final int TYPE_SISTER = 13; 5243 public static final int TYPE_SPOUSE = 14; 5244 5245 /** 5246 * The name of the relative as the user entered it. 5247 * <P>Type: TEXT</P> 5248 */ 5249 public static final String NAME = DATA; 5250 5251 /** 5252 * Return the string resource that best describes the given 5253 * {@link #TYPE}. Will always return a valid resource. 5254 */ 5255 public static final int getTypeLabelResource(int type) { 5256 switch (type) { 5257 case TYPE_ASSISTANT: return com.android.internal.R.string.relationTypeAssistant; 5258 case TYPE_BROTHER: return com.android.internal.R.string.relationTypeBrother; 5259 case TYPE_CHILD: return com.android.internal.R.string.relationTypeChild; 5260 case TYPE_DOMESTIC_PARTNER: 5261 return com.android.internal.R.string.relationTypeDomesticPartner; 5262 case TYPE_FATHER: return com.android.internal.R.string.relationTypeFather; 5263 case TYPE_FRIEND: return com.android.internal.R.string.relationTypeFriend; 5264 case TYPE_MANAGER: return com.android.internal.R.string.relationTypeManager; 5265 case TYPE_MOTHER: return com.android.internal.R.string.relationTypeMother; 5266 case TYPE_PARENT: return com.android.internal.R.string.relationTypeParent; 5267 case TYPE_PARTNER: return com.android.internal.R.string.relationTypePartner; 5268 case TYPE_REFERRED_BY: 5269 return com.android.internal.R.string.relationTypeReferredBy; 5270 case TYPE_RELATIVE: return com.android.internal.R.string.relationTypeRelative; 5271 case TYPE_SISTER: return com.android.internal.R.string.relationTypeSister; 5272 case TYPE_SPOUSE: return com.android.internal.R.string.relationTypeSpouse; 5273 default: return com.android.internal.R.string.orgTypeCustom; 5274 } 5275 } 5276 5277 /** 5278 * Return a {@link CharSequence} that best describes the given type, 5279 * possibly substituting the given {@link #LABEL} value 5280 * for {@link #TYPE_CUSTOM}. 5281 */ 5282 public static final CharSequence getTypeLabel(Resources res, int type, 5283 CharSequence label) { 5284 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 5285 return label; 5286 } else { 5287 final int labelRes = getTypeLabelResource(type); 5288 return res.getText(labelRes); 5289 } 5290 } 5291 } 5292 5293 /** 5294 * <p> 5295 * A data kind representing an event. 5296 * </p> 5297 * <p> 5298 * You can use all columns defined for {@link ContactsContract.Data} as 5299 * well as the following aliases. 5300 * </p> 5301 * <h2>Column aliases</h2> 5302 * <table class="jd-sumtable"> 5303 * <tr> 5304 * <th>Type</th> 5305 * <th>Alias</th><th colspan='2'>Data column</th> 5306 * </tr> 5307 * <tr> 5308 * <td>String</td> 5309 * <td>{@link #START_DATE}</td> 5310 * <td>{@link #DATA1}</td> 5311 * <td></td> 5312 * </tr> 5313 * <tr> 5314 * <td>int</td> 5315 * <td>{@link #TYPE}</td> 5316 * <td>{@link #DATA2}</td> 5317 * <td>Allowed values are: 5318 * <p> 5319 * <ul> 5320 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 5321 * <li>{@link #TYPE_ANNIVERSARY}</li> 5322 * <li>{@link #TYPE_OTHER}</li> 5323 * <li>{@link #TYPE_BIRTHDAY}</li> 5324 * </ul> 5325 * </p> 5326 * </td> 5327 * </tr> 5328 * <tr> 5329 * <td>String</td> 5330 * <td>{@link #LABEL}</td> 5331 * <td>{@link #DATA3}</td> 5332 * <td></td> 5333 * </tr> 5334 * </table> 5335 */ 5336 public static final class Event implements DataColumnsWithJoins, CommonColumns { 5337 /** 5338 * This utility class cannot be instantiated 5339 */ 5340 private Event() {} 5341 5342 /** MIME type used when storing this in data table. */ 5343 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event"; 5344 5345 public static final int TYPE_ANNIVERSARY = 1; 5346 public static final int TYPE_OTHER = 2; 5347 public static final int TYPE_BIRTHDAY = 3; 5348 5349 /** 5350 * The event start date as the user entered it. 5351 * <P>Type: TEXT</P> 5352 */ 5353 public static final String START_DATE = DATA; 5354 5355 /** 5356 * Return the string resource that best describes the given 5357 * {@link #TYPE}. Will always return a valid resource. 5358 */ 5359 public static int getTypeResource(Integer type) { 5360 if (type == null) { 5361 return com.android.internal.R.string.eventTypeOther; 5362 } 5363 switch (type) { 5364 case TYPE_ANNIVERSARY: 5365 return com.android.internal.R.string.eventTypeAnniversary; 5366 case TYPE_BIRTHDAY: return com.android.internal.R.string.eventTypeBirthday; 5367 case TYPE_OTHER: return com.android.internal.R.string.eventTypeOther; 5368 default: return com.android.internal.R.string.eventTypeCustom; 5369 } 5370 } 5371 } 5372 5373 /** 5374 * <p> 5375 * A data kind representing an photo for the contact. 5376 * </p> 5377 * <p> 5378 * Some sync adapters will choose to download photos in a separate 5379 * pass. A common pattern is to use columns {@link ContactsContract.Data#SYNC1} 5380 * through {@link ContactsContract.Data#SYNC4} to store temporary 5381 * data, e.g. the image URL or ID, state of download, server-side version 5382 * of the image. It is allowed for the {@link #PHOTO} to be null. 5383 * </p> 5384 * <p> 5385 * You can use all columns defined for {@link ContactsContract.Data} as 5386 * well as the following aliases. 5387 * </p> 5388 * <h2>Column aliases</h2> 5389 * <table class="jd-sumtable"> 5390 * <tr> 5391 * <th>Type</th> 5392 * <th>Alias</th><th colspan='2'>Data column</th> 5393 * </tr> 5394 * <tr> 5395 * <td>BLOB</td> 5396 * <td>{@link #PHOTO}</td> 5397 * <td>{@link #DATA15}</td> 5398 * <td>By convention, binary data is stored in DATA15.</td> 5399 * </tr> 5400 * </table> 5401 */ 5402 public static final class Photo implements DataColumnsWithJoins { 5403 /** 5404 * This utility class cannot be instantiated 5405 */ 5406 private Photo() {} 5407 5408 /** MIME type used when storing this in data table. */ 5409 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo"; 5410 5411 /** 5412 * Thumbnail photo of the raw contact. This is the raw bytes of an image 5413 * that could be inflated using {@link android.graphics.BitmapFactory}. 5414 * <p> 5415 * Type: BLOB 5416 */ 5417 public static final String PHOTO = DATA15; 5418 } 5419 5420 /** 5421 * <p> 5422 * Notes about the contact. 5423 * </p> 5424 * <p> 5425 * You can use all columns defined for {@link ContactsContract.Data} as 5426 * well as the following aliases. 5427 * </p> 5428 * <h2>Column aliases</h2> 5429 * <table class="jd-sumtable"> 5430 * <tr> 5431 * <th>Type</th> 5432 * <th>Alias</th><th colspan='2'>Data column</th> 5433 * </tr> 5434 * <tr> 5435 * <td>String</td> 5436 * <td>{@link #NOTE}</td> 5437 * <td>{@link #DATA1}</td> 5438 * <td></td> 5439 * </tr> 5440 * </table> 5441 */ 5442 public static final class Note implements DataColumnsWithJoins { 5443 /** 5444 * This utility class cannot be instantiated 5445 */ 5446 private Note() {} 5447 5448 /** MIME type used when storing this in data table. */ 5449 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note"; 5450 5451 /** 5452 * The note text. 5453 * <P>Type: TEXT</P> 5454 */ 5455 public static final String NOTE = DATA1; 5456 } 5457 5458 /** 5459 * <p> 5460 * Group Membership. 5461 * </p> 5462 * <p> 5463 * You can use all columns defined for {@link ContactsContract.Data} as 5464 * well as the following aliases. 5465 * </p> 5466 * <h2>Column aliases</h2> 5467 * <table class="jd-sumtable"> 5468 * <tr> 5469 * <th>Type</th> 5470 * <th>Alias</th><th colspan='2'>Data column</th> 5471 * </tr> 5472 * <tr> 5473 * <td>long</td> 5474 * <td>{@link #GROUP_ROW_ID}</td> 5475 * <td>{@link #DATA1}</td> 5476 * <td></td> 5477 * </tr> 5478 * <tr> 5479 * <td>String</td> 5480 * <td>{@link #GROUP_SOURCE_ID}</td> 5481 * <td>none</td> 5482 * <td> 5483 * <p> 5484 * The sourceid of the group that this group membership refers to. 5485 * Exactly one of this or {@link #GROUP_ROW_ID} must be set when 5486 * inserting a row. 5487 * </p> 5488 * <p> 5489 * If this field is specified, the provider will first try to 5490 * look up a group with this {@link Groups Groups.SOURCE_ID}. If such a group 5491 * is found, it will use the corresponding row id. If the group is not 5492 * found, it will create one. 5493 * </td> 5494 * </tr> 5495 * </table> 5496 */ 5497 public static final class GroupMembership implements DataColumnsWithJoins { 5498 /** 5499 * This utility class cannot be instantiated 5500 */ 5501 private GroupMembership() {} 5502 5503 /** MIME type used when storing this in data table. */ 5504 public static final String CONTENT_ITEM_TYPE = 5505 "vnd.android.cursor.item/group_membership"; 5506 5507 /** 5508 * The row id of the group that this group membership refers to. Exactly one of 5509 * this or {@link #GROUP_SOURCE_ID} must be set when inserting a row. 5510 * <P>Type: INTEGER</P> 5511 */ 5512 public static final String GROUP_ROW_ID = DATA1; 5513 5514 /** 5515 * The sourceid of the group that this group membership refers to. Exactly one of 5516 * this or {@link #GROUP_ROW_ID} must be set when inserting a row. 5517 * <P>Type: TEXT</P> 5518 */ 5519 public static final String GROUP_SOURCE_ID = "group_sourceid"; 5520 } 5521 5522 /** 5523 * <p> 5524 * A data kind representing a website related to the contact. 5525 * </p> 5526 * <p> 5527 * You can use all columns defined for {@link ContactsContract.Data} as 5528 * well as the following aliases. 5529 * </p> 5530 * <h2>Column aliases</h2> 5531 * <table class="jd-sumtable"> 5532 * <tr> 5533 * <th>Type</th> 5534 * <th>Alias</th><th colspan='2'>Data column</th> 5535 * </tr> 5536 * <tr> 5537 * <td>String</td> 5538 * <td>{@link #URL}</td> 5539 * <td>{@link #DATA1}</td> 5540 * <td></td> 5541 * </tr> 5542 * <tr> 5543 * <td>int</td> 5544 * <td>{@link #TYPE}</td> 5545 * <td>{@link #DATA2}</td> 5546 * <td>Allowed values are: 5547 * <p> 5548 * <ul> 5549 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 5550 * <li>{@link #TYPE_HOMEPAGE}</li> 5551 * <li>{@link #TYPE_BLOG}</li> 5552 * <li>{@link #TYPE_PROFILE}</li> 5553 * <li>{@link #TYPE_HOME}</li> 5554 * <li>{@link #TYPE_WORK}</li> 5555 * <li>{@link #TYPE_FTP}</li> 5556 * <li>{@link #TYPE_OTHER}</li> 5557 * </ul> 5558 * </p> 5559 * </td> 5560 * </tr> 5561 * <tr> 5562 * <td>String</td> 5563 * <td>{@link #LABEL}</td> 5564 * <td>{@link #DATA3}</td> 5565 * <td></td> 5566 * </tr> 5567 * </table> 5568 */ 5569 public static final class Website implements DataColumnsWithJoins, CommonColumns { 5570 /** 5571 * This utility class cannot be instantiated 5572 */ 5573 private Website() {} 5574 5575 /** MIME type used when storing this in data table. */ 5576 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website"; 5577 5578 public static final int TYPE_HOMEPAGE = 1; 5579 public static final int TYPE_BLOG = 2; 5580 public static final int TYPE_PROFILE = 3; 5581 public static final int TYPE_HOME = 4; 5582 public static final int TYPE_WORK = 5; 5583 public static final int TYPE_FTP = 6; 5584 public static final int TYPE_OTHER = 7; 5585 5586 /** 5587 * The website URL string. 5588 * <P>Type: TEXT</P> 5589 */ 5590 public static final String URL = DATA; 5591 } 5592 5593 /** 5594 * <p> 5595 * A data kind representing a SIP address for the contact. 5596 * </p> 5597 * <p> 5598 * You can use all columns defined for {@link ContactsContract.Data} as 5599 * well as the following aliases. 5600 * </p> 5601 * <h2>Column aliases</h2> 5602 * <table class="jd-sumtable"> 5603 * <tr> 5604 * <th>Type</th> 5605 * <th>Alias</th><th colspan='2'>Data column</th> 5606 * </tr> 5607 * <tr> 5608 * <td>String</td> 5609 * <td>{@link #SIP_ADDRESS}</td> 5610 * <td>{@link #DATA1}</td> 5611 * <td></td> 5612 * </tr> 5613 * <tr> 5614 * <td>int</td> 5615 * <td>{@link #TYPE}</td> 5616 * <td>{@link #DATA2}</td> 5617 * <td>Allowed values are: 5618 * <p> 5619 * <ul> 5620 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 5621 * <li>{@link #TYPE_HOME}</li> 5622 * <li>{@link #TYPE_WORK}</li> 5623 * <li>{@link #TYPE_OTHER}</li> 5624 * </ul> 5625 * </p> 5626 * </td> 5627 * </tr> 5628 * <tr> 5629 * <td>String</td> 5630 * <td>{@link #LABEL}</td> 5631 * <td>{@link #DATA3}</td> 5632 * <td></td> 5633 * </tr> 5634 * </table> 5635 */ 5636 public static final class SipAddress implements DataColumnsWithJoins, CommonColumns { 5637 /** 5638 * This utility class cannot be instantiated 5639 */ 5640 private SipAddress() {} 5641 5642 /** MIME type used when storing this in data table. */ 5643 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address"; 5644 5645 public static final int TYPE_HOME = 1; 5646 public static final int TYPE_WORK = 2; 5647 public static final int TYPE_OTHER = 3; 5648 5649 /** 5650 * The SIP address. 5651 * <P>Type: TEXT</P> 5652 */ 5653 public static final String SIP_ADDRESS = DATA1; 5654 // ...and TYPE and LABEL come from the CommonColumns interface. 5655 5656 /** 5657 * Return the string resource that best describes the given 5658 * {@link #TYPE}. Will always return a valid resource. 5659 */ 5660 public static final int getTypeLabelResource(int type) { 5661 switch (type) { 5662 case TYPE_HOME: return com.android.internal.R.string.sipAddressTypeHome; 5663 case TYPE_WORK: return com.android.internal.R.string.sipAddressTypeWork; 5664 case TYPE_OTHER: return com.android.internal.R.string.sipAddressTypeOther; 5665 default: return com.android.internal.R.string.sipAddressTypeCustom; 5666 } 5667 } 5668 5669 /** 5670 * Return a {@link CharSequence} that best describes the given type, 5671 * possibly substituting the given {@link #LABEL} value 5672 * for {@link #TYPE_CUSTOM}. 5673 */ 5674 public static final CharSequence getTypeLabel(Resources res, int type, 5675 CharSequence label) { 5676 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 5677 return label; 5678 } else { 5679 final int labelRes = getTypeLabelResource(type); 5680 return res.getText(labelRes); 5681 } 5682 } 5683 } 5684 } 5685 5686 /** 5687 * @see Groups 5688 */ 5689 protected interface GroupsColumns { 5690 /** 5691 * The display title of this group. 5692 * <p> 5693 * Type: TEXT 5694 */ 5695 public static final String TITLE = "title"; 5696 5697 /** 5698 * The package name to use when creating {@link Resources} objects for 5699 * this group. This value is only designed for use when building user 5700 * interfaces, and should not be used to infer the owner. 5701 * 5702 * @hide 5703 */ 5704 public static final String RES_PACKAGE = "res_package"; 5705 5706 /** 5707 * The display title of this group to load as a resource from 5708 * {@link #RES_PACKAGE}, which may be localized. 5709 * <P>Type: TEXT</P> 5710 * 5711 * @hide 5712 */ 5713 public static final String TITLE_RES = "title_res"; 5714 5715 /** 5716 * Notes about the group. 5717 * <p> 5718 * Type: TEXT 5719 */ 5720 public static final String NOTES = "notes"; 5721 5722 /** 5723 * The ID of this group if it is a System Group, i.e. a group that has a special meaning 5724 * to the sync adapter, null otherwise. 5725 * <P>Type: TEXT</P> 5726 */ 5727 public static final String SYSTEM_ID = "system_id"; 5728 5729 /** 5730 * The total number of {@link Contacts} that have 5731 * {@link CommonDataKinds.GroupMembership} in this group. Read-only value that is only 5732 * present when querying {@link Groups#CONTENT_SUMMARY_URI}. 5733 * <p> 5734 * Type: INTEGER 5735 */ 5736 public static final String SUMMARY_COUNT = "summ_count"; 5737 5738 /** 5739 * The total number of {@link Contacts} that have both 5740 * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers. 5741 * Read-only value that is only present when querying 5742 * {@link Groups#CONTENT_SUMMARY_URI}. 5743 * <p> 5744 * Type: INTEGER 5745 */ 5746 public static final String SUMMARY_WITH_PHONES = "summ_phones"; 5747 5748 /** 5749 * Flag indicating if the contacts belonging to this group should be 5750 * visible in any user interface. 5751 * <p> 5752 * Type: INTEGER (boolean) 5753 */ 5754 public static final String GROUP_VISIBLE = "group_visible"; 5755 5756 /** 5757 * The "deleted" flag: "0" by default, "1" if the row has been marked 5758 * for deletion. When {@link android.content.ContentResolver#delete} is 5759 * called on a group, it is marked for deletion. The sync adaptor 5760 * deletes the group on the server and then calls ContactResolver.delete 5761 * once more, this time setting the the 5762 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to 5763 * finalize the data removal. 5764 * <P>Type: INTEGER</P> 5765 */ 5766 public static final String DELETED = "deleted"; 5767 5768 /** 5769 * Whether this group should be synced if the SYNC_EVERYTHING settings 5770 * is false for this group's account. 5771 * <p> 5772 * Type: INTEGER (boolean) 5773 */ 5774 public static final String SHOULD_SYNC = "should_sync"; 5775 5776 /** 5777 * Any newly created contacts will automatically be added to groups that have this 5778 * flag set to true. 5779 * <p> 5780 * Type: INTEGER (boolean) 5781 */ 5782 public static final String AUTO_ADD = "auto_add"; 5783 5784 /** 5785 * When a contacts is marked as a favorites it will be automatically added 5786 * to the groups that have this flag set, and when it is removed from favorites 5787 * it will be removed from these groups. 5788 * <p> 5789 * Type: INTEGER (boolean) 5790 */ 5791 public static final String FAVORITES = "favorites"; 5792 5793 /** 5794 * The "read-only" flag: "0" by default, "1" if the row cannot be modified or 5795 * deleted except by a sync adapter. See {@link ContactsContract#CALLER_IS_SYNCADAPTER}. 5796 * <P>Type: INTEGER</P> 5797 */ 5798 public static final String GROUP_IS_READ_ONLY = "group_is_read_only"; 5799 } 5800 5801 /** 5802 * Constants for the groups table. Only per-account groups are supported. 5803 * <h2>Columns</h2> 5804 * <table class="jd-sumtable"> 5805 * <tr> 5806 * <th colspan='4'>Groups</th> 5807 * </tr> 5808 * <tr> 5809 * <td>long</td> 5810 * <td>{@link #_ID}</td> 5811 * <td>read-only</td> 5812 * <td>Row ID. Sync adapter should try to preserve row IDs during updates. 5813 * In other words, it would be a really bad idea to delete and reinsert a 5814 * group. A sync adapter should always do an update instead.</td> 5815 * </tr> 5816 * <tr> 5817 * <td>String</td> 5818 * <td>{@link #TITLE}</td> 5819 * <td>read/write</td> 5820 * <td>The display title of this group.</td> 5821 * </tr> 5822 * <tr> 5823 * <td>String</td> 5824 * <td>{@link #NOTES}</td> 5825 * <td>read/write</td> 5826 * <td>Notes about the group.</td> 5827 * </tr> 5828 * <tr> 5829 * <td>String</td> 5830 * <td>{@link #SYSTEM_ID}</td> 5831 * <td>read/write</td> 5832 * <td>The ID of this group if it is a System Group, i.e. a group that has a 5833 * special meaning to the sync adapter, null otherwise.</td> 5834 * </tr> 5835 * <tr> 5836 * <td>int</td> 5837 * <td>{@link #SUMMARY_COUNT}</td> 5838 * <td>read-only</td> 5839 * <td>The total number of {@link Contacts} that have 5840 * {@link CommonDataKinds.GroupMembership} in this group. Read-only value 5841 * that is only present when querying {@link Groups#CONTENT_SUMMARY_URI}.</td> 5842 * </tr> 5843 * <tr> 5844 * <td>int</td> 5845 * <td>{@link #SUMMARY_WITH_PHONES}</td> 5846 * <td>read-only</td> 5847 * <td>The total number of {@link Contacts} that have both 5848 * {@link CommonDataKinds.GroupMembership} in this group, and also have 5849 * phone numbers. Read-only value that is only present when querying 5850 * {@link Groups#CONTENT_SUMMARY_URI}.</td> 5851 * </tr> 5852 * <tr> 5853 * <td>int</td> 5854 * <td>{@link #GROUP_VISIBLE}</td> 5855 * <td>read-only</td> 5856 * <td>Flag indicating if the contacts belonging to this group should be 5857 * visible in any user interface. Allowed values: 0 and 1.</td> 5858 * </tr> 5859 * <tr> 5860 * <td>int</td> 5861 * <td>{@link #DELETED}</td> 5862 * <td>read/write</td> 5863 * <td>The "deleted" flag: "0" by default, "1" if the row has been marked 5864 * for deletion. When {@link android.content.ContentResolver#delete} is 5865 * called on a group, it is marked for deletion. The sync adaptor deletes 5866 * the group on the server and then calls ContactResolver.delete once more, 5867 * this time setting the the {@link ContactsContract#CALLER_IS_SYNCADAPTER} 5868 * query parameter to finalize the data removal.</td> 5869 * </tr> 5870 * <tr> 5871 * <td>int</td> 5872 * <td>{@link #SHOULD_SYNC}</td> 5873 * <td>read/write</td> 5874 * <td>Whether this group should be synced if the SYNC_EVERYTHING settings 5875 * is false for this group's account.</td> 5876 * </tr> 5877 * </table> 5878 */ 5879 public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns { 5880 /** 5881 * This utility class cannot be instantiated 5882 */ 5883 private Groups() { 5884 } 5885 5886 /** 5887 * The content:// style URI for this table 5888 */ 5889 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "groups"); 5890 5891 /** 5892 * The content:// style URI for this table joined with details data from 5893 * {@link ContactsContract.Data}. 5894 */ 5895 public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI, 5896 "groups_summary"); 5897 5898 /** 5899 * The MIME type of a directory of groups. 5900 */ 5901 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/group"; 5902 5903 /** 5904 * The MIME type of a single group. 5905 */ 5906 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group"; 5907 5908 public static EntityIterator newEntityIterator(Cursor cursor) { 5909 return new EntityIteratorImpl(cursor); 5910 } 5911 5912 private static class EntityIteratorImpl extends CursorEntityIterator { 5913 public EntityIteratorImpl(Cursor cursor) { 5914 super(cursor); 5915 } 5916 5917 @Override 5918 public Entity getEntityAndIncrementCursor(Cursor cursor) throws RemoteException { 5919 // we expect the cursor is already at the row we need to read from 5920 final ContentValues values = new ContentValues(); 5921 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, _ID); 5922 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_NAME); 5923 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_TYPE); 5924 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DIRTY); 5925 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, VERSION); 5926 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SOURCE_ID); 5927 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, RES_PACKAGE); 5928 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE); 5929 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE_RES); 5930 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, GROUP_VISIBLE); 5931 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC1); 5932 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC2); 5933 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC3); 5934 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC4); 5935 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYSTEM_ID); 5936 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DELETED); 5937 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, NOTES); 5938 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SHOULD_SYNC); 5939 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, FAVORITES); 5940 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, AUTO_ADD); 5941 cursor.moveToNext(); 5942 return new Entity(values); 5943 } 5944 } 5945 } 5946 5947 /** 5948 * <p> 5949 * Constants for the contact aggregation exceptions table, which contains 5950 * aggregation rules overriding those used by automatic aggregation. This 5951 * type only supports query and update. Neither insert nor delete are 5952 * supported. 5953 * </p> 5954 * <h2>Columns</h2> 5955 * <table class="jd-sumtable"> 5956 * <tr> 5957 * <th colspan='4'>AggregationExceptions</th> 5958 * </tr> 5959 * <tr> 5960 * <td>int</td> 5961 * <td>{@link #TYPE}</td> 5962 * <td>read/write</td> 5963 * <td>The type of exception: {@link #TYPE_KEEP_TOGETHER}, 5964 * {@link #TYPE_KEEP_SEPARATE} or {@link #TYPE_AUTOMATIC}.</td> 5965 * </tr> 5966 * <tr> 5967 * <td>long</td> 5968 * <td>{@link #RAW_CONTACT_ID1}</td> 5969 * <td>read/write</td> 5970 * <td>A reference to the {@link RawContacts#_ID} of the raw contact that 5971 * the rule applies to.</td> 5972 * </tr> 5973 * <tr> 5974 * <td>long</td> 5975 * <td>{@link #RAW_CONTACT_ID2}</td> 5976 * <td>read/write</td> 5977 * <td>A reference to the other {@link RawContacts#_ID} of the raw contact 5978 * that the rule applies to.</td> 5979 * </tr> 5980 * </table> 5981 */ 5982 public static final class AggregationExceptions implements BaseColumns { 5983 /** 5984 * This utility class cannot be instantiated 5985 */ 5986 private AggregationExceptions() {} 5987 5988 /** 5989 * The content:// style URI for this table 5990 */ 5991 public static final Uri CONTENT_URI = 5992 Uri.withAppendedPath(AUTHORITY_URI, "aggregation_exceptions"); 5993 5994 /** 5995 * The MIME type of {@link #CONTENT_URI} providing a directory of data. 5996 */ 5997 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception"; 5998 5999 /** 6000 * The MIME type of a {@link #CONTENT_URI} subdirectory of an aggregation exception 6001 */ 6002 public static final String CONTENT_ITEM_TYPE = 6003 "vnd.android.cursor.item/aggregation_exception"; 6004 6005 /** 6006 * The type of exception: {@link #TYPE_KEEP_TOGETHER}, {@link #TYPE_KEEP_SEPARATE} or 6007 * {@link #TYPE_AUTOMATIC}. 6008 * 6009 * <P>Type: INTEGER</P> 6010 */ 6011 public static final String TYPE = "type"; 6012 6013 /** 6014 * Allows the provider to automatically decide whether the specified raw contacts should 6015 * be included in the same aggregate contact or not. 6016 */ 6017 public static final int TYPE_AUTOMATIC = 0; 6018 6019 /** 6020 * Makes sure that the specified raw contacts are included in the same 6021 * aggregate contact. 6022 */ 6023 public static final int TYPE_KEEP_TOGETHER = 1; 6024 6025 /** 6026 * Makes sure that the specified raw contacts are NOT included in the same 6027 * aggregate contact. 6028 */ 6029 public static final int TYPE_KEEP_SEPARATE = 2; 6030 6031 /** 6032 * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to. 6033 */ 6034 public static final String RAW_CONTACT_ID1 = "raw_contact_id1"; 6035 6036 /** 6037 * A reference to the other {@link RawContacts#_ID} of the raw contact that the rule 6038 * applies to. 6039 */ 6040 public static final String RAW_CONTACT_ID2 = "raw_contact_id2"; 6041 } 6042 6043 /** 6044 * @see Settings 6045 */ 6046 protected interface SettingsColumns { 6047 /** 6048 * The name of the account instance to which this row belongs. 6049 * <P>Type: TEXT</P> 6050 */ 6051 public static final String ACCOUNT_NAME = "account_name"; 6052 6053 /** 6054 * The type of account to which this row belongs, which when paired with 6055 * {@link #ACCOUNT_NAME} identifies a specific account. 6056 * <P>Type: TEXT</P> 6057 */ 6058 public static final String ACCOUNT_TYPE = "account_type"; 6059 6060 /** 6061 * Depending on the mode defined by the sync-adapter, this flag controls 6062 * the top-level sync behavior for this data source. 6063 * <p> 6064 * Type: INTEGER (boolean) 6065 */ 6066 public static final String SHOULD_SYNC = "should_sync"; 6067 6068 /** 6069 * Flag indicating if contacts without any {@link CommonDataKinds.GroupMembership} 6070 * entries should be visible in any user interface. 6071 * <p> 6072 * Type: INTEGER (boolean) 6073 */ 6074 public static final String UNGROUPED_VISIBLE = "ungrouped_visible"; 6075 6076 /** 6077 * Read-only flag indicating if this {@link #SHOULD_SYNC} or any 6078 * {@link Groups#SHOULD_SYNC} under this account have been marked as 6079 * unsynced. 6080 */ 6081 public static final String ANY_UNSYNCED = "any_unsynced"; 6082 6083 /** 6084 * Read-only count of {@link Contacts} from a specific source that have 6085 * no {@link CommonDataKinds.GroupMembership} entries. 6086 * <p> 6087 * Type: INTEGER 6088 */ 6089 public static final String UNGROUPED_COUNT = "summ_count"; 6090 6091 /** 6092 * Read-only count of {@link Contacts} from a specific source that have 6093 * no {@link CommonDataKinds.GroupMembership} entries, and also have phone numbers. 6094 * <p> 6095 * Type: INTEGER 6096 */ 6097 public static final String UNGROUPED_WITH_PHONES = "summ_phones"; 6098 } 6099 6100 /** 6101 * <p> 6102 * Contacts-specific settings for various {@link Account}'s. 6103 * </p> 6104 * <h2>Columns</h2> 6105 * <table class="jd-sumtable"> 6106 * <tr> 6107 * <th colspan='4'>Settings</th> 6108 * </tr> 6109 * <tr> 6110 * <td>String</td> 6111 * <td>{@link #ACCOUNT_NAME}</td> 6112 * <td>read/write-once</td> 6113 * <td>The name of the account instance to which this row belongs.</td> 6114 * </tr> 6115 * <tr> 6116 * <td>String</td> 6117 * <td>{@link #ACCOUNT_TYPE}</td> 6118 * <td>read/write-once</td> 6119 * <td>The type of account to which this row belongs, which when paired with 6120 * {@link #ACCOUNT_NAME} identifies a specific account.</td> 6121 * </tr> 6122 * <tr> 6123 * <td>int</td> 6124 * <td>{@link #SHOULD_SYNC}</td> 6125 * <td>read/write</td> 6126 * <td>Depending on the mode defined by the sync-adapter, this flag controls 6127 * the top-level sync behavior for this data source.</td> 6128 * </tr> 6129 * <tr> 6130 * <td>int</td> 6131 * <td>{@link #UNGROUPED_VISIBLE}</td> 6132 * <td>read/write</td> 6133 * <td>Flag indicating if contacts without any 6134 * {@link CommonDataKinds.GroupMembership} entries should be visible in any 6135 * user interface.</td> 6136 * </tr> 6137 * <tr> 6138 * <td>int</td> 6139 * <td>{@link #ANY_UNSYNCED}</td> 6140 * <td>read-only</td> 6141 * <td>Read-only flag indicating if this {@link #SHOULD_SYNC} or any 6142 * {@link Groups#SHOULD_SYNC} under this account have been marked as 6143 * unsynced.</td> 6144 * </tr> 6145 * <tr> 6146 * <td>int</td> 6147 * <td>{@link #UNGROUPED_COUNT}</td> 6148 * <td>read-only</td> 6149 * <td>Read-only count of {@link Contacts} from a specific source that have 6150 * no {@link CommonDataKinds.GroupMembership} entries.</td> 6151 * </tr> 6152 * <tr> 6153 * <td>int</td> 6154 * <td>{@link #UNGROUPED_WITH_PHONES}</td> 6155 * <td>read-only</td> 6156 * <td>Read-only count of {@link Contacts} from a specific source that have 6157 * no {@link CommonDataKinds.GroupMembership} entries, and also have phone 6158 * numbers.</td> 6159 * </tr> 6160 * </table> 6161 */ 6162 public static final class Settings implements SettingsColumns { 6163 /** 6164 * This utility class cannot be instantiated 6165 */ 6166 private Settings() { 6167 } 6168 6169 /** 6170 * The content:// style URI for this table 6171 */ 6172 public static final Uri CONTENT_URI = 6173 Uri.withAppendedPath(AUTHORITY_URI, "settings"); 6174 6175 /** 6176 * The MIME-type of {@link #CONTENT_URI} providing a directory of 6177 * settings. 6178 */ 6179 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting"; 6180 6181 /** 6182 * The MIME-type of {@link #CONTENT_URI} providing a single setting. 6183 */ 6184 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting"; 6185 } 6186 6187 /** 6188 * Private API for inquiring about the general status of the provider. 6189 * 6190 * @hide 6191 */ 6192 public static final class ProviderStatus { 6193 6194 /** 6195 * Not instantiable. 6196 */ 6197 private ProviderStatus() { 6198 } 6199 6200 /** 6201 * The content:// style URI for this table. Requests to this URI can be 6202 * performed on the UI thread because they are always unblocking. 6203 * 6204 * @hide 6205 */ 6206 public static final Uri CONTENT_URI = 6207 Uri.withAppendedPath(AUTHORITY_URI, "provider_status"); 6208 6209 /** 6210 * The MIME-type of {@link #CONTENT_URI} providing a directory of 6211 * settings. 6212 * 6213 * @hide 6214 */ 6215 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/provider_status"; 6216 6217 /** 6218 * An integer representing the current status of the provider. 6219 * 6220 * @hide 6221 */ 6222 public static final String STATUS = "status"; 6223 6224 /** 6225 * Default status of the provider. 6226 * 6227 * @hide 6228 */ 6229 public static final int STATUS_NORMAL = 0; 6230 6231 /** 6232 * The status used when the provider is in the process of upgrading. Contacts 6233 * are temporarily unaccessible. 6234 * 6235 * @hide 6236 */ 6237 public static final int STATUS_UPGRADING = 1; 6238 6239 /** 6240 * The status used if the provider was in the process of upgrading but ran 6241 * out of storage. The DATA1 column will contain the estimated amount of 6242 * storage required (in bytes). Update status to STATUS_NORMAL to force 6243 * the provider to retry the upgrade. 6244 * 6245 * @hide 6246 */ 6247 public static final int STATUS_UPGRADE_OUT_OF_MEMORY = 2; 6248 6249 /** 6250 * The status used during a locale change. 6251 * 6252 * @hide 6253 */ 6254 public static final int STATUS_CHANGING_LOCALE = 3; 6255 6256 /** 6257 * The status that indicates that there are no accounts and no contacts 6258 * on the device. 6259 * 6260 * @hide 6261 */ 6262 public static final int STATUS_NO_ACCOUNTS_NO_CONTACTS = 4; 6263 6264 /** 6265 * Additional data associated with the status. 6266 * 6267 * @hide 6268 */ 6269 public static final String DATA1 = "data1"; 6270 } 6271 6272 /** 6273 * <p> 6274 * API allowing applications to send usage information for each {@link Data} row to the 6275 * Contacts Provider. 6276 * </p> 6277 * <p> 6278 * With the feedback, Contacts Provider may return more contextually appropriate results for 6279 * Data listing, typically supplied with 6280 * {@link ContactsContract.Contacts#CONTENT_FILTER_URI}, 6281 * {@link ContactsContract.CommonDataKinds.Email#CONTENT_FILTER_URI}, 6282 * {@link ContactsContract.CommonDataKinds.Phone#CONTENT_FILTER_URI}, and users can benefit 6283 * from better ranked (sorted) lists in applications that show auto-complete list. 6284 * </p> 6285 * <p> 6286 * There is no guarantee for how this feedback is used, or even whether it is used at all. 6287 * The ranking algorithm will make best efforts to use the feedback data, but the exact 6288 * implementation, the storage data structures as well as the resulting sort order is device 6289 * and version specific and can change over time. 6290 * </p> 6291 * <p> 6292 * When updating usage information, users of this API need to use 6293 * {@link ContentResolver#update(Uri, ContentValues, String, String[])} with a Uri constructed 6294 * from {@link DataUsageFeedback#FEEDBACK_URI}. The Uri must contain one or more data id(s) as 6295 * its last path. They also need to append a query parameter to the Uri, to specify the type of 6296 * the communication, which enables the Contacts Provider to differentiate between kinds of 6297 * interactions using the same contact data field (for example a phone number can be used to 6298 * make phone calls or send SMS). 6299 * </p> 6300 * <p> 6301 * Selection and selectionArgs are ignored and must be set to null. To get data ids, 6302 * you may need to call {@link ContentResolver#query(Uri, String[], String, String[], String)} 6303 * toward {@link Data#CONTENT_URI}. 6304 * </p> 6305 * <p> 6306 * {@link ContentResolver#update(Uri, ContentValues, String, String[])} returns a positive 6307 * integer when successful, and returns 0 if no contact with that id was found. 6308 * </p> 6309 * <p> 6310 * Example: 6311 * <pre> 6312 * Uri uri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 6313 * .appendPath(TextUtils.join(",", dataIds)) 6314 * .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, 6315 * DataUsageFeedback.USAGE_TYPE_CALL) 6316 * .build(); 6317 * boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0; 6318 * </pre> 6319 * </p> 6320 * @hide 6321 */ 6322 public static final class DataUsageFeedback { 6323 6324 /** 6325 * The content:// style URI for sending usage feedback. 6326 * Must be used with {@link ContentResolver#update(Uri, ContentValues, String, String[])}. 6327 */ 6328 public static final Uri FEEDBACK_URI = 6329 Uri.withAppendedPath(Data.CONTENT_URI, "usagefeedback"); 6330 6331 /** 6332 * <p> 6333 * Name for query parameter specifying the type of data usage. 6334 * </p> 6335 */ 6336 public static final String USAGE_TYPE = "type"; 6337 6338 /** 6339 * <p> 6340 * Type of usage for voice interaction, which includes phone call, voice chat, and 6341 * video chat. 6342 * </p> 6343 */ 6344 public static final String USAGE_TYPE_CALL = "call"; 6345 6346 /** 6347 * <p> 6348 * Type of usage for text interaction involving longer messages, which includes email. 6349 * </p> 6350 */ 6351 public static final String USAGE_TYPE_LONG_TEXT = "long_text"; 6352 6353 /** 6354 * <p> 6355 * Type of usage for text interaction involving shorter messages, which includes SMS, 6356 * text chat with email addresses. 6357 * </p> 6358 */ 6359 public static final String USAGE_TYPE_SHORT_TEXT = "short_text"; 6360 } 6361 6362 /** 6363 * Helper methods to display QuickContact dialogs that allow users to pivot on 6364 * a specific {@link Contacts} entry. 6365 */ 6366 public static final class QuickContact { 6367 /** 6368 * Action used to trigger person pivot dialog. 6369 * @hide 6370 */ 6371 public static final String ACTION_QUICK_CONTACT = 6372 "com.android.contacts.action.QUICK_CONTACT"; 6373 6374 /** 6375 * Extra used to specify pivot dialog location in screen coordinates. 6376 * @deprecated Use {@link Intent#setSourceBounds(Rect)} instead. 6377 * @hide 6378 */ 6379 @Deprecated 6380 public static final String EXTRA_TARGET_RECT = "target_rect"; 6381 6382 /** 6383 * Extra used to specify size of pivot dialog. 6384 * @hide 6385 */ 6386 public static final String EXTRA_MODE = "mode"; 6387 6388 /** 6389 * Extra used to indicate a list of specific MIME-types to exclude and 6390 * not display. Stored as a {@link String} array. 6391 * @hide 6392 */ 6393 public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes"; 6394 6395 /** 6396 * Small QuickContact mode, usually presented with minimal actions. 6397 */ 6398 public static final int MODE_SMALL = 1; 6399 6400 /** 6401 * Medium QuickContact mode, includes actions and light summary describing 6402 * the {@link Contacts} entry being shown. This may include social 6403 * status and presence details. 6404 */ 6405 public static final int MODE_MEDIUM = 2; 6406 6407 /** 6408 * Large QuickContact mode, includes actions and larger, card-like summary 6409 * of the {@link Contacts} entry being shown. This may include detailed 6410 * information, such as a photo. 6411 */ 6412 public static final int MODE_LARGE = 3; 6413 6414 /** 6415 * Trigger a dialog that lists the various methods of interacting with 6416 * the requested {@link Contacts} entry. This may be based on available 6417 * {@link ContactsContract.Data} rows under that contact, and may also 6418 * include social status and presence details. 6419 * 6420 * @param context The parent {@link Context} that may be used as the 6421 * parent for this dialog. 6422 * @param target Specific {@link View} from your layout that this dialog 6423 * should be centered around. In particular, if the dialog 6424 * has a "callout" arrow, it will be pointed and centered 6425 * around this {@link View}. 6426 * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 6427 * {@link Uri} that describes a specific contact to feature 6428 * in this dialog. 6429 * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or 6430 * {@link #MODE_LARGE}, indicating the desired dialog size, 6431 * when supported. 6432 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 6433 * to exclude when showing this dialog. For example, when 6434 * already viewing the contact details card, this can be used 6435 * to omit the details entry from the dialog. 6436 */ 6437 public static void showQuickContact(Context context, View target, Uri lookupUri, int mode, 6438 String[] excludeMimes) { 6439 // Find location and bounds of target view, adjusting based on the 6440 // assumed local density. 6441 final float appScale = context.getResources().getCompatibilityInfo().applicationScale; 6442 final int[] pos = new int[2]; 6443 target.getLocationOnScreen(pos); 6444 6445 final Rect rect = new Rect(); 6446 rect.left = (int) (pos[0] * appScale + 0.5f); 6447 rect.top = (int) (pos[1] * appScale + 0.5f); 6448 rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f); 6449 rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f); 6450 6451 // Trigger with obtained rectangle 6452 showQuickContact(context, rect, lookupUri, mode, excludeMimes); 6453 } 6454 6455 /** 6456 * Trigger a dialog that lists the various methods of interacting with 6457 * the requested {@link Contacts} entry. This may be based on available 6458 * {@link ContactsContract.Data} rows under that contact, and may also 6459 * include social status and presence details. 6460 * 6461 * @param context The parent {@link Context} that may be used as the 6462 * parent for this dialog. 6463 * @param target Specific {@link Rect} that this dialog should be 6464 * centered around, in screen coordinates. In particular, if 6465 * the dialog has a "callout" arrow, it will be pointed and 6466 * centered around this {@link Rect}. If you are running at a 6467 * non-native density, you need to manually adjust using 6468 * {@link DisplayMetrics#density} before calling. 6469 * @param lookupUri A 6470 * {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 6471 * {@link Uri} that describes a specific contact to feature 6472 * in this dialog. 6473 * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or 6474 * {@link #MODE_LARGE}, indicating the desired dialog size, 6475 * when supported. 6476 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 6477 * to exclude when showing this dialog. For example, when 6478 * already viewing the contact details card, this can be used 6479 * to omit the details entry from the dialog. 6480 */ 6481 public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode, 6482 String[] excludeMimes) { 6483 // Launch pivot dialog through intent for now 6484 final Intent intent = new Intent(ACTION_QUICK_CONTACT); 6485 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP 6486 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 6487 6488 intent.setData(lookupUri); 6489 intent.setSourceBounds(target); 6490 intent.putExtra(EXTRA_MODE, mode); 6491 intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes); 6492 context.startActivity(intent); 6493 } 6494 } 6495 6496 /** 6497 * Contains helper classes used to create or manage {@link android.content.Intent Intents} 6498 * that involve contacts. 6499 */ 6500 public static final class Intents { 6501 /** 6502 * This is the intent that is fired when a search suggestion is clicked on. 6503 */ 6504 public static final String SEARCH_SUGGESTION_CLICKED = 6505 "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED"; 6506 6507 /** 6508 * This is the intent that is fired when a search suggestion for dialing a number 6509 * is clicked on. 6510 */ 6511 public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = 6512 "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED"; 6513 6514 /** 6515 * This is the intent that is fired when a search suggestion for creating a contact 6516 * is clicked on. 6517 */ 6518 public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = 6519 "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED"; 6520 6521 /** 6522 * Starts an Activity that lets the user pick a contact to attach an image to. 6523 * After picking the contact it launches the image cropper in face detection mode. 6524 */ 6525 public static final String ATTACH_IMAGE = 6526 "com.android.contacts.action.ATTACH_IMAGE"; 6527 6528 /** 6529 * Takes as input a data URI with a mailto: or tel: scheme. If a single 6530 * contact exists with the given data it will be shown. If no contact 6531 * exists, a dialog will ask the user if they want to create a new 6532 * contact with the provided details filled in. If multiple contacts 6533 * share the data the user will be prompted to pick which contact they 6534 * want to view. 6535 * <p> 6536 * For <code>mailto:</code> URIs, the scheme specific portion must be a 6537 * raw email address, such as one built using 6538 * {@link Uri#fromParts(String, String, String)}. 6539 * <p> 6540 * For <code>tel:</code> URIs, the scheme specific portion is compared 6541 * to existing numbers using the standard caller ID lookup algorithm. 6542 * The number must be properly encoded, for example using 6543 * {@link Uri#fromParts(String, String, String)}. 6544 * <p> 6545 * Any extras from the {@link Insert} class will be passed along to the 6546 * create activity if there are no contacts to show. 6547 * <p> 6548 * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip 6549 * prompting the user when the contact doesn't exist. 6550 */ 6551 public static final String SHOW_OR_CREATE_CONTACT = 6552 "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; 6553 6554 /** 6555 * Starts an Activity that lets the user select the multiple phones from a 6556 * list of phone numbers which come from the contacts or 6557 * {@link #EXTRA_PHONE_URIS}. 6558 * <p> 6559 * The phone numbers being passed in through {@link #EXTRA_PHONE_URIS} 6560 * could belong to the contacts or not, and will be selected by default. 6561 * <p> 6562 * The user's selection will be returned from 6563 * {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)} 6564 * if the resultCode is 6565 * {@link android.app.Activity#RESULT_OK}, the array of picked phone 6566 * numbers are in the Intent's 6567 * {@link #EXTRA_PHONE_URIS}; otherwise, the 6568 * {@link android.app.Activity#RESULT_CANCELED} is returned if the user 6569 * left the Activity without changing the selection. 6570 * 6571 * @hide 6572 */ 6573 public static final String ACTION_GET_MULTIPLE_PHONES = 6574 "com.android.contacts.action.GET_MULTIPLE_PHONES"; 6575 6576 /** 6577 * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new 6578 * contact if no matching contact found. Otherwise, default behavior is 6579 * to prompt user with dialog before creating. 6580 * <p> 6581 * Type: BOOLEAN 6582 */ 6583 public static final String EXTRA_FORCE_CREATE = 6584 "com.android.contacts.action.FORCE_CREATE"; 6585 6586 /** 6587 * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact 6588 * description to be shown when prompting user about creating a new 6589 * contact. 6590 * <p> 6591 * Type: STRING 6592 */ 6593 public static final String EXTRA_CREATE_DESCRIPTION = 6594 "com.android.contacts.action.CREATE_DESCRIPTION"; 6595 6596 /** 6597 * Used with {@link #ACTION_GET_MULTIPLE_PHONES} as the input or output value. 6598 * <p> 6599 * The phone numbers want to be picked by default should be passed in as 6600 * input value. These phone numbers could belong to the contacts or not. 6601 * <p> 6602 * The phone numbers which were picked by the user are returned as output 6603 * value. 6604 * <p> 6605 * Type: array of URIs, the tel URI is used for the phone numbers which don't 6606 * belong to any contact, the content URI is used for phone id in contacts. 6607 * 6608 * @hide 6609 */ 6610 public static final String EXTRA_PHONE_URIS = 6611 "com.android.contacts.extra.PHONE_URIS"; 6612 6613 /** 6614 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a 6615 * dialog location using screen coordinates. When not specified, the 6616 * dialog will be centered. 6617 * 6618 * @hide 6619 */ 6620 @Deprecated 6621 public static final String EXTRA_TARGET_RECT = "target_rect"; 6622 6623 /** 6624 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a 6625 * desired dialog style, usually a variation on size. One of 6626 * {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}. 6627 * 6628 * @hide 6629 */ 6630 @Deprecated 6631 public static final String EXTRA_MODE = "mode"; 6632 6633 /** 6634 * Value for {@link #EXTRA_MODE} to show a small-sized dialog. 6635 * 6636 * @hide 6637 */ 6638 @Deprecated 6639 public static final int MODE_SMALL = 1; 6640 6641 /** 6642 * Value for {@link #EXTRA_MODE} to show a medium-sized dialog. 6643 * 6644 * @hide 6645 */ 6646 @Deprecated 6647 public static final int MODE_MEDIUM = 2; 6648 6649 /** 6650 * Value for {@link #EXTRA_MODE} to show a large-sized dialog. 6651 * 6652 * @hide 6653 */ 6654 @Deprecated 6655 public static final int MODE_LARGE = 3; 6656 6657 /** 6658 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to indicate 6659 * a list of specific MIME-types to exclude and not display. Stored as a 6660 * {@link String} array. 6661 * 6662 * @hide 6663 */ 6664 @Deprecated 6665 public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes"; 6666 6667 /** 6668 * Intents related to the Contacts app UI. 6669 * 6670 * @hide 6671 */ 6672 public static final class UI { 6673 /** 6674 * The action for the default contacts list tab. 6675 */ 6676 public static final String LIST_DEFAULT = 6677 "com.android.contacts.action.LIST_DEFAULT"; 6678 6679 /** 6680 * The action for the contacts list tab. 6681 */ 6682 public static final String LIST_GROUP_ACTION = 6683 "com.android.contacts.action.LIST_GROUP"; 6684 6685 /** 6686 * When in LIST_GROUP_ACTION mode, this is the group to display. 6687 */ 6688 public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP"; 6689 6690 /** 6691 * The action for the all contacts list tab. 6692 */ 6693 public static final String LIST_ALL_CONTACTS_ACTION = 6694 "com.android.contacts.action.LIST_ALL_CONTACTS"; 6695 6696 /** 6697 * The action for the contacts with phone numbers list tab. 6698 */ 6699 public static final String LIST_CONTACTS_WITH_PHONES_ACTION = 6700 "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES"; 6701 6702 /** 6703 * The action for the starred contacts list tab. 6704 */ 6705 public static final String LIST_STARRED_ACTION = 6706 "com.android.contacts.action.LIST_STARRED"; 6707 6708 /** 6709 * The action for the frequent contacts list tab. 6710 */ 6711 public static final String LIST_FREQUENT_ACTION = 6712 "com.android.contacts.action.LIST_FREQUENT"; 6713 6714 /** 6715 * The action for the "strequent" contacts list tab. It first lists the starred 6716 * contacts in alphabetical order and then the frequent contacts in descending 6717 * order of the number of times they have been contacted. 6718 */ 6719 public static final String LIST_STREQUENT_ACTION = 6720 "com.android.contacts.action.LIST_STREQUENT"; 6721 6722 /** 6723 * A key for to be used as an intent extra to set the activity 6724 * title to a custom String value. 6725 */ 6726 public static final String TITLE_EXTRA_KEY = 6727 "com.android.contacts.extra.TITLE_EXTRA"; 6728 6729 /** 6730 * Activity Action: Display a filtered list of contacts 6731 * <p> 6732 * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for 6733 * filtering 6734 * <p> 6735 * Output: Nothing. 6736 */ 6737 public static final String FILTER_CONTACTS_ACTION = 6738 "com.android.contacts.action.FILTER_CONTACTS"; 6739 6740 /** 6741 * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION} 6742 * intents to supply the text on which to filter. 6743 */ 6744 public static final String FILTER_TEXT_EXTRA_KEY = 6745 "com.android.contacts.extra.FILTER_TEXT"; 6746 } 6747 6748 /** 6749 * Convenience class that contains string constants used 6750 * to create contact {@link android.content.Intent Intents}. 6751 */ 6752 public static final class Insert { 6753 /** The action code to use when adding a contact */ 6754 public static final String ACTION = Intent.ACTION_INSERT; 6755 6756 /** 6757 * If present, forces a bypass of quick insert mode. 6758 */ 6759 public static final String FULL_MODE = "full_mode"; 6760 6761 /** 6762 * The extra field for the contact name. 6763 * <P>Type: String</P> 6764 */ 6765 public static final String NAME = "name"; 6766 6767 // TODO add structured name values here. 6768 6769 /** 6770 * The extra field for the contact phonetic name. 6771 * <P>Type: String</P> 6772 */ 6773 public static final String PHONETIC_NAME = "phonetic_name"; 6774 6775 /** 6776 * The extra field for the contact company. 6777 * <P>Type: String</P> 6778 */ 6779 public static final String COMPANY = "company"; 6780 6781 /** 6782 * The extra field for the contact job title. 6783 * <P>Type: String</P> 6784 */ 6785 public static final String JOB_TITLE = "job_title"; 6786 6787 /** 6788 * The extra field for the contact notes. 6789 * <P>Type: String</P> 6790 */ 6791 public static final String NOTES = "notes"; 6792 6793 /** 6794 * The extra field for the contact phone number. 6795 * <P>Type: String</P> 6796 */ 6797 public static final String PHONE = "phone"; 6798 6799 /** 6800 * The extra field for the contact phone number type. 6801 * <P>Type: Either an integer value from 6802 * {@link CommonDataKinds.Phone}, 6803 * or a string specifying a custom label.</P> 6804 */ 6805 public static final String PHONE_TYPE = "phone_type"; 6806 6807 /** 6808 * The extra field for the phone isprimary flag. 6809 * <P>Type: boolean</P> 6810 */ 6811 public static final String PHONE_ISPRIMARY = "phone_isprimary"; 6812 6813 /** 6814 * The extra field for an optional second contact phone number. 6815 * <P>Type: String</P> 6816 */ 6817 public static final String SECONDARY_PHONE = "secondary_phone"; 6818 6819 /** 6820 * The extra field for an optional second contact phone number type. 6821 * <P>Type: Either an integer value from 6822 * {@link CommonDataKinds.Phone}, 6823 * or a string specifying a custom label.</P> 6824 */ 6825 public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type"; 6826 6827 /** 6828 * The extra field for an optional third contact phone number. 6829 * <P>Type: String</P> 6830 */ 6831 public static final String TERTIARY_PHONE = "tertiary_phone"; 6832 6833 /** 6834 * The extra field for an optional third contact phone number type. 6835 * <P>Type: Either an integer value from 6836 * {@link CommonDataKinds.Phone}, 6837 * or a string specifying a custom label.</P> 6838 */ 6839 public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type"; 6840 6841 /** 6842 * The extra field for the contact email address. 6843 * <P>Type: String</P> 6844 */ 6845 public static final String EMAIL = "email"; 6846 6847 /** 6848 * The extra field for the contact email type. 6849 * <P>Type: Either an integer value from 6850 * {@link CommonDataKinds.Email} 6851 * or a string specifying a custom label.</P> 6852 */ 6853 public static final String EMAIL_TYPE = "email_type"; 6854 6855 /** 6856 * The extra field for the email isprimary flag. 6857 * <P>Type: boolean</P> 6858 */ 6859 public static final String EMAIL_ISPRIMARY = "email_isprimary"; 6860 6861 /** 6862 * The extra field for an optional second contact email address. 6863 * <P>Type: String</P> 6864 */ 6865 public static final String SECONDARY_EMAIL = "secondary_email"; 6866 6867 /** 6868 * The extra field for an optional second contact email type. 6869 * <P>Type: Either an integer value from 6870 * {@link CommonDataKinds.Email} 6871 * or a string specifying a custom label.</P> 6872 */ 6873 public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type"; 6874 6875 /** 6876 * The extra field for an optional third contact email address. 6877 * <P>Type: String</P> 6878 */ 6879 public static final String TERTIARY_EMAIL = "tertiary_email"; 6880 6881 /** 6882 * The extra field for an optional third contact email type. 6883 * <P>Type: Either an integer value from 6884 * {@link CommonDataKinds.Email} 6885 * or a string specifying a custom label.</P> 6886 */ 6887 public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type"; 6888 6889 /** 6890 * The extra field for the contact postal address. 6891 * <P>Type: String</P> 6892 */ 6893 public static final String POSTAL = "postal"; 6894 6895 /** 6896 * The extra field for the contact postal address type. 6897 * <P>Type: Either an integer value from 6898 * {@link CommonDataKinds.StructuredPostal} 6899 * or a string specifying a custom label.</P> 6900 */ 6901 public static final String POSTAL_TYPE = "postal_type"; 6902 6903 /** 6904 * The extra field for the postal isprimary flag. 6905 * <P>Type: boolean</P> 6906 */ 6907 public static final String POSTAL_ISPRIMARY = "postal_isprimary"; 6908 6909 /** 6910 * The extra field for an IM handle. 6911 * <P>Type: String</P> 6912 */ 6913 public static final String IM_HANDLE = "im_handle"; 6914 6915 /** 6916 * The extra field for the IM protocol 6917 */ 6918 public static final String IM_PROTOCOL = "im_protocol"; 6919 6920 /** 6921 * The extra field for the IM isprimary flag. 6922 * <P>Type: boolean</P> 6923 */ 6924 public static final String IM_ISPRIMARY = "im_isprimary"; 6925 6926 /** 6927 * The extra field that allows the client to supply multiple rows of 6928 * arbitrary data for a single contact created using the {@link Intent#ACTION_INSERT} 6929 * or edited using {@link Intent#ACTION_EDIT}. It is an ArrayList of 6930 * {@link ContentValues}, one per data row. Supplying this extra is 6931 * similar to inserting multiple rows into the {@link Data} table, 6932 * except the user gets a chance to see and edit them before saving. 6933 * Each ContentValues object must have a value for {@link Data#MIMETYPE}. 6934 * If supplied values are not visible in the editor UI, they will be 6935 * dropped. Duplicate data will dropped. Some fields 6936 * like {@link CommonDataKinds.Email#TYPE Email.TYPE} may be automatically 6937 * adjusted to comply with the constraints of the specific account type. 6938 * For example, an Exchange contact can only have one phone numbers of type Home, 6939 * so the contact editor may choose a different type for this phone number to 6940 * avoid dropping the valueable part of the row, which is the phone number. 6941 * <p> 6942 * Example: 6943 * <pre> 6944 * ArrayList<ContentValues> data = new ArrayList<ContentValues>(); 6945 * 6946 * ContentValues row1 = new ContentValues(); 6947 * row1.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); 6948 * row1.put(Organization.COMPANY, "Android"); 6949 * data.add(row1); 6950 * 6951 * ContentValues row2 = new ContentValues(); 6952 * row2.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 6953 * row2.put(Email.TYPE, Email.TYPE_CUSTOM); 6954 * row2.put(Email.LABEL, "Green Bot"); 6955 * row2.put(Email.ADDRESS, "android@android.com"); 6956 * data.add(row2); 6957 * 6958 * Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); 6959 * intent.putParcelableArrayListExtra(Insert.DATA, data); 6960 * 6961 * startActivity(intent); 6962 * </pre> 6963 */ 6964 public static final String DATA = "data"; 6965 6966 /** 6967 * Used to specify the account in which to create the new contact. 6968 * <p> 6969 * If this value is not provided, the user is presented with a disambiguation 6970 * dialog to chose an account 6971 * <p> 6972 * Type: {@link Account} 6973 * 6974 * @hide 6975 */ 6976 public static final String ACCOUNT = "com.android.contacts.extra.ACCOUNT"; 6977 } 6978 } 6979} 6980