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 17 package android.provider; 18 19 import android.accounts.Account; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SdkConstant; 24 import android.annotation.SdkConstant.SdkConstantType; 25 import android.annotation.SystemApi; 26 import android.annotation.TestApi; 27 import android.app.Activity; 28 import android.compat.annotation.UnsupportedAppUsage; 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.ContentProviderClient; 32 import android.content.ContentProviderOperation; 33 import android.content.ContentResolver; 34 import android.content.ContentUris; 35 import android.content.ContentValues; 36 import android.content.Context; 37 import android.content.ContextWrapper; 38 import android.content.CursorEntityIterator; 39 import android.content.Entity; 40 import android.content.EntityIterator; 41 import android.content.Intent; 42 import android.content.IntentFilter; 43 import android.content.res.AssetFileDescriptor; 44 import android.content.res.Resources; 45 import android.database.Cursor; 46 import android.database.CursorWrapper; 47 import android.database.DatabaseUtils; 48 import android.graphics.Rect; 49 import android.net.Uri; 50 import android.os.Build; 51 import android.os.Bundle; 52 import android.os.Parcel; 53 import android.os.Parcelable; 54 import android.os.RemoteException; 55 import android.telecom.PhoneAccountHandle; 56 import android.text.TextUtils; 57 import android.util.DisplayMetrics; 58 import android.util.Pair; 59 import android.view.View; 60 61 import com.google.android.collect.Sets; 62 63 import java.io.ByteArrayInputStream; 64 import java.io.IOException; 65 import java.io.InputStream; 66 import java.util.ArrayList; 67 import java.util.List; 68 import java.util.Objects; 69 import java.util.Set; 70 71 /** 72 * <p> 73 * The contract between the contacts provider and applications. Contains 74 * definitions for the supported URIs and columns. These APIs supersede 75 * {@link Contacts}. 76 * </p> 77 * <h3>Overview</h3> 78 * <p> 79 * ContactsContract defines an extensible database of contact-related 80 * information. Contact information is stored in a three-tier data model: 81 * </p> 82 * <ul> 83 * <li> 84 * A row in the {@link Data} table can store any kind of personal data, such 85 * as a phone number or email addresses. The set of data kinds that can be 86 * stored in this table is open-ended. There is a predefined set of common 87 * kinds, but any application can add its own data kinds. 88 * </li> 89 * <li> 90 * A row in the {@link RawContacts} table represents a set of data describing a 91 * person and associated with a single account (for example, one of the user's 92 * Gmail accounts). 93 * </li> 94 * <li> 95 * A row in the {@link Contacts} table represents an aggregate of one or more 96 * RawContacts presumably describing the same person. When data in or associated with 97 * the RawContacts table is changed, the affected aggregate contacts are updated as 98 * necessary. 99 * </li> 100 * </ul> 101 * <p> 102 * Other tables include: 103 * </p> 104 * <ul> 105 * <li> 106 * {@link Groups}, which contains information about raw contact groups 107 * such as Gmail contact groups. The 108 * current API does not support the notion of groups spanning multiple accounts. 109 * </li> 110 * <li> 111 * {@link StatusUpdates}, which contains social status updates including IM 112 * availability. 113 * </li> 114 * <li> 115 * {@link AggregationExceptions}, which is used for manual aggregation and 116 * disaggregation of raw contacts 117 * </li> 118 * <li> 119 * {@link Settings}, which contains visibility and sync settings for accounts 120 * and groups. 121 * </li> 122 * <li> 123 * {@link SyncState}, which contains free-form data maintained on behalf of sync 124 * adapters 125 * </li> 126 * <li> 127 * {@link PhoneLookup}, which is used for quick caller-ID lookup</li> 128 * </ul> 129 */ 130 @SuppressWarnings("unused") 131 public final class ContactsContract { 132 /** The authority for the contacts provider */ 133 public static final String AUTHORITY = "com.android.contacts"; 134 /** A content:// style uri to the authority for the contacts provider */ 135 public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); 136 137 /** 138 * Prefix for column names that are not visible to client apps. 139 * @hide 140 */ 141 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 142 @TestApi 143 public static final String HIDDEN_COLUMN_PREFIX = "x_"; 144 145 /** 146 * An optional URI parameter for insert, update, or delete queries 147 * that allows the caller 148 * to specify that it is a sync adapter. The default value is false. If true 149 * {@link RawContacts#DIRTY} is not automatically set and the 150 * "syncToNetwork" parameter is set to false when calling 151 * {@link 152 * ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}. 153 * This prevents an unnecessary extra synchronization, see the discussion of 154 * the delete operation in {@link RawContacts}. 155 */ 156 public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; 157 158 /** 159 * Query parameter that should be used by the client to access a specific 160 * {@link Directory}. The parameter value should be the _ID of the corresponding 161 * directory, e.g. 162 * {@code content://com.android.contacts/data/emails/filter/acme?directory=3} 163 */ 164 public static final String DIRECTORY_PARAM_KEY = "directory"; 165 166 /** 167 * A query parameter that limits the number of results returned for supported URIs. The 168 * parameter value should be an integer. 169 * 170 * <p>This parameter is not supported by all URIs. Supported URIs include, but not limited to, 171 * {@link Contacts#CONTENT_URI}, 172 * {@link RawContacts#CONTENT_URI}, 173 * {@link Data#CONTENT_URI}, 174 * {@link CommonDataKinds.Phone#CONTENT_URI}, 175 * {@link CommonDataKinds.Callable#CONTENT_URI}, 176 * {@link CommonDataKinds.Email#CONTENT_URI}, 177 * {@link CommonDataKinds.Contactables#CONTENT_URI}, 178 * 179 * <p>In order to limit the number of rows returned by a non-supported URI, you can implement a 180 * {@link CursorWrapper} and override the {@link CursorWrapper#getCount()} methods. 181 */ 182 public static final String LIMIT_PARAM_KEY = "limit"; 183 184 /** 185 * A query parameter specifing a primary account. This parameter should be used with 186 * {@link #PRIMARY_ACCOUNT_TYPE}. The contacts provider handling a query may rely on 187 * this information to optimize its query results. 188 * 189 * For example, in an email composition screen, its implementation can specify an account when 190 * obtaining possible recipients, letting the provider know which account is selected during 191 * the composition. The provider may use the "primary account" information to optimize 192 * the search result. 193 */ 194 public static final String PRIMARY_ACCOUNT_NAME = "name_for_primary_account"; 195 196 /** 197 * A query parameter specifing a primary account. This parameter should be used with 198 * {@link #PRIMARY_ACCOUNT_NAME}. See the doc in {@link #PRIMARY_ACCOUNT_NAME}. 199 */ 200 public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account"; 201 202 /** 203 * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and 204 * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to 205 * return only phone-related results. 206 */ 207 public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only"; 208 209 /** 210 * A key to a boolean in the "extras" bundle of the cursor. 211 * The boolean indicates that the provider did not create a snippet and that the client asking 212 * for the snippet should do it (true means the snippeting was deferred to the client). 213 * 214 * @see SearchSnippets 215 */ 216 public static final String DEFERRED_SNIPPETING = "deferred_snippeting"; 217 218 /** 219 * Key to retrieve the original deferred snippeting from the cursor on the client side. 220 * 221 * @see SearchSnippets 222 * @see #DEFERRED_SNIPPETING 223 */ 224 public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query"; 225 226 /** 227 * A boolean parameter for {@link CommonDataKinds.Phone#CONTENT_URI Phone.CONTENT_URI}, 228 * {@link CommonDataKinds.Email#CONTENT_URI Email.CONTENT_URI}, and 229 * {@link CommonDataKinds.StructuredPostal#CONTENT_URI StructuredPostal.CONTENT_URI}. 230 * This enables a content provider to remove duplicate entries in results. 231 */ 232 public static final String REMOVE_DUPLICATE_ENTRIES = "remove_duplicate_entries"; 233 234 /** 235 * <p> 236 * API for obtaining a pre-authorized version of a URI that normally requires special 237 * permission (beyond READ_CONTACTS) to read. The caller obtaining the pre-authorized URI 238 * must already have the necessary permissions to access the URI; otherwise a 239 * {@link SecurityException} will be thrown. Unlike {@link Context#grantUriPermission}, 240 * this can be used to grant permissions that aren't explicitly required for the URI inside 241 * AndroidManifest.xml. For example, permissions that are only required when reading URIs 242 * that refer to the user's profile. 243 * </p> 244 * <p> 245 * The authorized URI returned in the bundle contains an expiring token that allows the 246 * caller to execute the query without having the special permissions that would normally 247 * be required. The token expires in five minutes. 248 * </p> 249 * <p> 250 * This API does not access disk, and should be safe to invoke from the UI thread. 251 * </p> 252 * <p> 253 * Example usage: 254 * <pre> 255 * Uri profileUri = ContactsContract.Profile.CONTENT_VCARD_URI; 256 * Bundle uriBundle = new Bundle(); 257 * uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri); 258 * Bundle authResponse = getContext().getContentResolver().call( 259 * ContactsContract.AUTHORITY_URI, 260 * ContactsContract.Authorization.AUTHORIZATION_METHOD, 261 * null, // String arg, not used. 262 * uriBundle); 263 * if (authResponse != null) { 264 * Uri preauthorizedProfileUri = (Uri) authResponse.getParcelable( 265 * ContactsContract.Authorization.KEY_AUTHORIZED_URI); 266 * // This pre-authorized URI can be queried by a caller without READ_PROFILE 267 * // permission. 268 * } 269 * </pre> 270 * </p> 271 * 272 * @hide 273 */ 274 public static final class Authorization { 275 /** 276 * The method to invoke to create a pre-authorized URI out of the input argument. 277 */ 278 public static final String AUTHORIZATION_METHOD = "authorize"; 279 280 /** 281 * The key to set in the outbound Bundle with the URI that should be authorized. 282 */ 283 public static final String KEY_URI_TO_AUTHORIZE = "uri_to_authorize"; 284 285 /** 286 * The key to retrieve from the returned Bundle to obtain the pre-authorized URI. 287 */ 288 public static final String KEY_AUTHORIZED_URI = "authorized_uri"; 289 } 290 291 /** 292 * A Directory represents a contacts corpus, e.g. Local contacts, 293 * Google Apps Global Address List or Corporate Global Address List. 294 * <p> 295 * A Directory is implemented as a content provider with its unique authority and 296 * the same API as the main Contacts Provider. However, there is no expectation that 297 * every directory provider will implement this Contract in its entirety. If a 298 * directory provider does not have an implementation for a specific request, it 299 * should throw an UnsupportedOperationException. 300 * </p> 301 * <p> 302 * The most important use case for Directories is search. A Directory provider is 303 * expected to support at least {@link ContactsContract.Contacts#CONTENT_FILTER_URI 304 * Contacts.CONTENT_FILTER_URI}. If a Directory provider wants to participate 305 * in email and phone lookup functionalities, it should also implement 306 * {@link CommonDataKinds.Email#CONTENT_FILTER_URI CommonDataKinds.Email.CONTENT_FILTER_URI} 307 * and 308 * {@link CommonDataKinds.Phone#CONTENT_FILTER_URI CommonDataKinds.Phone.CONTENT_FILTER_URI}. 309 * </p> 310 * <p> 311 * A directory provider should return NULL for every projection field it does not 312 * recognize, rather than throwing an exception. This way it will not be broken 313 * if ContactsContract is extended with new fields in the future. 314 * </p> 315 * <p> 316 * The client interacts with a directory via Contacts Provider by supplying an 317 * optional {@code directory=} query parameter. 318 * <p> 319 * <p> 320 * When the Contacts Provider receives the request, it transforms the URI and forwards 321 * the request to the corresponding directory content provider. 322 * The URI is transformed in the following fashion: 323 * <ul> 324 * <li>The URI authority is replaced with the corresponding {@link #DIRECTORY_AUTHORITY}.</li> 325 * <li>The {@code accountName=} and {@code accountType=} parameters are added or 326 * replaced using the corresponding {@link #ACCOUNT_TYPE} and {@link #ACCOUNT_NAME} values.</li> 327 * </ul> 328 * </p> 329 * <p> 330 * Clients should send directory requests to Contacts Provider and let it 331 * forward them to the respective providers rather than constructing 332 * directory provider URIs by themselves. This level of indirection allows 333 * Contacts Provider to implement additional system-level features and 334 * optimizations. Access to Contacts Provider is protected by the 335 * READ_CONTACTS permission, but access to the directory provider is protected by 336 * BIND_DIRECTORY_SEARCH. This permission was introduced at the API level 17, for previous 337 * platform versions the provider should perform the following check to make sure the call 338 * is coming from the ContactsProvider: 339 * <pre> 340 * private boolean isCallerAllowed() { 341 * PackageManager pm = getContext().getPackageManager(); 342 * for (String packageName: pm.getPackagesForUid(Binder.getCallingUid())) { 343 * if (packageName.equals("com.android.providers.contacts")) { 344 * return true; 345 * } 346 * } 347 * return false; 348 * } 349 * </pre> 350 * </p> 351 * <p> 352 * The Directory table is read-only and is maintained by the Contacts Provider 353 * automatically. 354 * </p> 355 * <p>It always has at least these two rows: 356 * <ul> 357 * <li> 358 * The local directory. It has {@link Directory#_ID Directory._ID} = 359 * {@link Directory#DEFAULT Directory.DEFAULT}. This directory can be used to access locally 360 * stored contacts. The same can be achieved by omitting the {@code directory=} 361 * parameter altogether. 362 * </li> 363 * <li> 364 * The local invisible contacts. The corresponding directory ID is 365 * {@link Directory#LOCAL_INVISIBLE Directory.LOCAL_INVISIBLE}. 366 * </li> 367 * </ul> 368 * </p> 369 * <p>Custom Directories are discovered by the Contacts Provider following this procedure: 370 * <ul> 371 * <li>It finds all installed content providers with meta data identifying them 372 * as directory providers in AndroidManifest.xml: 373 * <code> 374 * <meta-data android:name="android.content.ContactDirectory" 375 * android:value="true" /> 376 * </code> 377 * <p> 378 * This tag should be placed inside the corresponding content provider declaration. 379 * </p> 380 * </li> 381 * <li> 382 * Then Contacts Provider sends a {@link Directory#CONTENT_URI Directory.CONTENT_URI} 383 * query to each of the directory authorities. A directory provider must implement 384 * this query and return a list of directories. Each directory returned by 385 * the provider must have a unique combination for the {@link #ACCOUNT_NAME} and 386 * {@link #ACCOUNT_TYPE} columns (nulls are allowed). Since directory IDs are assigned 387 * automatically, the _ID field will not be part of the query projection. 388 * </li> 389 * <li>Contacts Provider compiles directory lists received from all directory 390 * providers into one, assigns each individual directory a globally unique ID and 391 * stores all directory records in the Directory table. 392 * </li> 393 * </ul> 394 * </p> 395 * <p>Contacts Provider automatically interrogates newly installed or replaced packages. 396 * Thus simply installing a package containing a directory provider is sufficient 397 * to have that provider registered. A package supplying a directory provider does 398 * not have to contain launchable activities. 399 * </p> 400 * <p> 401 * Every row in the Directory table is automatically associated with the corresponding package 402 * (apk). If the package is later uninstalled, all corresponding directory rows 403 * are automatically removed from the Contacts Provider. 404 * </p> 405 * <p> 406 * When the list of directories handled by a directory provider changes 407 * (for instance when the user adds a new Directory account), the directory provider 408 * should call {@link #notifyDirectoryChange} to notify the Contacts Provider of the change. 409 * In response, the Contacts Provider will requery the directory provider to obtain the 410 * new list of directories. 411 * </p> 412 * <p> 413 * A directory row can be optionally associated with an existing account 414 * (see {@link android.accounts.AccountManager}). If the account is later removed, 415 * the corresponding directory rows are automatically removed from the Contacts Provider. 416 * </p> 417 */ 418 public static final class Directory implements BaseColumns { 419 420 /** 421 * Not instantiable. 422 */ Directory()423 private Directory() { 424 } 425 426 /** 427 * The content:// style URI for this table. Requests to this URI can be 428 * performed on the UI thread because they are always unblocking. 429 */ 430 public static final Uri CONTENT_URI = 431 Uri.withAppendedPath(AUTHORITY_URI, "directories"); 432 433 /** 434 * URI used for getting all directories from primary and managed profile. 435 * It supports the same semantics as {@link #CONTENT_URI} and returns the same columns. 436 * If the device has no managed profile that is linked to the current profile, it behaves 437 * in the exact same way as {@link #CONTENT_URI}. 438 * If there is a managed profile linked to the current profile, it will merge 439 * managed profile and current profile's results and return. 440 * 441 * Note: this query returns primary profile results before managed profile results, 442 * and this order is not affected by sorting parameter. 443 * 444 */ 445 public static final Uri ENTERPRISE_CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, 446 "directories_enterprise"); 447 448 /** 449 * Access file provided by remote directory. It allows both personal and work remote 450 * directory, but not local and invisible diretory. 451 * 452 * It's supported only by a few specific places for referring to contact pictures in the 453 * remote directory. Contact picture URIs, e.g. 454 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}, may contain this kind of URI. 455 * 456 * @hide 457 */ 458 public static final Uri ENTERPRISE_FILE_URI = Uri.withAppendedPath(AUTHORITY_URI, 459 "directory_file_enterprise"); 460 461 462 /** 463 * The MIME-type of {@link #CONTENT_URI} providing a directory of 464 * contact directories. 465 */ 466 public static final String CONTENT_TYPE = 467 "vnd.android.cursor.dir/contact_directories"; 468 469 /** 470 * The MIME type of a {@link #CONTENT_URI} item. 471 */ 472 public static final String CONTENT_ITEM_TYPE = 473 "vnd.android.cursor.item/contact_directory"; 474 475 /** 476 * _ID of the default directory, which represents locally stored contacts. 477 * <b>This is only supported by {@link ContactsContract.Contacts#CONTENT_URI} and 478 * {@link ContactsContract.Contacts#CONTENT_FILTER_URI}. 479 * Other URLs do not support the concept of "visible" or "invisible" contacts. 480 */ 481 public static final long DEFAULT = 0; 482 483 /** 484 * _ID of the directory that represents locally stored invisible contacts. 485 */ 486 public static final long LOCAL_INVISIBLE = 1; 487 488 /** 489 * _ID of the work profile default directory, which represents locally stored contacts. 490 */ 491 public static final long ENTERPRISE_DEFAULT = Directory.ENTERPRISE_DIRECTORY_ID_BASE 492 + DEFAULT; 493 494 /** 495 * _ID of the work profile directory that represents locally stored invisible contacts. 496 */ 497 public static final long ENTERPRISE_LOCAL_INVISIBLE = Directory.ENTERPRISE_DIRECTORY_ID_BASE 498 + LOCAL_INVISIBLE; 499 500 /** 501 * The name of the package that owns this directory. Contacts Provider 502 * fill it in with the name of the package containing the directory provider. 503 * If the package is later uninstalled, the directories it owns are 504 * automatically removed from this table. 505 * 506 * <p>TYPE: TEXT</p> 507 */ 508 public static final String PACKAGE_NAME = "packageName"; 509 510 /** 511 * The type of directory captured as a resource ID in the context of the 512 * package {@link #PACKAGE_NAME}, e.g. "Corporate Directory" 513 * 514 * <p>TYPE: INTEGER</p> 515 */ 516 public static final String TYPE_RESOURCE_ID = "typeResourceId"; 517 518 /** 519 * An optional name that can be used in the UI to represent this directory, 520 * e.g. "Acme Corp" 521 * <p>TYPE: text</p> 522 */ 523 public static final String DISPLAY_NAME = "displayName"; 524 525 /** 526 * <p> 527 * The authority of the Directory Provider. Contacts Provider will 528 * use this authority to forward requests to the directory provider. 529 * A directory provider can leave this column empty - Contacts Provider will fill it in. 530 * </p> 531 * <p> 532 * Clients of this API should not send requests directly to this authority. 533 * All directory requests must be routed through Contacts Provider. 534 * </p> 535 * 536 * <p>TYPE: text</p> 537 */ 538 public static final String DIRECTORY_AUTHORITY = "authority"; 539 540 /** 541 * The account type which this directory is associated. 542 * 543 * <p>TYPE: text</p> 544 */ 545 public static final String ACCOUNT_TYPE = "accountType"; 546 547 /** 548 * The account with which this directory is associated. If the account is later 549 * removed, the directories it owns are automatically removed from this table. 550 * 551 * <p>TYPE: text</p> 552 */ 553 public static final String ACCOUNT_NAME = "accountName"; 554 555 /** 556 * Mimimal ID for corp directory returned from 557 * {@link Directory#CORP_CONTENT_URI}. 558 * 559 * @hide 560 */ 561 // slightly smaller than 2 ** 30 562 public static final long ENTERPRISE_DIRECTORY_ID_BASE = 1000000000; 563 564 /** 565 * One of {@link #EXPORT_SUPPORT_NONE}, {@link #EXPORT_SUPPORT_ANY_ACCOUNT}, 566 * {@link #EXPORT_SUPPORT_SAME_ACCOUNT_ONLY}. This is the expectation the 567 * directory has for data exported from it. Clients must obey this setting. 568 */ 569 public static final String EXPORT_SUPPORT = "exportSupport"; 570 571 /** 572 * An {@link #EXPORT_SUPPORT} setting that indicates that the directory 573 * does not allow any data to be copied out of it. 574 */ 575 public static final int EXPORT_SUPPORT_NONE = 0; 576 577 /** 578 * An {@link #EXPORT_SUPPORT} setting that indicates that the directory 579 * allow its data copied only to the account specified by 580 * {@link #ACCOUNT_TYPE}/{@link #ACCOUNT_NAME}. 581 */ 582 public static final int EXPORT_SUPPORT_SAME_ACCOUNT_ONLY = 1; 583 584 /** 585 * An {@link #EXPORT_SUPPORT} setting that indicates that the directory 586 * allow its data copied to any contacts account. 587 */ 588 public static final int EXPORT_SUPPORT_ANY_ACCOUNT = 2; 589 590 /** 591 * One of {@link #SHORTCUT_SUPPORT_NONE}, {@link #SHORTCUT_SUPPORT_DATA_ITEMS_ONLY}, 592 * {@link #SHORTCUT_SUPPORT_FULL}. This is the expectation the directory 593 * has for shortcuts created for its elements. Clients must obey this setting. 594 */ 595 public static final String SHORTCUT_SUPPORT = "shortcutSupport"; 596 597 /** 598 * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory 599 * does not allow any shortcuts created for its contacts. 600 */ 601 public static final int SHORTCUT_SUPPORT_NONE = 0; 602 603 /** 604 * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory 605 * allow creation of shortcuts for data items like email, phone or postal address, 606 * but not the entire contact. 607 */ 608 public static final int SHORTCUT_SUPPORT_DATA_ITEMS_ONLY = 1; 609 610 /** 611 * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory 612 * allow creation of shortcuts for contact as well as their constituent elements. 613 */ 614 public static final int SHORTCUT_SUPPORT_FULL = 2; 615 616 /** 617 * One of {@link #PHOTO_SUPPORT_NONE}, {@link #PHOTO_SUPPORT_THUMBNAIL_ONLY}, 618 * {@link #PHOTO_SUPPORT_FULL}. This is a feature flag indicating the extent 619 * to which the directory supports contact photos. 620 */ 621 public static final String PHOTO_SUPPORT = "photoSupport"; 622 623 /** 624 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 625 * does not provide any photos. 626 */ 627 public static final int PHOTO_SUPPORT_NONE = 0; 628 629 /** 630 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 631 * can only produce small size thumbnails of contact photos. 632 */ 633 public static final int PHOTO_SUPPORT_THUMBNAIL_ONLY = 1; 634 635 /** 636 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 637 * has full-size contact photos, but cannot provide scaled thumbnails. 638 */ 639 public static final int PHOTO_SUPPORT_FULL_SIZE_ONLY = 2; 640 641 /** 642 * An {@link #PHOTO_SUPPORT} setting that indicates that the directory 643 * can produce thumbnails as well as full-size contact photos. 644 */ 645 public static final int PHOTO_SUPPORT_FULL = 3; 646 647 /** 648 * Return TRUE if it is a remote stored directory. 649 */ isRemoteDirectoryId(long directoryId)650 public static boolean isRemoteDirectoryId(long directoryId) { 651 return directoryId != Directory.DEFAULT 652 && directoryId != Directory.LOCAL_INVISIBLE 653 && directoryId != Directory.ENTERPRISE_DEFAULT 654 && directoryId != Directory.ENTERPRISE_LOCAL_INVISIBLE; 655 } 656 657 /** 658 * Return TRUE if it is a remote stored directory. TODO: Remove this method once all 659 * internal apps are not using this API. 660 * 661 * @hide 662 */ isRemoteDirectory(long directoryId)663 public static boolean isRemoteDirectory(long directoryId) { 664 return isRemoteDirectoryId(directoryId); 665 } 666 667 /** 668 * Return TRUE if a directory ID is from the contacts provider on the enterprise profile. 669 * 670 */ isEnterpriseDirectoryId(long directoryId)671 public static boolean isEnterpriseDirectoryId(long directoryId) { 672 return directoryId >= ENTERPRISE_DIRECTORY_ID_BASE; 673 } 674 675 /** 676 * Notifies the system of a change in the list of directories handled by 677 * a particular directory provider. The Contacts provider will turn around 678 * and send a query to the directory provider for the full list of directories, 679 * which will replace the previous list. 680 */ notifyDirectoryChange(ContentResolver resolver)681 public static void notifyDirectoryChange(ContentResolver resolver) { 682 // This is done to trigger a query by Contacts Provider back to the directory provider. 683 // No data needs to be sent back, because the provider can infer the calling 684 // package from binder. 685 ContentValues contentValues = new ContentValues(); 686 resolver.update(Directory.CONTENT_URI, contentValues, null, null); 687 } 688 689 /** 690 * A query parameter that's passed to directory providers which indicates the client 691 * package name that has made the query requests. 692 */ 693 public static final String CALLER_PACKAGE_PARAM_KEY = "callerPackage"; 694 } 695 696 /** 697 * @hide should be removed when users are updated to refer to SyncState 698 * @deprecated use SyncState instead 699 */ 700 @Deprecated 701 public interface SyncStateColumns extends SyncStateContract.Columns { 702 } 703 704 /** 705 * A table provided for sync adapters to use for storing private sync state data for contacts. 706 * 707 * @see SyncStateContract 708 */ 709 public static final class SyncState implements SyncStateContract.Columns { 710 /** 711 * This utility class cannot be instantiated 712 */ SyncState()713 private SyncState() {} 714 715 public static final String CONTENT_DIRECTORY = 716 SyncStateContract.Constants.CONTENT_DIRECTORY; 717 718 /** 719 * The content:// style URI for this table 720 */ 721 public static final Uri CONTENT_URI = 722 Uri.withAppendedPath(AUTHORITY_URI, CONTENT_DIRECTORY); 723 724 /** 725 * @see android.provider.SyncStateContract.Helpers#get 726 */ get(ContentProviderClient provider, Account account)727 public static byte[] get(ContentProviderClient provider, Account account) 728 throws RemoteException { 729 return SyncStateContract.Helpers.get(provider, CONTENT_URI, account); 730 } 731 732 /** 733 * @see android.provider.SyncStateContract.Helpers#get 734 */ getWithUri(ContentProviderClient provider, Account account)735 public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account) 736 throws RemoteException { 737 return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account); 738 } 739 740 /** 741 * @see android.provider.SyncStateContract.Helpers#set 742 */ set(ContentProviderClient provider, Account account, byte[] data)743 public static void set(ContentProviderClient provider, Account account, byte[] data) 744 throws RemoteException { 745 SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data); 746 } 747 748 /** 749 * @see android.provider.SyncStateContract.Helpers#newSetOperation 750 */ newSetOperation(Account account, byte[] data)751 public static ContentProviderOperation newSetOperation(Account account, byte[] data) { 752 return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data); 753 } 754 } 755 756 757 /** 758 * A table provided for sync adapters to use for storing private sync state data for the 759 * user's personal profile. 760 * 761 * @see SyncStateContract 762 */ 763 public static final class ProfileSyncState implements SyncStateContract.Columns { 764 /** 765 * This utility class cannot be instantiated 766 */ ProfileSyncState()767 private ProfileSyncState() {} 768 769 public static final String CONTENT_DIRECTORY = 770 SyncStateContract.Constants.CONTENT_DIRECTORY; 771 772 /** 773 * The content:// style URI for this table 774 */ 775 public static final Uri CONTENT_URI = 776 Uri.withAppendedPath(Profile.CONTENT_URI, CONTENT_DIRECTORY); 777 778 /** 779 * @see android.provider.SyncStateContract.Helpers#get 780 */ get(ContentProviderClient provider, Account account)781 public static byte[] get(ContentProviderClient provider, Account account) 782 throws RemoteException { 783 return SyncStateContract.Helpers.get(provider, CONTENT_URI, account); 784 } 785 786 /** 787 * @see android.provider.SyncStateContract.Helpers#get 788 */ getWithUri(ContentProviderClient provider, Account account)789 public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account) 790 throws RemoteException { 791 return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account); 792 } 793 794 /** 795 * @see android.provider.SyncStateContract.Helpers#set 796 */ set(ContentProviderClient provider, Account account, byte[] data)797 public static void set(ContentProviderClient provider, Account account, byte[] data) 798 throws RemoteException { 799 SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data); 800 } 801 802 /** 803 * @see android.provider.SyncStateContract.Helpers#newSetOperation 804 */ newSetOperation(Account account, byte[] data)805 public static ContentProviderOperation newSetOperation(Account account, byte[] data) { 806 return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data); 807 } 808 } 809 810 /** 811 * Generic columns for use by sync adapters. The specific functions of 812 * these columns are private to the sync adapter. Other clients of the API 813 * should not attempt to either read or write this column. 814 * 815 * @see RawContacts 816 * @see Groups 817 */ 818 protected interface BaseSyncColumns { 819 820 /** Generic column for use by sync adapters. */ 821 public static final String SYNC1 = "sync1"; 822 /** Generic column for use by sync adapters. */ 823 public static final String SYNC2 = "sync2"; 824 /** Generic column for use by sync adapters. */ 825 public static final String SYNC3 = "sync3"; 826 /** Generic column for use by sync adapters. */ 827 public static final String SYNC4 = "sync4"; 828 } 829 830 /** 831 * Columns that appear when each row of a table belongs to a specific 832 * account, including sync information that an account may need. 833 * 834 * @see RawContacts 835 * @see Groups 836 */ 837 protected interface SyncColumns extends BaseSyncColumns { 838 /** 839 * The name of the account instance to which this row belongs, which when paired with 840 * {@link #ACCOUNT_TYPE} identifies a specific account. 841 * <P>Type: TEXT</P> 842 */ 843 public static final String ACCOUNT_NAME = "account_name"; 844 845 /** 846 * The type of account to which this row belongs, which when paired with 847 * {@link #ACCOUNT_NAME} identifies a specific account. 848 * <P>Type: TEXT</P> 849 */ 850 public static final String ACCOUNT_TYPE = "account_type"; 851 852 /** 853 * String that uniquely identifies this row to its source account. 854 * <P>Type: TEXT</P> 855 */ 856 public static final String SOURCE_ID = "sourceid"; 857 858 /** 859 * Version number that is updated whenever this row or its related data 860 * changes. 861 * <P>Type: INTEGER</P> 862 */ 863 public static final String VERSION = "version"; 864 865 /** 866 * Flag indicating that {@link #VERSION} has changed, and this row needs 867 * to be synchronized by its owning account. 868 * <P>Type: INTEGER (boolean)</P> 869 */ 870 public static final String DIRTY = "dirty"; 871 } 872 873 /** 874 * Columns of {@link ContactsContract.Contacts} that track the user's 875 * preferences for, or interactions with, the contact. 876 * 877 * @see Contacts 878 * @see RawContacts 879 * @see ContactsContract.Data 880 * @see PhoneLookup 881 * @see ContactsContract.Contacts.AggregationSuggestions 882 */ 883 protected interface ContactOptionsColumns { 884 /** 885 * The number of times a contact has been contacted. 886 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 887 * this field is obsolete, regardless of Android version. For more information, see the 888 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 889 * page.</p> 890 * <P>Type: INTEGER</P> 891 * 892 * @deprecated Contacts affinity information is no longer supported as of 893 * Android version {@link android.os.Build.VERSION_CODES#Q}. This column 894 * always contains 0. 895 */ 896 @Deprecated 897 public static final String TIMES_CONTACTED = "times_contacted"; 898 899 /** 900 * The last time a contact was contacted. 901 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 902 * this field is obsolete, regardless of Android version. For more information, see the 903 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 904 * page.</p> 905 * <P>Type: INTEGER</P> 906 * 907 * @deprecated Contacts affinity information is no longer supported as of 908 * Android version {@link android.os.Build.VERSION_CODES#Q}. This column 909 * always contains 0. 910 */ 911 @Deprecated 912 public static final String LAST_TIME_CONTACTED = "last_time_contacted"; 913 914 /** @hide Raw value. */ 915 public static final String RAW_TIMES_CONTACTED = HIDDEN_COLUMN_PREFIX + TIMES_CONTACTED; 916 917 /** @hide Raw value. */ 918 public static final String RAW_LAST_TIME_CONTACTED = 919 HIDDEN_COLUMN_PREFIX + LAST_TIME_CONTACTED; 920 921 /** 922 * @hide 923 * Low res version. Same as {@link #TIMES_CONTACTED} but use it in CP2 for clarification. 924 */ 925 public static final String LR_TIMES_CONTACTED = TIMES_CONTACTED; 926 927 /** 928 * @hide 929 * Low res version. Same as {@link #TIMES_CONTACTED} but use it in CP2 for clarification. 930 */ 931 public static final String LR_LAST_TIME_CONTACTED = LAST_TIME_CONTACTED; 932 933 /** 934 * Is the contact starred? 935 * <P>Type: INTEGER (boolean)</P> 936 */ 937 public static final String STARRED = "starred"; 938 939 /** 940 * The position at which the contact is pinned. If {@link PinnedPositions#UNPINNED}, 941 * the contact is not pinned. Also see {@link PinnedPositions}. 942 * <P>Type: INTEGER </P> 943 */ 944 public static final String PINNED = "pinned"; 945 946 /** 947 * URI for a custom ringtone associated with the contact. If null or missing, 948 * the default ringtone is used. 949 * <P>Type: TEXT (URI to the ringtone)</P> 950 */ 951 public static final String CUSTOM_RINGTONE = "custom_ringtone"; 952 953 /** 954 * Whether the contact should always be sent to voicemail. If missing, 955 * defaults to false. 956 * <P>Type: INTEGER (0 for false, 1 for true)</P> 957 */ 958 public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; 959 } 960 961 /** 962 * Columns of {@link ContactsContract.Contacts} that refer to intrinsic 963 * properties of the contact, as opposed to the user-specified options 964 * found in {@link ContactOptionsColumns}. 965 * 966 * @see Contacts 967 * @see ContactsContract.Data 968 * @see PhoneLookup 969 * @see ContactsContract.Contacts.AggregationSuggestions 970 */ 971 protected interface ContactsColumns { 972 /** 973 * The display name for the contact. 974 * <P>Type: TEXT</P> 975 */ 976 public static final String DISPLAY_NAME = ContactNameColumns.DISPLAY_NAME_PRIMARY; 977 978 /** 979 * Reference to the row in the RawContacts table holding the contact name. 980 * <P>Type: INTEGER REFERENCES raw_contacts(_id)</P> 981 */ 982 public static final String NAME_RAW_CONTACT_ID = "name_raw_contact_id"; 983 984 /** 985 * Reference to the row in the data table holding the photo. A photo can 986 * be referred to either by ID (this field) or by URI (see {@link #PHOTO_THUMBNAIL_URI} 987 * and {@link #PHOTO_URI}). 988 * If PHOTO_ID is null, consult {@link #PHOTO_URI} or {@link #PHOTO_THUMBNAIL_URI}, 989 * which is a more generic mechanism for referencing the contact photo, especially for 990 * contacts returned by non-local directories (see {@link Directory}). 991 * 992 * <P>Type: INTEGER REFERENCES data(_id)</P> 993 */ 994 public static final String PHOTO_ID = "photo_id"; 995 996 /** 997 * Photo file ID of the full-size photo. If present, this will be used to populate 998 * {@link #PHOTO_URI}. The ID can also be used with 999 * {@link ContactsContract.DisplayPhoto#CONTENT_URI} to create a URI to the photo. 1000 * If this is present, {@link #PHOTO_ID} is also guaranteed to be populated. 1001 * 1002 * <P>Type: INTEGER</P> 1003 */ 1004 public static final String PHOTO_FILE_ID = "photo_file_id"; 1005 1006 /** 1007 * A URI that can be used to retrieve the contact's full-size photo. 1008 * If PHOTO_FILE_ID is not null, this will be populated with a URI based off 1009 * {@link ContactsContract.DisplayPhoto#CONTENT_URI}. Otherwise, this will 1010 * be populated with the same value as {@link #PHOTO_THUMBNAIL_URI}. 1011 * A photo can be referred to either by a URI (this field) or by ID 1012 * (see {@link #PHOTO_ID}). If either PHOTO_FILE_ID or PHOTO_ID is not null, 1013 * PHOTO_URI and PHOTO_THUMBNAIL_URI shall not be null (but not necessarily 1014 * vice versa). Thus using PHOTO_URI is a more robust method of retrieving 1015 * contact photos. 1016 * 1017 * <P>Type: TEXT</P> 1018 */ 1019 public static final String PHOTO_URI = "photo_uri"; 1020 1021 /** 1022 * A URI that can be used to retrieve a thumbnail of the contact's photo. 1023 * A photo can be referred to either by a URI (this field or {@link #PHOTO_URI}) 1024 * or by ID (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and 1025 * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa). 1026 * If the content provider does not differentiate between full-size photos 1027 * and thumbnail photos, PHOTO_THUMBNAIL_URI and {@link #PHOTO_URI} can contain 1028 * the same value, but either both shall be null or both not null. 1029 * 1030 * <P>Type: TEXT</P> 1031 */ 1032 public static final String PHOTO_THUMBNAIL_URI = "photo_thumb_uri"; 1033 1034 /** 1035 * Flag that reflects whether the contact exists inside the default directory. 1036 * Ie, whether the contact is designed to only be visible outside search. 1037 */ 1038 public static final String IN_DEFAULT_DIRECTORY = "in_default_directory"; 1039 1040 /** 1041 * Flag that reflects the {@link Groups#GROUP_VISIBLE} state of any 1042 * {@link CommonDataKinds.GroupMembership} for this contact. 1043 */ 1044 public static final String IN_VISIBLE_GROUP = "in_visible_group"; 1045 1046 /** 1047 * Flag that reflects whether this contact represents the user's 1048 * personal profile entry. 1049 */ 1050 public static final String IS_USER_PROFILE = "is_user_profile"; 1051 1052 /** 1053 * An indicator of whether this contact has at least one phone number. "1" if there is 1054 * at least one phone number, "0" otherwise. 1055 * <P>Type: INTEGER</P> 1056 */ 1057 public static final String HAS_PHONE_NUMBER = "has_phone_number"; 1058 1059 /** 1060 * An opaque value that contains hints on how to find the contact if 1061 * its row id changed as a result of a sync or aggregation. 1062 */ 1063 public static final String LOOKUP_KEY = "lookup"; 1064 1065 /** 1066 * Timestamp (milliseconds since epoch) of when this contact was last updated. This 1067 * includes updates to all data associated with this contact including raw contacts. Any 1068 * modification (including deletes and inserts) of underlying contact data are also 1069 * reflected in this timestamp. 1070 */ 1071 public static final String CONTACT_LAST_UPDATED_TIMESTAMP = 1072 "contact_last_updated_timestamp"; 1073 } 1074 1075 /** 1076 * @see Contacts 1077 */ 1078 protected interface ContactStatusColumns { 1079 /** 1080 * Contact presence status. See {@link StatusUpdates} for individual status 1081 * definitions. 1082 * <p>Type: NUMBER</p> 1083 */ 1084 public static final String CONTACT_PRESENCE = "contact_presence"; 1085 1086 /** 1087 * Contact Chat Capabilities. See {@link StatusUpdates} for individual 1088 * definitions. 1089 * <p>Type: NUMBER</p> 1090 */ 1091 public static final String CONTACT_CHAT_CAPABILITY = "contact_chat_capability"; 1092 1093 /** 1094 * Contact's latest status update. 1095 * <p>Type: TEXT</p> 1096 */ 1097 public static final String CONTACT_STATUS = "contact_status"; 1098 1099 /** 1100 * The absolute time in milliseconds when the latest status was 1101 * inserted/updated. 1102 * <p>Type: NUMBER</p> 1103 */ 1104 public static final String CONTACT_STATUS_TIMESTAMP = "contact_status_ts"; 1105 1106 /** 1107 * The package containing resources for this status: label and icon. 1108 * <p>Type: TEXT</p> 1109 */ 1110 public static final String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package"; 1111 1112 /** 1113 * The resource ID of the label describing the source of contact 1114 * status, e.g. "Google Talk". This resource is scoped by the 1115 * {@link #CONTACT_STATUS_RES_PACKAGE}. 1116 * <p>Type: NUMBER</p> 1117 */ 1118 public static final String CONTACT_STATUS_LABEL = "contact_status_label"; 1119 1120 /** 1121 * The resource ID of the icon for the source of contact status. This 1122 * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}. 1123 * <p>Type: NUMBER</p> 1124 */ 1125 public static final String CONTACT_STATUS_ICON = "contact_status_icon"; 1126 } 1127 1128 /** 1129 * Constants for various styles of combining given name, family name etc into 1130 * a full name. For example, the western tradition follows the pattern 1131 * 'given name' 'middle name' 'family name' with the alternative pattern being 1132 * 'family name', 'given name' 'middle name'. The CJK tradition is 1133 * 'family name' 'middle name' 'given name', with Japanese favoring a space between 1134 * the names and Chinese omitting the space. 1135 */ 1136 public interface FullNameStyle { 1137 public static final int UNDEFINED = 0; 1138 public static final int WESTERN = 1; 1139 1140 /** 1141 * Used if the name is written in Hanzi/Kanji/Hanja and we could not determine 1142 * which specific language it belongs to: Chinese, Japanese or Korean. 1143 */ 1144 public static final int CJK = 2; 1145 1146 public static final int CHINESE = 3; 1147 public static final int JAPANESE = 4; 1148 public static final int KOREAN = 5; 1149 } 1150 1151 /** 1152 * Constants for various styles of capturing the pronunciation of a person's name. 1153 */ 1154 public interface PhoneticNameStyle { 1155 public static final int UNDEFINED = 0; 1156 1157 /** 1158 * Pinyin is a phonetic method of entering Chinese characters. Typically not explicitly 1159 * shown in UIs, but used for searches and sorting. 1160 */ 1161 public static final int PINYIN = 3; 1162 1163 /** 1164 * Hiragana and Katakana are two common styles of writing out the pronunciation 1165 * of a Japanese names. 1166 */ 1167 public static final int JAPANESE = 4; 1168 1169 /** 1170 * Hangul is the Korean phonetic alphabet. 1171 */ 1172 public static final int KOREAN = 5; 1173 } 1174 1175 /** 1176 * Types of data used to produce the display name for a contact. In the order 1177 * of increasing priority: {@link #EMAIL}, {@link #PHONE}, 1178 * {@link #ORGANIZATION}, {@link #NICKNAME}, {@link #STRUCTURED_PHONETIC_NAME}, 1179 * {@link #STRUCTURED_NAME}. 1180 */ 1181 public interface DisplayNameSources { 1182 public static final int UNDEFINED = 0; 1183 public static final int EMAIL = 10; 1184 public static final int PHONE = 20; 1185 public static final int ORGANIZATION = 30; 1186 public static final int NICKNAME = 35; 1187 /** Display name comes from a structured name that only has phonetic components. */ 1188 public static final int STRUCTURED_PHONETIC_NAME = 37; 1189 public static final int STRUCTURED_NAME = 40; 1190 } 1191 1192 /** 1193 * Contact name and contact name metadata columns in the RawContacts table. 1194 * 1195 * @see Contacts 1196 * @see RawContacts 1197 */ 1198 protected interface ContactNameColumns { 1199 1200 /** 1201 * The kind of data that is used as the display name for the contact, such as 1202 * structured name or email address. See {@link DisplayNameSources}. 1203 */ 1204 public static final String DISPLAY_NAME_SOURCE = "display_name_source"; 1205 1206 /** 1207 * <p> 1208 * The standard text shown as the contact's display name, based on the best 1209 * available information for the contact (for example, it might be the email address 1210 * if the name is not available). 1211 * The information actually used to compute the name is stored in 1212 * {@link #DISPLAY_NAME_SOURCE}. 1213 * </p> 1214 * <p> 1215 * A contacts provider is free to choose whatever representation makes most 1216 * sense for its target market. 1217 * For example in the default Android Open Source Project implementation, 1218 * if the display name is 1219 * based on the structured name and the structured name follows 1220 * the Western full-name style, then this field contains the "given name first" 1221 * version of the full name. 1222 * <p> 1223 * 1224 * @see ContactsContract.ContactNameColumns#DISPLAY_NAME_ALTERNATIVE 1225 */ 1226 public static final String DISPLAY_NAME_PRIMARY = "display_name"; 1227 1228 /** 1229 * <p> 1230 * An alternative representation of the display name, such as "family name first" 1231 * instead of "given name first" for Western names. If an alternative is not 1232 * available, the values should be the same as {@link #DISPLAY_NAME_PRIMARY}. 1233 * </p> 1234 * <p> 1235 * A contacts provider is free to provide alternatives as necessary for 1236 * its target market. 1237 * For example the default Android Open Source Project contacts provider 1238 * currently provides an 1239 * alternative in a single case: if the display name is 1240 * based on the structured name and the structured name follows 1241 * the Western full name style, then the field contains the "family name first" 1242 * version of the full name. 1243 * Other cases may be added later. 1244 * </p> 1245 */ 1246 public static final String DISPLAY_NAME_ALTERNATIVE = "display_name_alt"; 1247 1248 /** 1249 * The phonetic alphabet used to represent the {@link #PHONETIC_NAME}. See 1250 * {@link PhoneticNameStyle}. 1251 */ 1252 public static final String PHONETIC_NAME_STYLE = "phonetic_name_style"; 1253 1254 /** 1255 * <p> 1256 * Pronunciation of the full name in the phonetic alphabet specified by 1257 * {@link #PHONETIC_NAME_STYLE}. 1258 * </p> 1259 * <p> 1260 * The value may be set manually by the user. This capability is of 1261 * interest only in countries with commonly used phonetic alphabets, 1262 * such as Japan and Korea. See {@link PhoneticNameStyle}. 1263 * </p> 1264 */ 1265 public static final String PHONETIC_NAME = "phonetic_name"; 1266 1267 /** 1268 * Sort key that takes into account locale-based traditions for sorting 1269 * names in address books. The default 1270 * sort key is {@link #DISPLAY_NAME_PRIMARY}. For Chinese names 1271 * the sort key is the name's Pinyin spelling, and for Japanese names 1272 * it is the Hiragana version of the phonetic name. 1273 */ 1274 public static final String SORT_KEY_PRIMARY = "sort_key"; 1275 1276 /** 1277 * Sort key based on the alternative representation of the full name, 1278 * {@link #DISPLAY_NAME_ALTERNATIVE}. Thus for Western names, 1279 * it is the one using the "family name first" format. 1280 */ 1281 public static final String SORT_KEY_ALTERNATIVE = "sort_key_alt"; 1282 } 1283 1284 interface ContactCounts { 1285 1286 /** 1287 * Add this query parameter to a URI to get back row counts grouped by the address book 1288 * index as cursor extras. For most languages it is the first letter of the sort key. This 1289 * parameter does not affect the main content of the cursor. 1290 * 1291 * <p> 1292 * <pre> 1293 * Example: 1294 * 1295 * import android.provider.ContactsContract.Contacts; 1296 * 1297 * Uri uri = Contacts.CONTENT_URI.buildUpon() 1298 * .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true") 1299 * .build(); 1300 * Cursor cursor = getContentResolver().query(uri, 1301 * new String[] {Contacts.DISPLAY_NAME}, 1302 * null, null, null); 1303 * Bundle bundle = cursor.getExtras(); 1304 * if (bundle.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES) && 1305 * bundle.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS)) { 1306 * String sections[] = 1307 * bundle.getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES); 1308 * int counts[] = bundle.getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS); 1309 * } 1310 * </pre> 1311 * </p> 1312 */ 1313 public static final String EXTRA_ADDRESS_BOOK_INDEX = 1314 "android.provider.extra.ADDRESS_BOOK_INDEX"; 1315 1316 /** 1317 * The array of address book index titles, which are returned in the 1318 * same order as the data in the cursor. 1319 * <p>TYPE: String[]</p> 1320 */ 1321 public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES = 1322 "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; 1323 1324 /** 1325 * The array of group counts for the corresponding group. Contains the same number 1326 * of elements as the EXTRA_ADDRESS_BOOK_INDEX_TITLES array. 1327 * <p>TYPE: int[]</p> 1328 */ 1329 public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = 1330 "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; 1331 } 1332 1333 /** 1334 * Constants for the contacts table, which contains a record per aggregate 1335 * of raw contacts representing the same person. 1336 * <h3>Operations</h3> 1337 * <dl> 1338 * <dt><b>Insert</b></dt> 1339 * <dd>A Contact cannot be created explicitly. When a raw contact is 1340 * inserted, the provider will first try to find a Contact representing the 1341 * same person. If one is found, the raw contact's 1342 * {@link RawContacts#CONTACT_ID} column gets the _ID of the aggregate 1343 * Contact. If no match is found, the provider automatically inserts a new 1344 * Contact and puts its _ID into the {@link RawContacts#CONTACT_ID} column 1345 * of the newly inserted raw contact.</dd> 1346 * <dt><b>Update</b></dt> 1347 * <dd>Only certain columns of Contact are modifiable: 1348 * {@link #STARRED}, {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of 1349 * these columns on the Contact also changes them on all constituent raw 1350 * contacts.</dd> 1351 * <dt><b>Delete</b></dt> 1352 * <dd>Be careful with deleting Contacts! Deleting an aggregate contact 1353 * deletes all constituent raw contacts. The corresponding sync adapters 1354 * will notice the deletions of their respective raw contacts and remove 1355 * them from their back end storage.</dd> 1356 * <dt><b>Query</b></dt> 1357 * <dd> 1358 * <ul> 1359 * <li>If you need to read an individual contact, consider using 1360 * {@link #CONTENT_LOOKUP_URI} instead of {@link #CONTENT_URI}.</li> 1361 * <li>If you need to look up a contact by the phone number, use 1362 * {@link PhoneLookup#CONTENT_FILTER_URI PhoneLookup.CONTENT_FILTER_URI}, 1363 * which is optimized for this purpose.</li> 1364 * <li>If you need to look up a contact by partial name, e.g. to produce 1365 * filter-as-you-type suggestions, use the {@link #CONTENT_FILTER_URI} URI. 1366 * <li>If you need to look up a contact by some data element like email 1367 * address, nickname, etc, use a query against the {@link ContactsContract.Data} table. 1368 * The result will contain contact ID, name etc. 1369 * </ul> 1370 * </dd> 1371 * </dl> 1372 * <h2>Columns</h2> 1373 * <table class="jd-sumtable"> 1374 * <tr> 1375 * <th colspan='4'>Contacts</th> 1376 * </tr> 1377 * <tr> 1378 * <td>long</td> 1379 * <td>{@link #_ID}</td> 1380 * <td>read-only</td> 1381 * <td>Row ID. Consider using {@link #LOOKUP_KEY} instead.</td> 1382 * </tr> 1383 * <tr> 1384 * <td>String</td> 1385 * <td>{@link #LOOKUP_KEY}</td> 1386 * <td>read-only</td> 1387 * <td>An opaque value that contains hints on how to find the contact if its 1388 * row id changed as a result of a sync or aggregation.</td> 1389 * </tr> 1390 * <tr> 1391 * <td>long</td> 1392 * <td>NAME_RAW_CONTACT_ID</td> 1393 * <td>read-only</td> 1394 * <td>The ID of the raw contact that contributes the display name 1395 * to the aggregate contact. During aggregation one of the constituent 1396 * raw contacts is chosen using a heuristic: a longer name or a name 1397 * with more diacritic marks or more upper case characters is chosen.</td> 1398 * </tr> 1399 * <tr> 1400 * <td>String</td> 1401 * <td>DISPLAY_NAME_PRIMARY</td> 1402 * <td>read-only</td> 1403 * <td>The display name for the contact. It is the display name 1404 * contributed by the raw contact referred to by the NAME_RAW_CONTACT_ID 1405 * column.</td> 1406 * </tr> 1407 * <tr> 1408 * <td>long</td> 1409 * <td>{@link #PHOTO_ID}</td> 1410 * <td>read-only</td> 1411 * <td>Reference to the row in the {@link ContactsContract.Data} table holding the photo. 1412 * That row has the mime type 1413 * {@link CommonDataKinds.Photo#CONTENT_ITEM_TYPE}. The value of this field 1414 * is computed automatically based on the 1415 * {@link CommonDataKinds.Photo#IS_SUPER_PRIMARY} field of the data rows of 1416 * that mime type.</td> 1417 * </tr> 1418 * <tr> 1419 * <td>long</td> 1420 * <td>{@link #PHOTO_URI}</td> 1421 * <td>read-only</td> 1422 * <td>A URI that can be used to retrieve the contact's full-size photo. This 1423 * column is the preferred method of retrieving the contact photo.</td> 1424 * </tr> 1425 * <tr> 1426 * <td>long</td> 1427 * <td>{@link #PHOTO_THUMBNAIL_URI}</td> 1428 * <td>read-only</td> 1429 * <td>A URI that can be used to retrieve the thumbnail of contact's photo. This 1430 * column is the preferred method of retrieving the contact photo.</td> 1431 * </tr> 1432 * <tr> 1433 * <td>int</td> 1434 * <td>{@link #IN_VISIBLE_GROUP}</td> 1435 * <td>read-only</td> 1436 * <td>An indicator of whether this contact is supposed to be visible in the 1437 * UI. "1" if the contact has at least one raw contact that belongs to a 1438 * visible group; "0" otherwise.</td> 1439 * </tr> 1440 * <tr> 1441 * <td>int</td> 1442 * <td>{@link #HAS_PHONE_NUMBER}</td> 1443 * <td>read-only</td> 1444 * <td>An indicator of whether this contact has at least one phone number. 1445 * "1" if there is at least one phone number, "0" otherwise.</td> 1446 * </tr> 1447 * <tr> 1448 * <td>int</td> 1449 * <td>{@link #STARRED}</td> 1450 * <td>read/write</td> 1451 * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise. 1452 * When raw contacts are aggregated, this field is automatically computed: 1453 * if any constituent raw contacts are starred, then this field is set to 1454 * '1'. Setting this field automatically changes the corresponding field on 1455 * all constituent raw contacts.</td> 1456 * </tr> 1457 * <tr> 1458 * <td>String</td> 1459 * <td>{@link #CUSTOM_RINGTONE}</td> 1460 * <td>read/write</td> 1461 * <td>A custom ringtone associated with a contact. Typically this is the 1462 * URI returned by an activity launched with the 1463 * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent.</td> 1464 * </tr> 1465 * <tr> 1466 * <td>int</td> 1467 * <td>{@link #SEND_TO_VOICEMAIL}</td> 1468 * <td>read/write</td> 1469 * <td>An indicator of whether calls from this contact should be forwarded 1470 * directly to voice mail ('1') or not ('0'). When raw contacts are 1471 * aggregated, this field is automatically computed: if <i>all</i> 1472 * constituent raw contacts have SEND_TO_VOICEMAIL=1, then this field is set 1473 * to '1'. Setting this field automatically changes the corresponding field 1474 * on all constituent raw contacts.</td> 1475 * </tr> 1476 * <tr> 1477 * <td>int</td> 1478 * <td>{@link #CONTACT_PRESENCE}</td> 1479 * <td>read-only</td> 1480 * <td>Contact IM presence status. See {@link StatusUpdates} for individual 1481 * status definitions. Automatically computed as the highest presence of all 1482 * constituent raw contacts. The provider may choose not to store this value 1483 * in persistent storage. The expectation is that presence status will be 1484 * updated on a regular basis.</td> 1485 * </tr> 1486 * <tr> 1487 * <td>String</td> 1488 * <td>{@link #CONTACT_STATUS}</td> 1489 * <td>read-only</td> 1490 * <td>Contact's latest status update. Automatically computed as the latest 1491 * of all constituent raw contacts' status updates.</td> 1492 * </tr> 1493 * <tr> 1494 * <td>long</td> 1495 * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td> 1496 * <td>read-only</td> 1497 * <td>The absolute time in milliseconds when the latest status was 1498 * inserted/updated.</td> 1499 * </tr> 1500 * <tr> 1501 * <td>String</td> 1502 * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td> 1503 * <td>read-only</td> 1504 * <td> The package containing resources for this status: label and icon.</td> 1505 * </tr> 1506 * <tr> 1507 * <td>long</td> 1508 * <td>{@link #CONTACT_STATUS_LABEL}</td> 1509 * <td>read-only</td> 1510 * <td>The resource ID of the label describing the source of contact status, 1511 * e.g. "Google Talk". This resource is scoped by the 1512 * {@link #CONTACT_STATUS_RES_PACKAGE}.</td> 1513 * </tr> 1514 * <tr> 1515 * <td>long</td> 1516 * <td>{@link #CONTACT_STATUS_ICON}</td> 1517 * <td>read-only</td> 1518 * <td>The resource ID of the icon for the source of contact status. This 1519 * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}.</td> 1520 * </tr> 1521 * </table> 1522 */ 1523 public static class Contacts implements BaseColumns, ContactsColumns, 1524 ContactOptionsColumns, ContactNameColumns, ContactStatusColumns, ContactCounts { 1525 /** 1526 * This utility class cannot be instantiated 1527 */ Contacts()1528 private Contacts() {} 1529 1530 /** 1531 * The content:// style URI for this table 1532 */ 1533 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts"); 1534 1535 /** 1536 * Special contacts URI to refer to contacts on the corp profile from the personal 1537 * profile. 1538 * 1539 * It's supported only by a few specific places for referring to contact pictures that 1540 * are in the corp provider for enterprise caller-ID. Contact picture URIs returned from 1541 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI} may contain this kind of URI. 1542 * 1543 * @hide 1544 */ 1545 @UnsupportedAppUsage 1546 public static final Uri CORP_CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, 1547 "contacts_corp"); 1548 1549 /** 1550 * A content:// style URI for this table that should be used to create 1551 * shortcuts or otherwise create long-term links to contacts. This URI 1552 * should always be followed by a "/" and the contact's {@link #LOOKUP_KEY}. 1553 * It can optionally also have a "/" and last known contact ID appended after 1554 * that. This "complete" format is an important optimization and is highly recommended. 1555 * <p> 1556 * As long as the contact's row ID remains the same, this URI is 1557 * equivalent to {@link #CONTENT_URI}. If the contact's row ID changes 1558 * as a result of a sync or aggregation, this URI will look up the 1559 * contact using indirect information (sync IDs or constituent raw 1560 * contacts). 1561 * <p> 1562 * Lookup key should be appended unencoded - it is stored in the encoded 1563 * form, ready for use in a URI. 1564 */ 1565 public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, 1566 "lookup"); 1567 1568 /** 1569 * Base {@link Uri} for referencing a single {@link Contacts} entry, 1570 * created by appending {@link #LOOKUP_KEY} using 1571 * {@link Uri#withAppendedPath(Uri, String)}. Provides 1572 * {@link OpenableColumns} columns when queried, or returns the 1573 * referenced contact formatted as a vCard when opened through 1574 * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. 1575 */ 1576 public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, 1577 "as_vcard"); 1578 1579 /** 1580 * Boolean parameter that may be used with {@link #CONTENT_VCARD_URI} 1581 * and {@link #CONTENT_MULTI_VCARD_URI} to indicate that the returned 1582 * vcard should not contain a photo. 1583 * 1584 * This is useful for obtaining a space efficient vcard. 1585 */ 1586 public static final String QUERY_PARAMETER_VCARD_NO_PHOTO = "no_photo"; 1587 1588 /** 1589 * Base {@link Uri} for referencing multiple {@link Contacts} entry, 1590 * created by appending {@link #LOOKUP_KEY} using 1591 * {@link Uri#withAppendedPath(Uri, String)}. The lookup keys have to be 1592 * joined with the colon (":") separator, and the resulting string encoded. 1593 * 1594 * Provides {@link OpenableColumns} columns when queried, or returns the 1595 * referenced contact formatted as a vCard when opened through 1596 * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. 1597 * 1598 * <p> 1599 * Usage example: 1600 * <dl> 1601 * <dt>The following code snippet creates a multi-vcard URI that references all the 1602 * contacts in a user's database.</dt> 1603 * <dd> 1604 * 1605 * <pre> 1606 * public Uri getAllContactsVcardUri() { 1607 * Cursor cursor = getActivity().getContentResolver().query(Contacts.CONTENT_URI, 1608 * new String[] {Contacts.LOOKUP_KEY}, null, null, null); 1609 * if (cursor == null) { 1610 * return null; 1611 * } 1612 * try { 1613 * StringBuilder uriListBuilder = new StringBuilder(); 1614 * int index = 0; 1615 * while (cursor.moveToNext()) { 1616 * if (index != 0) uriListBuilder.append(':'); 1617 * uriListBuilder.append(cursor.getString(0)); 1618 * index++; 1619 * } 1620 * return Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI, 1621 * Uri.encode(uriListBuilder.toString())); 1622 * } finally { 1623 * cursor.close(); 1624 * } 1625 * } 1626 * </pre> 1627 * 1628 * </p> 1629 */ 1630 public static final Uri CONTENT_MULTI_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, 1631 "as_multi_vcard"); 1632 1633 /** 1634 * Builds a {@link #CONTENT_LOOKUP_URI} style {@link Uri} describing the 1635 * requested {@link Contacts} entry. 1636 * 1637 * @param contactUri A {@link #CONTENT_URI} row, or an existing 1638 * {@link #CONTENT_LOOKUP_URI} to attempt refreshing. 1639 */ getLookupUri(ContentResolver resolver, Uri contactUri)1640 public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) { 1641 final Cursor c = resolver.query(contactUri, new String[] { 1642 Contacts.LOOKUP_KEY, Contacts._ID 1643 }, null, null, null); 1644 if (c == null) { 1645 return null; 1646 } 1647 1648 try { 1649 if (c.moveToFirst()) { 1650 final String lookupKey = c.getString(0); 1651 final long contactId = c.getLong(1); 1652 return getLookupUri(contactId, lookupKey); 1653 } 1654 } finally { 1655 c.close(); 1656 } 1657 return null; 1658 } 1659 1660 /** 1661 * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the 1662 * given {@link ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}. 1663 * <p> 1664 * Returns null if unable to construct a valid lookup URI from the 1665 * provided parameters. 1666 */ getLookupUri(long contactId, String lookupKey)1667 public static Uri getLookupUri(long contactId, String lookupKey) { 1668 if (TextUtils.isEmpty(lookupKey)) { 1669 return null; 1670 } 1671 return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, 1672 lookupKey), contactId); 1673 } 1674 1675 /** 1676 * Computes a content URI (see {@link #CONTENT_URI}) given a lookup URI. 1677 * <p> 1678 * Returns null if the contact cannot be found. 1679 */ lookupContact(ContentResolver resolver, Uri lookupUri)1680 public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) { 1681 if (lookupUri == null) { 1682 return null; 1683 } 1684 1685 Cursor c = resolver.query(lookupUri, new String[]{Contacts._ID}, null, null, null); 1686 if (c == null) { 1687 return null; 1688 } 1689 1690 try { 1691 if (c.moveToFirst()) { 1692 long contactId = c.getLong(0); 1693 return ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1694 } 1695 } finally { 1696 c.close(); 1697 } 1698 return null; 1699 } 1700 1701 /** 1702 * Mark a contact as having been contacted. Updates two fields: 1703 * {@link #TIMES_CONTACTED} and {@link #LAST_TIME_CONTACTED}. The 1704 * TIMES_CONTACTED field is incremented by 1 and the LAST_TIME_CONTACTED 1705 * field is populated with the current system time. 1706 * 1707 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 1708 * this field is obsolete, regardless of Android version. For more information, see the 1709 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 1710 * page.</p> 1711 * 1712 * @param resolver the ContentResolver to use 1713 * @param contactId the person who was contacted 1714 * 1715 * @deprecated Contacts affinity information is no longer supported as of 1716 * Android version {@link android.os.Build.VERSION_CODES#Q}. This method 1717 * is no-op. 1718 */ 1719 @Deprecated markAsContacted(ContentResolver resolver, long contactId)1720 public static void markAsContacted(ContentResolver resolver, long contactId) { 1721 } 1722 1723 /** 1724 * The content:// style URI used for "type-to-filter" functionality on the 1725 * {@link #CONTENT_URI} URI. The filter string will be used to match 1726 * various parts of the contact name. The filter argument should be passed 1727 * as an additional path segment after this URI. 1728 */ 1729 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath( 1730 CONTENT_URI, "filter"); 1731 1732 /** 1733 * It supports the similar semantics as {@link #CONTENT_FILTER_URI} and returns the same 1734 * columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in parameters, 1735 * otherwise it will throw IllegalArgumentException. 1736 */ 1737 public static final Uri ENTERPRISE_CONTENT_FILTER_URI = Uri.withAppendedPath( 1738 CONTENT_URI, "filter_enterprise"); 1739 1740 /** 1741 * The content:// style URI for this table joined with useful data from 1742 * {@link ContactsContract.Data}, filtered to include only starred contacts. 1743 * Frequent contacts are no longer included in the result as of 1744 * Android version {@link android.os.Build.VERSION_CODES#Q}. 1745 * 1746 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this 1747 * field doesn't sort results based on contacts frequency. For more information, see the 1748 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 1749 * page. 1750 */ 1751 public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath( 1752 CONTENT_URI, "strequent"); 1753 1754 /** 1755 * The content:// style URI for showing a list of frequently contacted people. 1756 * 1757 * @deprecated Frequent contacts are no longer supported as of 1758 * Android version {@link android.os.Build.VERSION_CODES#Q}. 1759 * This URI always returns an empty cursor. 1760 * 1761 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this 1762 * field doesn't sort results based on contacts frequency. For more information, see the 1763 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 1764 * page. 1765 */ 1766 @Deprecated 1767 public static final Uri CONTENT_FREQUENT_URI = Uri.withAppendedPath( 1768 CONTENT_URI, "frequent"); 1769 1770 /** 1771 * <p>The content:// style URI used for "type-to-filter" functionality on the 1772 * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match 1773 * various parts of the contact name. The filter argument should be passed 1774 * as an additional path segment after this URI. 1775 * 1776 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this 1777 * field doesn't sort results based on contacts frequency. For more information, see the 1778 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 1779 * page. 1780 */ 1781 public static final Uri CONTENT_STREQUENT_FILTER_URI = Uri.withAppendedPath( 1782 CONTENT_STREQUENT_URI, "filter"); 1783 1784 public static final Uri CONTENT_GROUP_URI = Uri.withAppendedPath( 1785 CONTENT_URI, "group"); 1786 1787 /** 1788 * The MIME type of {@link #CONTENT_URI} providing a directory of 1789 * people. 1790 */ 1791 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact"; 1792 1793 /** 1794 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 1795 * person. 1796 */ 1797 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact"; 1798 1799 /** 1800 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 1801 * person. 1802 */ 1803 public static final String CONTENT_VCARD_TYPE = "text/x-vcard"; 1804 1805 /** 1806 * Mimimal ID for corp contacts returned from 1807 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}. 1808 * 1809 * @hide 1810 */ 1811 public static long ENTERPRISE_CONTACT_ID_BASE = 1000000000; // slightly smaller than 2 ** 30 1812 1813 /** 1814 * Prefix for corp contacts returned from 1815 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}. 1816 * 1817 * @hide 1818 */ 1819 public static String ENTERPRISE_CONTACT_LOOKUP_PREFIX = "c-"; 1820 1821 /** 1822 * Return TRUE if a contact ID is from the contacts provider on the enterprise profile. 1823 * 1824 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI} may return such a contact. 1825 */ isEnterpriseContactId(long contactId)1826 public static boolean isEnterpriseContactId(long contactId) { 1827 return (contactId >= ENTERPRISE_CONTACT_ID_BASE) && (contactId < Profile.MIN_ID); 1828 } 1829 1830 /** 1831 * A sub-directory of a single contact that contains all of the constituent raw contact 1832 * {@link ContactsContract.Data} rows. This directory can be used either 1833 * with a {@link #CONTENT_URI} or {@link #CONTENT_LOOKUP_URI}. 1834 */ 1835 public static final class Data implements BaseColumns, DataColumns { 1836 /** 1837 * no public constructor since this is a utility class 1838 */ Data()1839 private Data() {} 1840 1841 /** 1842 * The directory twig for this sub-table 1843 */ 1844 public static final String CONTENT_DIRECTORY = "data"; 1845 } 1846 1847 /** 1848 * <p> 1849 * A sub-directory of a contact that contains all of its 1850 * {@link ContactsContract.RawContacts} as well as 1851 * {@link ContactsContract.Data} rows. To access this directory append 1852 * {@link #CONTENT_DIRECTORY} to the contact URI. 1853 * </p> 1854 * <p> 1855 * Entity has three ID fields: {@link #CONTACT_ID} for the contact, 1856 * {@link #RAW_CONTACT_ID} for the raw contact and {@link #DATA_ID} for 1857 * the data rows. Entity always contains at least one row per 1858 * constituent raw contact, even if there are no actual data rows. In 1859 * this case the {@link #DATA_ID} field will be null. 1860 * </p> 1861 * <p> 1862 * Entity reads all data for the entire contact in one transaction, to 1863 * guarantee consistency. There is significant data duplication 1864 * in the Entity (each row repeats all Contact columns and all RawContact 1865 * columns), so the benefits of transactional consistency should be weighed 1866 * against the cost of transferring large amounts of denormalized data 1867 * from the Provider. 1868 * </p> 1869 * <p> 1870 * To reduce the amount of data duplication the contacts provider and directory 1871 * providers implementing this protocol are allowed to provide common Contacts 1872 * and RawContacts fields in the first row returned for each raw contact only and 1873 * leave them as null in subsequent rows. 1874 * </p> 1875 */ 1876 public static final class Entity implements BaseColumns, ContactsColumns, 1877 ContactNameColumns, RawContactsColumns, BaseSyncColumns, SyncColumns, DataColumns, 1878 StatusColumns, ContactOptionsColumns, ContactStatusColumns, DataUsageStatColumns { 1879 /** 1880 * no public constructor since this is a utility class 1881 */ Entity()1882 private Entity() { 1883 } 1884 1885 /** 1886 * The directory twig for this sub-table 1887 */ 1888 public static final String CONTENT_DIRECTORY = "entities"; 1889 1890 /** 1891 * The ID of the raw contact row. 1892 * <P>Type: INTEGER</P> 1893 */ 1894 public static final String RAW_CONTACT_ID = "raw_contact_id"; 1895 1896 /** 1897 * The ID of the data row. The value will be null if this raw contact has no 1898 * data rows. 1899 * <P>Type: INTEGER</P> 1900 */ 1901 public static final String DATA_ID = "data_id"; 1902 } 1903 1904 /** 1905 * <p> 1906 * A sub-directory of a single contact that contains all of the constituent raw contact 1907 * {@link ContactsContract.StreamItems} rows. This directory can be used either 1908 * with a {@link #CONTENT_URI} or {@link #CONTENT_LOOKUP_URI}. 1909 * </p> 1910 * <p> 1911 * Querying for social stream data requires android.permission.READ_SOCIAL_STREAM 1912 * permission. 1913 * </p> 1914 * 1915 * @deprecated - Do not use. This will not be supported in the future. In the future, 1916 * cursors returned from related queries will be empty. 1917 * 1918 * @removed 1919 */ 1920 @Deprecated 1921 public static final class StreamItems implements StreamItemsColumns { 1922 /** 1923 * no public constructor since this is a utility class 1924 * 1925 * @deprecated - Do not use. This will not be supported in the future. In the future, 1926 * cursors returned from related queries will be empty. 1927 */ 1928 @Deprecated StreamItems()1929 private StreamItems() {} 1930 1931 /** 1932 * The directory twig for this sub-table 1933 * 1934 * @deprecated - Do not use. This will not be supported in the future. In the future, 1935 * cursors returned from related queries will be empty. 1936 */ 1937 @Deprecated 1938 public static final String CONTENT_DIRECTORY = "stream_items"; 1939 } 1940 1941 /** 1942 * <p> 1943 * A <i>read-only</i> sub-directory of a single contact aggregate that 1944 * contains all aggregation suggestions (other contacts). The 1945 * aggregation suggestions are computed based on approximate data 1946 * matches with this contact. 1947 * </p> 1948 * <p> 1949 * <i>Note: this query may be expensive! If you need to use it in bulk, 1950 * make sure the user experience is acceptable when the query runs for a 1951 * long time.</i> 1952 * <p> 1953 * Usage example: 1954 * 1955 * <pre> 1956 * Uri uri = Contacts.CONTENT_URI.buildUpon() 1957 * .appendEncodedPath(String.valueOf(contactId)) 1958 * .appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY) 1959 * .appendQueryParameter("limit", "3") 1960 * .build() 1961 * Cursor cursor = getContentResolver().query(suggestionsUri, 1962 * new String[] {Contacts.DISPLAY_NAME, Contacts._ID, Contacts.LOOKUP_KEY}, 1963 * null, null, null); 1964 * </pre> 1965 * 1966 * </p> 1967 * <p> 1968 * This directory can be used either with a {@link #CONTENT_URI} or 1969 * {@link #CONTENT_LOOKUP_URI}. 1970 * </p> 1971 */ 1972 public static final class AggregationSuggestions implements BaseColumns, ContactsColumns, 1973 ContactOptionsColumns, ContactStatusColumns { 1974 /** 1975 * No public constructor since this is a utility class 1976 */ AggregationSuggestions()1977 private AggregationSuggestions() {} 1978 1979 /** 1980 * The directory twig for this sub-table. The URI can be followed by an optional 1981 * type-to-filter, similar to 1982 * {@link android.provider.ContactsContract.Contacts#CONTENT_FILTER_URI}. 1983 */ 1984 public static final String CONTENT_DIRECTORY = "suggestions"; 1985 1986 /** 1987 * Used to specify what kind of data is supplied for the suggestion query. 1988 * 1989 * @hide 1990 */ 1991 public static final String PARAMETER_MATCH_NAME = "name"; 1992 1993 /** 1994 * A convenience builder for aggregation suggestion content URIs. 1995 */ 1996 public static final class Builder { 1997 private long mContactId; 1998 private final ArrayList<String> mValues = new ArrayList<String>(); 1999 private int mLimit; 2000 2001 /** 2002 * Optional existing contact ID. If it is not provided, the search 2003 * will be based exclusively on the values supplied with {@link #addNameParameter}. 2004 * 2005 * @param contactId contact to find aggregation suggestions for 2006 * @return This Builder object to allow for chaining of calls to builder methods 2007 */ setContactId(long contactId)2008 public Builder setContactId(long contactId) { 2009 this.mContactId = contactId; 2010 return this; 2011 } 2012 2013 /** 2014 * Add a name to be used when searching for aggregation suggestions. 2015 * 2016 * @param name name to find aggregation suggestions for 2017 * @return This Builder object to allow for chaining of calls to builder methods 2018 */ addNameParameter(String name)2019 public Builder addNameParameter(String name) { 2020 mValues.add(name); 2021 return this; 2022 } 2023 2024 /** 2025 * Sets the Maximum number of suggested aggregations that should be returned. 2026 * @param limit The maximum number of suggested aggregations 2027 * 2028 * @return This Builder object to allow for chaining of calls to builder methods 2029 */ setLimit(int limit)2030 public Builder setLimit(int limit) { 2031 mLimit = limit; 2032 return this; 2033 } 2034 2035 /** 2036 * Combine all of the options that have been set and return a new {@link Uri} 2037 * object for fetching aggregation suggestions. 2038 */ build()2039 public Uri build() { 2040 android.net.Uri.Builder builder = Contacts.CONTENT_URI.buildUpon(); 2041 builder.appendEncodedPath(String.valueOf(mContactId)); 2042 builder.appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY); 2043 if (mLimit != 0) { 2044 builder.appendQueryParameter("limit", String.valueOf(mLimit)); 2045 } 2046 2047 int count = mValues.size(); 2048 for (int i = 0; i < count; i++) { 2049 builder.appendQueryParameter("query", PARAMETER_MATCH_NAME 2050 + ":" + mValues.get(i)); 2051 } 2052 2053 return builder.build(); 2054 } 2055 } 2056 2057 /** 2058 * @hide 2059 */ 2060 @UnsupportedAppUsage builder()2061 public static final Builder builder() { 2062 return new Builder(); 2063 } 2064 } 2065 2066 /** 2067 * A <i>read-only</i> sub-directory of a single contact that contains 2068 * the contact's primary photo. The photo may be stored in up to two ways - 2069 * the default "photo" is a thumbnail-sized image stored directly in the data 2070 * row, while the "display photo", if present, is a larger version stored as 2071 * a file. 2072 * <p> 2073 * Usage example: 2074 * <dl> 2075 * <dt>Retrieving the thumbnail-sized photo</dt> 2076 * <dd> 2077 * <pre> 2078 * public InputStream openPhoto(long contactId) { 2079 * Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2080 * Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); 2081 * Cursor cursor = getContentResolver().query(photoUri, 2082 * new String[] {Contacts.Photo.PHOTO}, null, null, null); 2083 * if (cursor == null) { 2084 * return null; 2085 * } 2086 * try { 2087 * if (cursor.moveToFirst()) { 2088 * byte[] data = cursor.getBlob(0); 2089 * if (data != null) { 2090 * return new ByteArrayInputStream(data); 2091 * } 2092 * } 2093 * } finally { 2094 * cursor.close(); 2095 * } 2096 * return null; 2097 * } 2098 * </pre> 2099 * </dd> 2100 * <dt>Retrieving the larger photo version</dt> 2101 * <dd> 2102 * <pre> 2103 * public InputStream openDisplayPhoto(long contactId) { 2104 * Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2105 * Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO); 2106 * try { 2107 * AssetFileDescriptor fd = 2108 * getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r"); 2109 * return fd.createInputStream(); 2110 * } catch (IOException e) { 2111 * return null; 2112 * } 2113 * } 2114 * </pre> 2115 * </dd> 2116 * </dl> 2117 * 2118 * </p> 2119 * <p>You may also consider using the convenience method 2120 * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri, boolean)} 2121 * to retrieve the raw photo contents of either the thumbnail-sized or the full-sized photo. 2122 * </p> 2123 * <p> 2124 * This directory can be used either with a {@link #CONTENT_URI} or 2125 * {@link #CONTENT_LOOKUP_URI}. 2126 * </p> 2127 */ 2128 public static final class Photo implements BaseColumns, DataColumnsWithJoins { 2129 /** 2130 * no public constructor since this is a utility class 2131 */ Photo()2132 private Photo() {} 2133 2134 /** 2135 * The directory twig for this sub-table 2136 */ 2137 public static final String CONTENT_DIRECTORY = "photo"; 2138 2139 /** 2140 * The directory twig for retrieving the full-size display photo. 2141 */ 2142 public static final String DISPLAY_PHOTO = "display_photo"; 2143 2144 /** 2145 * Full-size photo file ID of the raw contact. 2146 * See {@link ContactsContract.DisplayPhoto}. 2147 * <p> 2148 * Type: NUMBER 2149 */ 2150 public static final String PHOTO_FILE_ID = DATA14; 2151 2152 /** 2153 * Thumbnail photo of the raw contact. This is the raw bytes of an image 2154 * that could be inflated using {@link android.graphics.BitmapFactory}. 2155 * <p> 2156 * Type: BLOB 2157 */ 2158 public static final String PHOTO = DATA15; 2159 } 2160 2161 /** 2162 * Opens an InputStream for the contacts's photo and returns the 2163 * photo as a byte stream. 2164 * @param cr The content resolver to use for querying 2165 * @param contactUri the contact whose photo should be used. This can be used with 2166 * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI. 2167 * @param preferHighres If this is true and the contact has a higher resolution photo 2168 * available, it is returned. If false, this function always tries to get the thumbnail 2169 * @return an InputStream of the photo, or null if no photo is present 2170 */ openContactPhotoInputStream(ContentResolver cr, Uri contactUri, boolean preferHighres)2171 public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri, 2172 boolean preferHighres) { 2173 if (preferHighres) { 2174 final Uri displayPhotoUri = Uri.withAppendedPath(contactUri, 2175 Contacts.Photo.DISPLAY_PHOTO); 2176 try { 2177 AssetFileDescriptor fd = cr.openAssetFileDescriptor(displayPhotoUri, "r"); 2178 if (fd != null) { 2179 return fd.createInputStream(); 2180 } 2181 } catch (IOException e) { 2182 // fallback to the thumbnail code 2183 } 2184 } 2185 2186 Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY); 2187 if (photoUri == null) { 2188 return null; 2189 } 2190 Cursor cursor = cr.query(photoUri, 2191 new String[] { 2192 ContactsContract.CommonDataKinds.Photo.PHOTO 2193 }, null, null, null); 2194 try { 2195 if (cursor == null || !cursor.moveToNext()) { 2196 return null; 2197 } 2198 byte[] data = cursor.getBlob(0); 2199 if (data == null) { 2200 return null; 2201 } 2202 return new ByteArrayInputStream(data); 2203 } finally { 2204 if (cursor != null) { 2205 cursor.close(); 2206 } 2207 } 2208 } 2209 2210 /** 2211 * Opens an InputStream for the contacts's thumbnail photo and returns the 2212 * photo as a byte stream. 2213 * @param cr The content resolver to use for querying 2214 * @param contactUri the contact whose photo should be used. This can be used with 2215 * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI. 2216 * @return an InputStream of the photo, or null if no photo is present 2217 * @see #openContactPhotoInputStream(ContentResolver, Uri, boolean), if instead 2218 * of the thumbnail the high-res picture is preferred 2219 */ openContactPhotoInputStream(ContentResolver cr, Uri contactUri)2220 public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { 2221 return openContactPhotoInputStream(cr, contactUri, false); 2222 } 2223 2224 /** 2225 * Creates and returns a corp lookup URI from the given enterprise lookup URI by removing 2226 * {@link #ENTERPRISE_CONTACT_LOOKUP_PREFIX} from the key. Returns {@code null} if the given 2227 * URI is not an enterprise lookup URI. 2228 * 2229 * @hide 2230 */ 2231 @Nullable createCorpLookupUriFromEnterpriseLookupUri( @onNull Uri enterpriseLookupUri)2232 public static Uri createCorpLookupUriFromEnterpriseLookupUri( 2233 @NonNull Uri enterpriseLookupUri) { 2234 final List<String> pathSegments = enterpriseLookupUri.getPathSegments(); 2235 if (pathSegments == null || pathSegments.size() <= 2) { 2236 return null; 2237 } 2238 final String key = pathSegments.get(2); 2239 if (TextUtils.isEmpty(key) || !key.startsWith(ENTERPRISE_CONTACT_LOOKUP_PREFIX)) { 2240 return null; 2241 } 2242 final String actualKey = key.substring(ENTERPRISE_CONTACT_LOOKUP_PREFIX.length()); 2243 return Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, actualKey); 2244 } 2245 } 2246 2247 /** 2248 * <p> 2249 * Constants for the user's profile data, which is represented as a single contact on 2250 * the device that represents the user. The profile contact is not aggregated 2251 * together automatically in the same way that normal contacts are; instead, each 2252 * account (including data set, if applicable) on the device may contribute a single 2253 * raw contact representing the user's personal profile data from that source. 2254 * </p> 2255 * <p> 2256 * Access to the profile entry through these URIs (or incidental access to parts of 2257 * the profile if retrieved directly via ID) requires additional permissions beyond 2258 * the read/write contact permissions required by the provider. Querying for profile 2259 * data requires android.permission.READ_PROFILE permission, and inserting or 2260 * updating profile data requires android.permission.WRITE_PROFILE permission. 2261 * </p> 2262 * <h3>Operations</h3> 2263 * <dl> 2264 * <dt><b>Insert</b></dt> 2265 * <dd>The user's profile entry cannot be created explicitly (attempting to do so 2266 * will throw an exception). When a raw contact is inserted into the profile, the 2267 * provider will check for the existence of a profile on the device. If one is 2268 * found, the raw contact's {@link RawContacts#CONTACT_ID} column gets the _ID of 2269 * the profile Contact. If no match is found, the profile Contact is created and 2270 * its _ID is put into the {@link RawContacts#CONTACT_ID} column of the newly 2271 * inserted raw contact.</dd> 2272 * <dt><b>Update</b></dt> 2273 * <dd>The profile Contact has the same update restrictions as Contacts in general, 2274 * but requires the android.permission.WRITE_PROFILE permission.</dd> 2275 * <dt><b>Delete</b></dt> 2276 * <dd>The profile Contact cannot be explicitly deleted. It will be removed 2277 * automatically if all of its constituent raw contact entries are deleted.</dd> 2278 * <dt><b>Query</b></dt> 2279 * <dd> 2280 * <ul> 2281 * <li>The {@link #CONTENT_URI} for profiles behaves in much the same way as 2282 * retrieving a contact by ID, except that it will only ever return the user's 2283 * profile contact. 2284 * </li> 2285 * <li> 2286 * The profile contact supports all of the same sub-paths as an individual contact 2287 * does - the content of the profile contact can be retrieved as entities or 2288 * data rows. Similarly, specific raw contact entries can be retrieved by appending 2289 * the desired raw contact ID within the profile. 2290 * </li> 2291 * </ul> 2292 * </dd> 2293 * </dl> 2294 */ 2295 public static final class Profile implements BaseColumns, ContactsColumns, 2296 ContactOptionsColumns, ContactNameColumns, ContactStatusColumns { 2297 /** 2298 * This utility class cannot be instantiated 2299 */ Profile()2300 private Profile() { 2301 } 2302 2303 /** 2304 * The content:// style URI for this table, which requests the contact entry 2305 * representing the user's personal profile data. 2306 */ 2307 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "profile"); 2308 2309 /** 2310 * {@link Uri} for referencing the user's profile {@link Contacts} entry, 2311 * Provides {@link OpenableColumns} columns when queried, or returns the 2312 * user's profile contact formatted as a vCard when opened through 2313 * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. 2314 */ 2315 public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, 2316 "as_vcard"); 2317 2318 /** 2319 * {@link Uri} for referencing the raw contacts that make up the user's profile 2320 * {@link Contacts} entry. An individual raw contact entry within the profile 2321 * can be addressed by appending the raw contact ID. The entities or data within 2322 * that specific raw contact can be requested by appending the entity or data 2323 * path as well. 2324 */ 2325 public static final Uri CONTENT_RAW_CONTACTS_URI = Uri.withAppendedPath(CONTENT_URI, 2326 "raw_contacts"); 2327 2328 /** 2329 * The minimum ID for any entity that belongs to the profile. This essentially 2330 * defines an ID-space in which profile data is stored, and is used by the provider 2331 * to determine whether a request via a non-profile-specific URI should be directed 2332 * to the profile data rather than general contacts data, along with all the special 2333 * permission checks that entails. 2334 * 2335 * Callers may use {@link #isProfileId} to check whether a specific ID falls into 2336 * the set of data intended for the profile. 2337 */ 2338 public static final long MIN_ID = Long.MAX_VALUE - (long) Integer.MAX_VALUE; 2339 } 2340 2341 /** 2342 * This method can be used to identify whether the given ID is associated with profile 2343 * data. It does not necessarily indicate that the ID is tied to valid data, merely 2344 * that accessing data using this ID will result in profile access checks and will only 2345 * return data from the profile. 2346 * 2347 * @param id The ID to check. 2348 * @return Whether the ID is associated with profile data. 2349 */ isProfileId(long id)2350 public static boolean isProfileId(long id) { 2351 return id >= Profile.MIN_ID; 2352 } 2353 2354 protected interface DeletedContactsColumns { 2355 2356 /** 2357 * A reference to the {@link ContactsContract.Contacts#_ID} that was deleted. 2358 * <P>Type: INTEGER</P> 2359 */ 2360 public static final String CONTACT_ID = "contact_id"; 2361 2362 /** 2363 * Time (milliseconds since epoch) that the contact was deleted. 2364 */ 2365 public static final String CONTACT_DELETED_TIMESTAMP = "contact_deleted_timestamp"; 2366 } 2367 2368 /** 2369 * Constants for the deleted contact table. This table holds a log of deleted contacts. 2370 * <p> 2371 * Log older than {@link #DAYS_KEPT_MILLISECONDS} may be deleted. 2372 */ 2373 public static final class DeletedContacts implements DeletedContactsColumns { 2374 2375 /** 2376 * This utility class cannot be instantiated 2377 */ DeletedContacts()2378 private DeletedContacts() { 2379 } 2380 2381 /** 2382 * The content:// style URI for this table, which requests a directory of raw contact rows 2383 * matching the selection criteria. 2384 */ 2385 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, 2386 "deleted_contacts"); 2387 2388 /** 2389 * Number of days that the delete log will be kept. After this time, delete records may be 2390 * deleted. 2391 * 2392 * @hide 2393 */ 2394 private static final int DAYS_KEPT = 30; 2395 2396 /** 2397 * Milliseconds that the delete log will be kept. After this time, delete records may be 2398 * deleted. 2399 */ 2400 public static final long DAYS_KEPT_MILLISECONDS = 1000L * 60L * 60L * 24L * (long)DAYS_KEPT; 2401 } 2402 2403 protected interface RawContactsColumns { 2404 /** 2405 * A reference to the {@link ContactsContract.Contacts#_ID} that this 2406 * data belongs to. 2407 * <P>Type: INTEGER</P> 2408 */ 2409 public static final String CONTACT_ID = "contact_id"; 2410 2411 /** 2412 * Persistent unique id for each raw_contact within its account. 2413 * This id is provided by its own data source, and can be used to backup metadata 2414 * to the server. 2415 * This should be unique within each set of account_name/account_type/data_set 2416 */ 2417 public static final String BACKUP_ID = "backup_id"; 2418 2419 /** 2420 * The data set within the account that this row belongs to. This allows 2421 * multiple sync adapters for the same account type to distinguish between 2422 * each others' data. 2423 * 2424 * This is empty by default, and is completely optional. It only needs to 2425 * be populated if multiple sync adapters are entering distinct data for 2426 * the same account type and account name. 2427 * <P>Type: TEXT</P> 2428 */ 2429 public static final String DATA_SET = "data_set"; 2430 2431 /** 2432 * A concatenation of the account type and data set (delimited by a forward 2433 * slash) - if the data set is empty, this will be the same as the account 2434 * type. For applications that need to be aware of the data set, this can 2435 * be used instead of account type to distinguish sets of data. This is 2436 * never intended to be used for specifying accounts. 2437 * <p> 2438 * This column does *not* escape forward slashes in the account type or the data set. 2439 * If this is an issue, consider using 2440 * {@link ContactsContract.RawContacts#ACCOUNT_TYPE} and 2441 * {@link ContactsContract.RawContacts#DATA_SET} directly. 2442 */ 2443 public static final String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set"; 2444 2445 /** 2446 * The aggregation mode for this contact. 2447 * <P>Type: INTEGER</P> 2448 */ 2449 public static final String AGGREGATION_MODE = "aggregation_mode"; 2450 2451 /** 2452 * The "deleted" flag: "0" by default, "1" if the row has been marked 2453 * for deletion. When {@link android.content.ContentResolver#delete} is 2454 * called on a raw contact, it is marked for deletion and removed from its 2455 * aggregate contact. The sync adaptor deletes the raw contact on the server and 2456 * then calls ContactResolver.delete once more, this time passing the 2457 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 2458 * the data removal. 2459 * <P>Type: INTEGER</P> 2460 */ 2461 public static final String DELETED = "deleted"; 2462 2463 /** 2464 * The "read-only" flag: "0" by default, "1" if the row cannot be modified or 2465 * deleted except by a sync adapter. See {@link ContactsContract#CALLER_IS_SYNCADAPTER}. 2466 * <P>Type: INTEGER</P> 2467 */ 2468 public static final String RAW_CONTACT_IS_READ_ONLY = "raw_contact_is_read_only"; 2469 2470 /** 2471 * Flag that reflects whether this raw contact belongs to the user's 2472 * personal profile entry. 2473 */ 2474 public static final String RAW_CONTACT_IS_USER_PROFILE = "raw_contact_is_user_profile"; 2475 2476 /** 2477 * Flag indicating that a raw contact's metadata has changed, and its metadata 2478 * needs to be synchronized by the server. 2479 * <P>Type: INTEGER (boolean)</P> 2480 * 2481 * @deprecated This column never actually worked since added. It will not supported as 2482 * of Android version {@link android.os.Build.VERSION_CODES#R}. 2483 */ 2484 @Deprecated 2485 public static final String METADATA_DIRTY = "metadata_dirty"; 2486 } 2487 2488 /** 2489 * Constants for the raw contacts table, which contains one row of contact 2490 * information for each person in each synced account. Sync adapters and 2491 * contact management apps 2492 * are the primary consumers of this API. 2493 * 2494 * <h3>Aggregation</h3> 2495 * <p> 2496 * As soon as a raw contact is inserted or whenever its constituent data 2497 * changes, the provider will check if the raw contact matches other 2498 * existing raw contacts and if so will aggregate it with those. The 2499 * aggregation is reflected in the {@link RawContacts} table by the change of the 2500 * {@link #CONTACT_ID} field, which is the reference to the aggregate contact. 2501 * </p> 2502 * <p> 2503 * Changes to the structured name, organization, phone number, email address, 2504 * or nickname trigger a re-aggregation. 2505 * </p> 2506 * <p> 2507 * See also {@link AggregationExceptions} for a mechanism to control 2508 * aggregation programmatically. 2509 * </p> 2510 * 2511 * <h3>Operations</h3> 2512 * <dl> 2513 * <dt><b>Insert</b></dt> 2514 * <dd> 2515 * <p> 2516 * Raw contacts can be inserted incrementally or in a batch. 2517 * The incremental method is more traditional but less efficient. 2518 * It should be used 2519 * only if no {@link Data} values are available at the time the raw contact is created: 2520 * <pre> 2521 * ContentValues values = new ContentValues(); 2522 * values.put(RawContacts.ACCOUNT_TYPE, accountType); 2523 * values.put(RawContacts.ACCOUNT_NAME, accountName); 2524 * Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values); 2525 * long rawContactId = ContentUris.parseId(rawContactUri); 2526 * </pre> 2527 * </p> 2528 * <p> 2529 * Once {@link Data} values become available, insert those. 2530 * For example, here's how you would insert a name: 2531 * 2532 * <pre> 2533 * values.clear(); 2534 * values.put(Data.RAW_CONTACT_ID, rawContactId); 2535 * values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 2536 * values.put(StructuredName.DISPLAY_NAME, "Mike Sullivan"); 2537 * getContentResolver().insert(Data.CONTENT_URI, values); 2538 * </pre> 2539 * </p> 2540 * <p> 2541 * The batch method is by far preferred. It inserts the raw contact and its 2542 * constituent data rows in a single database transaction 2543 * and causes at most one aggregation pass. 2544 * <pre> 2545 * ArrayList<ContentProviderOperation> ops = 2546 * new ArrayList<ContentProviderOperation>(); 2547 * ... 2548 * int rawContactInsertIndex = ops.size(); 2549 * ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI) 2550 * .withValue(RawContacts.ACCOUNT_TYPE, accountType) 2551 * .withValue(RawContacts.ACCOUNT_NAME, accountName) 2552 * .build()); 2553 * 2554 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 2555 * .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex) 2556 * .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 2557 * .withValue(StructuredName.DISPLAY_NAME, "Mike Sullivan") 2558 * .build()); 2559 * 2560 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 2561 * </pre> 2562 * </p> 2563 * <p> 2564 * Note the use of {@link ContentProviderOperation.Builder#withValueBackReference(String, int)} 2565 * to refer to the as-yet-unknown index value of the raw contact inserted in the 2566 * first operation. 2567 * </p> 2568 * 2569 * <dt><b>Update</b></dt> 2570 * <dd><p> 2571 * Raw contacts can be updated incrementally or in a batch. 2572 * Batch mode should be used whenever possible. 2573 * The procedures and considerations are analogous to those documented above for inserts. 2574 * </p></dd> 2575 * <dt><b>Delete</b></dt> 2576 * <dd><p>When a raw contact is deleted, all of its Data rows as well as StatusUpdates, 2577 * AggregationExceptions, PhoneLookup rows are deleted automatically. When all raw 2578 * contacts associated with a {@link Contacts} row are deleted, the {@link Contacts} row 2579 * itself is also deleted automatically. 2580 * </p> 2581 * <p> 2582 * The invocation of {@code resolver.delete(...)}, does not immediately delete 2583 * a raw contacts row. 2584 * Instead, it sets the {@link #DELETED} flag on the raw contact and 2585 * removes the raw contact from its aggregate contact. 2586 * The sync adapter then deletes the raw contact from the server and 2587 * finalizes phone-side deletion by calling {@code resolver.delete(...)} 2588 * again and passing the {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter.<p> 2589 * <p>Some sync adapters are read-only, meaning that they only sync server-side 2590 * changes to the phone, but not the reverse. If one of those raw contacts 2591 * is marked for deletion, it will remain on the phone. However it will be 2592 * effectively invisible, because it will not be part of any aggregate contact. 2593 * </dd> 2594 * 2595 * <dt><b>Query</b></dt> 2596 * <dd> 2597 * <p> 2598 * It is easy to find all raw contacts in a Contact: 2599 * <pre> 2600 * Cursor c = getContentResolver().query(RawContacts.CONTENT_URI, 2601 * new String[]{RawContacts._ID}, 2602 * RawContacts.CONTACT_ID + "=?", 2603 * new String[]{String.valueOf(contactId)}, null); 2604 * </pre> 2605 * </p> 2606 * <p> 2607 * To find raw contacts within a specific account, 2608 * you can either put the account name and type in the selection or pass them as query 2609 * parameters. The latter approach is preferable, especially when you can reuse the 2610 * URI: 2611 * <pre> 2612 * Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon() 2613 * .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName) 2614 * .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType) 2615 * .build(); 2616 * Cursor c1 = getContentResolver().query(rawContactUri, 2617 * RawContacts.STARRED + "<>0", null, null, null); 2618 * ... 2619 * Cursor c2 = getContentResolver().query(rawContactUri, 2620 * RawContacts.DELETED + "<>0", null, null, null); 2621 * </pre> 2622 * </p> 2623 * <p>The best way to read a raw contact along with all the data associated with it is 2624 * by using the {@link Entity} directory. If the raw contact has data rows, 2625 * the Entity cursor will contain a row for each data row. If the raw contact has no 2626 * data rows, the cursor will still contain one row with the raw contact-level information. 2627 * <pre> 2628 * Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 2629 * Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY); 2630 * Cursor c = getContentResolver().query(entityUri, 2631 * new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1}, 2632 * null, null, null); 2633 * try { 2634 * while (c.moveToNext()) { 2635 * String sourceId = c.getString(0); 2636 * if (!c.isNull(1)) { 2637 * String mimeType = c.getString(2); 2638 * String data = c.getString(3); 2639 * ... 2640 * } 2641 * } 2642 * } finally { 2643 * c.close(); 2644 * } 2645 * </pre> 2646 * </p> 2647 * </dd> 2648 * </dl> 2649 * <h2>Columns</h2> 2650 * 2651 * <table class="jd-sumtable"> 2652 * <tr> 2653 * <th colspan='4'>RawContacts</th> 2654 * </tr> 2655 * <tr> 2656 * <td>long</td> 2657 * <td>{@link #_ID}</td> 2658 * <td>read-only</td> 2659 * <td>Row ID. Sync adapters should try to preserve row IDs during updates. In other words, 2660 * it is much better for a sync adapter to update a raw contact rather than to delete and 2661 * re-insert it.</td> 2662 * </tr> 2663 * <tr> 2664 * <td>long</td> 2665 * <td>{@link #CONTACT_ID}</td> 2666 * <td>read-only</td> 2667 * <td>The ID of the row in the {@link ContactsContract.Contacts} table 2668 * that this raw contact belongs 2669 * to. Raw contacts are linked to contacts by the aggregation process, which can be controlled 2670 * by the {@link #AGGREGATION_MODE} field and {@link AggregationExceptions}.</td> 2671 * </tr> 2672 * <tr> 2673 * <td>int</td> 2674 * <td>{@link #AGGREGATION_MODE}</td> 2675 * <td>read/write</td> 2676 * <td>A mechanism that allows programmatic control of the aggregation process. The allowed 2677 * values are {@link #AGGREGATION_MODE_DEFAULT}, {@link #AGGREGATION_MODE_DISABLED} 2678 * and {@link #AGGREGATION_MODE_SUSPENDED}. See also {@link AggregationExceptions}.</td> 2679 * </tr> 2680 * <tr> 2681 * <td>int</td> 2682 * <td>{@link #DELETED}</td> 2683 * <td>read/write</td> 2684 * <td>The "deleted" flag: "0" by default, "1" if the row has been marked 2685 * for deletion. When {@link android.content.ContentResolver#delete} is 2686 * called on a raw contact, it is marked for deletion and removed from its 2687 * aggregate contact. The sync adaptor deletes the raw contact on the server and 2688 * then calls ContactResolver.delete once more, this time passing the 2689 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 2690 * the data removal.</td> 2691 * </tr> 2692 * <tr> 2693 * <td>int</td> 2694 * <td>{@link #STARRED}</td> 2695 * <td>read/write</td> 2696 * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise. 2697 * Changing this field immediately affects the corresponding aggregate contact: 2698 * if any raw contacts in that aggregate contact are starred, then the contact 2699 * itself is marked as starred.</td> 2700 * </tr> 2701 * <tr> 2702 * <td>String</td> 2703 * <td>{@link #CUSTOM_RINGTONE}</td> 2704 * <td>read/write</td> 2705 * <td>A custom ringtone associated with a raw contact. Typically this is the 2706 * URI returned by an activity launched with the 2707 * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent. 2708 * To have an effect on the corresponding value of the aggregate contact, this field 2709 * should be set at the time the raw contact is inserted. To set a custom 2710 * ringtone on a contact, use the field {@link ContactsContract.Contacts#CUSTOM_RINGTONE 2711 * Contacts.CUSTOM_RINGTONE} 2712 * instead.</td> 2713 * </tr> 2714 * <tr> 2715 * <td>int</td> 2716 * <td>{@link #SEND_TO_VOICEMAIL}</td> 2717 * <td>read/write</td> 2718 * <td>An indicator of whether calls from this raw contact should be forwarded 2719 * directly to voice mail ('1') or not ('0'). To have an effect 2720 * on the corresponding value of the aggregate contact, this field 2721 * should be set at the time the raw contact is inserted.</td> 2722 * </tr> 2723 * <tr> 2724 * <td>String</td> 2725 * <td>{@link #ACCOUNT_NAME}</td> 2726 * <td>read/write-once</td> 2727 * <td>The name of the account instance to which this row belongs, which when paired with 2728 * {@link #ACCOUNT_TYPE} identifies a specific account. 2729 * For example, this will be the Gmail address if it is a Google account. 2730 * It should be set at the time the raw contact is inserted and never 2731 * changed afterwards.</td> 2732 * </tr> 2733 * <tr> 2734 * <td>String</td> 2735 * <td>{@link #ACCOUNT_TYPE}</td> 2736 * <td>read/write-once</td> 2737 * <td> 2738 * <p> 2739 * The type of account to which this row belongs, which when paired with 2740 * {@link #ACCOUNT_NAME} identifies a specific account. 2741 * It should be set at the time the raw contact is inserted and never 2742 * changed afterwards. 2743 * </p> 2744 * <p> 2745 * To ensure uniqueness, new account types should be chosen according to the 2746 * Java package naming convention. Thus a Google account is of type "com.google". 2747 * </p> 2748 * </td> 2749 * </tr> 2750 * <tr> 2751 * <td>String</td> 2752 * <td>{@link #DATA_SET}</td> 2753 * <td>read/write-once</td> 2754 * <td> 2755 * <p> 2756 * The data set within the account that this row belongs to. This allows 2757 * multiple sync adapters for the same account type to distinguish between 2758 * each others' data. The combination of {@link #ACCOUNT_TYPE}, 2759 * {@link #ACCOUNT_NAME}, and {@link #DATA_SET} identifies a set of data 2760 * that is associated with a single sync adapter. 2761 * </p> 2762 * <p> 2763 * This is empty by default, and is completely optional. It only needs to 2764 * be populated if multiple sync adapters are entering distinct data for 2765 * the same account type and account name. 2766 * </p> 2767 * <p> 2768 * It should be set at the time the raw contact is inserted and never 2769 * changed afterwards. 2770 * </p> 2771 * </td> 2772 * </tr> 2773 * <tr> 2774 * <td>String</td> 2775 * <td>{@link #SOURCE_ID}</td> 2776 * <td>read/write</td> 2777 * <td>String that uniquely identifies this row to its source account. 2778 * Typically it is set at the time the raw contact is inserted and never 2779 * changed afterwards. The one notable exception is a new raw contact: it 2780 * will have an account name and type (and possibly a data set), but no 2781 * source id. This indicates to the sync adapter that a new contact needs 2782 * to be created server-side and its ID stored in the corresponding 2783 * SOURCE_ID field on the phone. 2784 * </td> 2785 * </tr> 2786 * <tr> 2787 * <td>int</td> 2788 * <td>{@link #VERSION}</td> 2789 * <td>read-only</td> 2790 * <td>Version number that is updated whenever this row or its related data 2791 * changes. This field can be used for optimistic locking of a raw contact. 2792 * </td> 2793 * </tr> 2794 * <tr> 2795 * <td>int</td> 2796 * <td>{@link #DIRTY}</td> 2797 * <td>read/write</td> 2798 * <td>Flag indicating that {@link #VERSION} has changed, and this row needs 2799 * to be synchronized by its owning account. The value is set to "1" automatically 2800 * whenever the raw contact changes, unless the URI has the 2801 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter specified. 2802 * The sync adapter should always supply this query parameter to prevent 2803 * unnecessary synchronization: user changes some data on the server, 2804 * the sync adapter updates the contact on the phone (without the 2805 * CALLER_IS_SYNCADAPTER flag) flag, which sets the DIRTY flag, 2806 * which triggers a sync to bring the changes to the server. 2807 * </td> 2808 * </tr> 2809 * <tr> 2810 * <td>String</td> 2811 * <td>{@link #SYNC1}</td> 2812 * <td>read/write</td> 2813 * <td>Generic column provided for arbitrary use by sync adapters. 2814 * The content provider 2815 * stores this information on behalf of the sync adapter but does not 2816 * interpret it in any way. 2817 * </td> 2818 * </tr> 2819 * <tr> 2820 * <td>String</td> 2821 * <td>{@link #SYNC2}</td> 2822 * <td>read/write</td> 2823 * <td>Generic column for use by sync adapters. 2824 * </td> 2825 * </tr> 2826 * <tr> 2827 * <td>String</td> 2828 * <td>{@link #SYNC3}</td> 2829 * <td>read/write</td> 2830 * <td>Generic column for use by sync adapters. 2831 * </td> 2832 * </tr> 2833 * <tr> 2834 * <td>String</td> 2835 * <td>{@link #SYNC4}</td> 2836 * <td>read/write</td> 2837 * <td>Generic column for use by sync adapters. 2838 * </td> 2839 * </tr> 2840 * </table> 2841 */ 2842 public static final class RawContacts implements BaseColumns, RawContactsColumns, 2843 ContactOptionsColumns, ContactNameColumns, SyncColumns { 2844 /** 2845 * This utility class cannot be instantiated 2846 */ RawContacts()2847 private RawContacts() { 2848 } 2849 2850 /** 2851 * The content:// style URI for this table, which requests a directory of 2852 * raw contact rows matching the selection criteria. 2853 */ 2854 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts"); 2855 2856 /** 2857 * The MIME type of the results from {@link #CONTENT_URI} when a specific 2858 * ID value is not provided, and multiple raw contacts may be returned. 2859 */ 2860 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact"; 2861 2862 /** 2863 * The MIME type of the results when a raw contact ID is appended to {@link #CONTENT_URI}, 2864 * yielding a subdirectory of a single person. 2865 */ 2866 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact"; 2867 2868 /** 2869 * Aggregation mode: aggregate immediately after insert or update operation(s) are complete. 2870 */ 2871 public static final int AGGREGATION_MODE_DEFAULT = 0; 2872 2873 /** 2874 * Aggregation mode: aggregate at the time the raw contact is inserted/updated. 2875 * @deprecated Aggregation is synchronous, this historic value is a no-op 2876 */ 2877 @Deprecated 2878 public static final int AGGREGATION_MODE_IMMEDIATE = 1; 2879 2880 /** 2881 * <p> 2882 * Aggregation mode: aggregation suspended temporarily, and is likely to be resumed later. 2883 * Changes to the raw contact will update the associated aggregate contact but will not 2884 * result in any change in how the contact is aggregated. Similar to 2885 * {@link #AGGREGATION_MODE_DISABLED}, but maintains a link to the corresponding 2886 * {@link Contacts} aggregate. 2887 * </p> 2888 * <p> 2889 * This can be used to postpone aggregation until after a series of updates, for better 2890 * performance and/or user experience. 2891 * </p> 2892 * <p> 2893 * Note that changing 2894 * {@link #AGGREGATION_MODE} from {@link #AGGREGATION_MODE_SUSPENDED} to 2895 * {@link #AGGREGATION_MODE_DEFAULT} does not trigger an aggregation pass, but any 2896 * subsequent 2897 * change to the raw contact's data will. 2898 * </p> 2899 */ 2900 public static final int AGGREGATION_MODE_SUSPENDED = 2; 2901 2902 /** 2903 * <p> 2904 * Aggregation mode: never aggregate this raw contact. The raw contact will not 2905 * have a corresponding {@link Contacts} aggregate and therefore will not be included in 2906 * {@link Contacts} query results. 2907 * </p> 2908 * <p> 2909 * For example, this mode can be used for a raw contact that is marked for deletion while 2910 * waiting for the deletion to occur on the server side. 2911 * </p> 2912 * 2913 * @see #AGGREGATION_MODE_SUSPENDED 2914 */ 2915 public static final int AGGREGATION_MODE_DISABLED = 3; 2916 2917 /** 2918 * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 2919 * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} 2920 * entry of the given {@link RawContacts} entry. 2921 */ getContactLookupUri(ContentResolver resolver, Uri rawContactUri)2922 public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) { 2923 // TODO: use a lighter query by joining rawcontacts with contacts in provider 2924 final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY); 2925 final Cursor cursor = resolver.query(dataUri, new String[] { 2926 RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY 2927 }, null, null, null); 2928 2929 Uri lookupUri = null; 2930 try { 2931 if (cursor != null && cursor.moveToFirst()) { 2932 final long contactId = cursor.getLong(0); 2933 final String lookupKey = cursor.getString(1); 2934 return Contacts.getLookupUri(contactId, lookupKey); 2935 } 2936 } finally { 2937 if (cursor != null) cursor.close(); 2938 } 2939 return lookupUri; 2940 } 2941 2942 /** 2943 * The default value used for {@link #ACCOUNT_NAME} of raw contacts when they are inserted 2944 * without a value for this column. 2945 * 2946 * <p>This account is used to identify contacts that are only stored locally in the 2947 * contacts database instead of being associated with an {@link Account} managed by an 2948 * installed application. 2949 * 2950 * <p>When this returns null then {@link #getLocalAccountType} will also return null and 2951 * when it is non-null {@link #getLocalAccountType} will also return a non-null value. 2952 */ 2953 @Nullable getLocalAccountName(@onNull Context context)2954 public static String getLocalAccountName(@NonNull Context context) { 2955 // config_rawContactsLocalAccountName is defined in 2956 // platform/frameworks/base/core/res/res/values/config.xml 2957 return TextUtils.nullIfEmpty(context.getString( 2958 com.android.internal.R.string.config_rawContactsLocalAccountName)); 2959 } 2960 2961 /** 2962 * The default value used for {@link #ACCOUNT_TYPE} of raw contacts when they are inserted 2963 * without a value for this column. 2964 * 2965 * <p>This account is used to identify contacts that are only stored locally in the 2966 * contacts database instead of being associated with an {@link Account} managed by an 2967 * installed application. 2968 * 2969 * <p>When this returns null then {@link #getLocalAccountName} will also return null and 2970 * when it is non-null {@link #getLocalAccountName} will also return a non-null value. 2971 */ 2972 @Nullable getLocalAccountType(@onNull Context context)2973 public static String getLocalAccountType(@NonNull Context context) { 2974 // config_rawContactsLocalAccountType is defined in 2975 // platform/frameworks/base/core/res/res/values/config.xml 2976 return TextUtils.nullIfEmpty(context.getString( 2977 com.android.internal.R.string.config_rawContactsLocalAccountType)); 2978 } 2979 2980 /** 2981 * A sub-directory of a single raw contact that contains all of its 2982 * {@link ContactsContract.Data} rows. To access this directory 2983 * append {@link Data#CONTENT_DIRECTORY} to the raw contact URI. 2984 */ 2985 public static final class Data implements BaseColumns, DataColumns { 2986 /** 2987 * no public constructor since this is a utility class 2988 */ Data()2989 private Data() { 2990 } 2991 2992 /** 2993 * The directory twig for this sub-table 2994 */ 2995 public static final String CONTENT_DIRECTORY = "data"; 2996 } 2997 2998 /** 2999 * <p> 3000 * A sub-directory of a single raw contact that contains all of its 3001 * {@link ContactsContract.Data} rows. To access this directory append 3002 * {@link RawContacts.Entity#CONTENT_DIRECTORY} to the raw contact URI. See 3003 * {@link RawContactsEntity} for a stand-alone table containing the same 3004 * data. 3005 * </p> 3006 * <p> 3007 * Entity has two ID fields: {@link #_ID} for the raw contact 3008 * and {@link #DATA_ID} for the data rows. 3009 * Entity always contains at least one row, even if there are no 3010 * actual data rows. In this case the {@link #DATA_ID} field will be 3011 * null. 3012 * </p> 3013 * <p> 3014 * Using Entity should be preferred to using two separate queries: 3015 * RawContacts followed by Data. The reason is that Entity reads all 3016 * data for a raw contact in one transaction, so there is no possibility 3017 * of the data changing between the two queries. 3018 */ 3019 public static final class Entity implements BaseColumns, DataColumns { 3020 /** 3021 * no public constructor since this is a utility class 3022 */ Entity()3023 private Entity() { 3024 } 3025 3026 /** 3027 * The directory twig for this sub-table 3028 */ 3029 public static final String CONTENT_DIRECTORY = "entity"; 3030 3031 /** 3032 * The ID of the data row. The value will be null if this raw contact has no 3033 * data rows. 3034 * <P>Type: INTEGER</P> 3035 */ 3036 public static final String DATA_ID = "data_id"; 3037 } 3038 3039 /** 3040 * <p> 3041 * A sub-directory of a single raw contact that contains all of its 3042 * {@link ContactsContract.StreamItems} rows. To access this directory append 3043 * {@link RawContacts.StreamItems#CONTENT_DIRECTORY} to the raw contact URI. See 3044 * {@link ContactsContract.StreamItems} for a stand-alone table containing the 3045 * same data. 3046 * </p> 3047 * <p> 3048 * Access to the social stream through this sub-directory requires additional permissions 3049 * beyond the read/write contact permissions required by the provider. Querying for 3050 * social stream data requires android.permission.READ_SOCIAL_STREAM permission, and 3051 * inserting or updating social stream items requires android.permission.WRITE_SOCIAL_STREAM 3052 * permission. 3053 * </p> 3054 * 3055 * @deprecated - Do not use. This will not be supported in the future. In the future, 3056 * cursors returned from related queries will be empty. 3057 * 3058 * @removed 3059 */ 3060 @Deprecated 3061 public static final class StreamItems implements BaseColumns, StreamItemsColumns { 3062 /** 3063 * No public constructor since this is a utility class 3064 * 3065 * @deprecated - Do not use. This will not be supported in the future. In the future, 3066 * cursors returned from related queries will be empty. 3067 */ 3068 @Deprecated StreamItems()3069 private StreamItems() { 3070 } 3071 3072 /** 3073 * The directory twig for this sub-table 3074 * 3075 * @deprecated - Do not use. This will not be supported in the future. In the future, 3076 * cursors returned from related queries will be empty. 3077 */ 3078 @Deprecated 3079 public static final String CONTENT_DIRECTORY = "stream_items"; 3080 } 3081 3082 /** 3083 * <p> 3084 * A sub-directory of a single raw contact that represents its primary 3085 * display photo. To access this directory append 3086 * {@link RawContacts.DisplayPhoto#CONTENT_DIRECTORY} to the raw contact URI. 3087 * The resulting URI represents an image file, and should be interacted with 3088 * using ContentResolver.openAssetFileDescriptor. 3089 * <p> 3090 * <p> 3091 * Note that this sub-directory also supports opening the photo as an asset file 3092 * in write mode. Callers can create or replace the primary photo associated 3093 * with this raw contact by opening the asset file and writing the full-size 3094 * photo contents into it. When the file is closed, the image will be parsed, 3095 * sized down if necessary for the full-size display photo and thumbnail 3096 * dimensions, and stored. 3097 * </p> 3098 * <p> 3099 * Usage example: 3100 * <pre> 3101 * public void writeDisplayPhoto(long rawContactId, byte[] photo) { 3102 * Uri rawContactPhotoUri = Uri.withAppendedPath( 3103 * ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3104 * RawContacts.DisplayPhoto.CONTENT_DIRECTORY); 3105 * try { 3106 * AssetFileDescriptor fd = 3107 * getContentResolver().openAssetFileDescriptor(rawContactPhotoUri, "rw"); 3108 * OutputStream os = fd.createOutputStream(); 3109 * os.write(photo); 3110 * os.close(); 3111 * fd.close(); 3112 * } catch (IOException e) { 3113 * // Handle error cases. 3114 * } 3115 * } 3116 * </pre> 3117 * </p> 3118 */ 3119 public static final class DisplayPhoto { 3120 /** 3121 * No public constructor since this is a utility class 3122 */ DisplayPhoto()3123 private DisplayPhoto() { 3124 } 3125 3126 /** 3127 * The directory twig for this sub-table 3128 */ 3129 public static final String CONTENT_DIRECTORY = "display_photo"; 3130 } 3131 3132 /** 3133 * TODO: javadoc 3134 * @param cursor 3135 * @return 3136 */ newEntityIterator(Cursor cursor)3137 public static EntityIterator newEntityIterator(Cursor cursor) { 3138 return new EntityIteratorImpl(cursor); 3139 } 3140 3141 private static class EntityIteratorImpl extends CursorEntityIterator { 3142 private static final String[] DATA_KEYS = new String[]{ 3143 Data.DATA1, 3144 Data.DATA2, 3145 Data.DATA3, 3146 Data.DATA4, 3147 Data.DATA5, 3148 Data.DATA6, 3149 Data.DATA7, 3150 Data.DATA8, 3151 Data.DATA9, 3152 Data.DATA10, 3153 Data.DATA11, 3154 Data.DATA12, 3155 Data.DATA13, 3156 Data.DATA14, 3157 Data.DATA15, 3158 Data.SYNC1, 3159 Data.SYNC2, 3160 Data.SYNC3, 3161 Data.SYNC4}; 3162 EntityIteratorImpl(Cursor cursor)3163 public EntityIteratorImpl(Cursor cursor) { 3164 super(cursor); 3165 } 3166 3167 @Override getEntityAndIncrementCursor(Cursor cursor)3168 public android.content.Entity getEntityAndIncrementCursor(Cursor cursor) 3169 throws RemoteException { 3170 final int columnRawContactId = cursor.getColumnIndexOrThrow(RawContacts._ID); 3171 final long rawContactId = cursor.getLong(columnRawContactId); 3172 3173 // we expect the cursor is already at the row we need to read from 3174 ContentValues cv = new ContentValues(); 3175 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_NAME); 3176 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_TYPE); 3177 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, DATA_SET); 3178 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, _ID); 3179 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DIRTY); 3180 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, VERSION); 3181 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SOURCE_ID); 3182 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC1); 3183 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC2); 3184 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC3); 3185 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC4); 3186 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DELETED); 3187 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID); 3188 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED); 3189 android.content.Entity contact = new android.content.Entity(cv); 3190 3191 // read data rows until the contact id changes 3192 do { 3193 if (rawContactId != cursor.getLong(columnRawContactId)) { 3194 break; 3195 } 3196 // add the data to to the contact 3197 cv = new ContentValues(); 3198 cv.put(Data._ID, cursor.getLong(cursor.getColumnIndexOrThrow(Entity.DATA_ID))); 3199 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 3200 Data.RES_PACKAGE); 3201 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Data.MIMETYPE); 3202 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.IS_PRIMARY); 3203 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, 3204 Data.IS_SUPER_PRIMARY); 3205 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.DATA_VERSION); 3206 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 3207 CommonDataKinds.GroupMembership.GROUP_SOURCE_ID); 3208 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, 3209 Data.DATA_VERSION); 3210 for (String key : DATA_KEYS) { 3211 final int columnIndex = cursor.getColumnIndexOrThrow(key); 3212 switch (cursor.getType(columnIndex)) { 3213 case Cursor.FIELD_TYPE_NULL: 3214 // don't put anything 3215 break; 3216 case Cursor.FIELD_TYPE_INTEGER: 3217 case Cursor.FIELD_TYPE_FLOAT: 3218 case Cursor.FIELD_TYPE_STRING: 3219 cv.put(key, cursor.getString(columnIndex)); 3220 break; 3221 case Cursor.FIELD_TYPE_BLOB: 3222 cv.put(key, cursor.getBlob(columnIndex)); 3223 break; 3224 default: 3225 throw new IllegalStateException("Invalid or unhandled data type"); 3226 } 3227 } 3228 contact.addSubValue(ContactsContract.Data.CONTENT_URI, cv); 3229 } while (cursor.moveToNext()); 3230 3231 return contact; 3232 } 3233 3234 } 3235 } 3236 3237 /** 3238 * Social status update columns. 3239 * 3240 * @see StatusUpdates 3241 * @see ContactsContract.Data 3242 */ 3243 protected interface StatusColumns { 3244 /** 3245 * Contact's latest presence level. 3246 * <P>Type: INTEGER (one of the values below)</P> 3247 */ 3248 public static final String PRESENCE = "mode"; 3249 3250 /** 3251 * @deprecated use {@link #PRESENCE} 3252 */ 3253 @Deprecated 3254 public static final String PRESENCE_STATUS = PRESENCE; 3255 3256 /** 3257 * An allowed value of {@link #PRESENCE}. 3258 */ 3259 int OFFLINE = 0; 3260 3261 /** 3262 * An allowed value of {@link #PRESENCE}. 3263 */ 3264 int INVISIBLE = 1; 3265 3266 /** 3267 * An allowed value of {@link #PRESENCE}. 3268 */ 3269 int AWAY = 2; 3270 3271 /** 3272 * An allowed value of {@link #PRESENCE}. 3273 */ 3274 int IDLE = 3; 3275 3276 /** 3277 * An allowed value of {@link #PRESENCE}. 3278 */ 3279 int DO_NOT_DISTURB = 4; 3280 3281 /** 3282 * An allowed value of {@link #PRESENCE}. 3283 */ 3284 int AVAILABLE = 5; 3285 3286 /** 3287 * Contact latest status update. 3288 * <p>Type: TEXT</p> 3289 */ 3290 public static final String STATUS = "status"; 3291 3292 /** 3293 * @deprecated use {@link #STATUS} 3294 */ 3295 @Deprecated 3296 public static final String PRESENCE_CUSTOM_STATUS = STATUS; 3297 3298 /** 3299 * The absolute time in milliseconds when the latest status was inserted/updated. 3300 * <p>Type: NUMBER</p> 3301 */ 3302 public static final String STATUS_TIMESTAMP = "status_ts"; 3303 3304 /** 3305 * The package containing resources for this status: label and icon. 3306 * <p>Type: TEXT</p> 3307 */ 3308 public static final String STATUS_RES_PACKAGE = "status_res_package"; 3309 3310 /** 3311 * The resource ID of the label describing the source of the status update, e.g. "Google 3312 * Talk". This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. 3313 * <p>Type: NUMBER</p> 3314 */ 3315 public static final String STATUS_LABEL = "status_label"; 3316 3317 /** 3318 * The resource ID of the icon for the source of the status update. 3319 * This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. 3320 * <p>Type: NUMBER</p> 3321 */ 3322 public static final String STATUS_ICON = "status_icon"; 3323 3324 /** 3325 * Contact's audio/video chat capability level. 3326 * <P>Type: INTEGER (one of the values below)</P> 3327 */ 3328 public static final String CHAT_CAPABILITY = "chat_capability"; 3329 3330 /** 3331 * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates audio-chat capability (microphone 3332 * and speaker) 3333 */ 3334 public static final int CAPABILITY_HAS_VOICE = 1; 3335 3336 /** 3337 * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates that the contact's device can 3338 * display a video feed. 3339 */ 3340 public static final int CAPABILITY_HAS_VIDEO = 2; 3341 3342 /** 3343 * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates that the contact's device has a 3344 * camera that can be used for video chat (e.g. a front-facing camera on a phone). 3345 */ 3346 public static final int CAPABILITY_HAS_CAMERA = 4; 3347 } 3348 3349 /** 3350 * <p> 3351 * Constants for the stream_items table, which contains social stream updates from 3352 * the user's contact list. 3353 * </p> 3354 * <p> 3355 * Only a certain number of stream items will ever be stored under a given raw contact. 3356 * Users of this API can query {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI} to 3357 * determine this limit, and should restrict the number of items inserted in any given 3358 * transaction correspondingly. Insertion of more items beyond the limit will 3359 * automatically lead to deletion of the oldest items, by {@link StreamItems#TIMESTAMP}. 3360 * </p> 3361 * <p> 3362 * Access to the social stream through these URIs requires additional permissions beyond the 3363 * read/write contact permissions required by the provider. Querying for social stream data 3364 * requires android.permission.READ_SOCIAL_STREAM permission, and inserting or updating social 3365 * stream items requires android.permission.WRITE_SOCIAL_STREAM permission. 3366 * </p> 3367 * <h3>Account check</h3> 3368 * <p> 3369 * The content URIs to the insert, update and delete operations are required to have the account 3370 * information matching that of the owning raw contact as query parameters, namely 3371 * {@link RawContacts#ACCOUNT_TYPE} and {@link RawContacts#ACCOUNT_NAME}. 3372 * {@link RawContacts#DATA_SET} isn't required. 3373 * </p> 3374 * <h3>Operations</h3> 3375 * <dl> 3376 * <dt><b>Insert</b></dt> 3377 * <dd> 3378 * <p>Social stream updates are always associated with a raw contact. There are a couple 3379 * of ways to insert these entries. 3380 * <dl> 3381 * <dt>Via the {@link RawContacts.StreamItems#CONTENT_DIRECTORY} sub-path of a raw contact:</dt> 3382 * <dd> 3383 * <pre> 3384 * ContentValues values = new ContentValues(); 3385 * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys"); 3386 * values.put(StreamItems.TIMESTAMP, timestamp); 3387 * values.put(StreamItems.COMMENTS, "3 people reshared this"); 3388 * Uri.Builder builder = RawContacts.CONTENT_URI.buildUpon(); 3389 * ContentUris.appendId(builder, rawContactId); 3390 * builder.appendEncodedPath(RawContacts.StreamItems.CONTENT_DIRECTORY); 3391 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3392 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3393 * Uri streamItemUri = getContentResolver().insert(builder.build(), values); 3394 * long streamItemId = ContentUris.parseId(streamItemUri); 3395 * </pre> 3396 * </dd> 3397 * <dt>Via {@link StreamItems#CONTENT_URI}:</dt> 3398 * <dd> 3399 *<pre> 3400 * ContentValues values = new ContentValues(); 3401 * values.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3402 * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys"); 3403 * values.put(StreamItems.TIMESTAMP, timestamp); 3404 * values.put(StreamItems.COMMENTS, "3 people reshared this"); 3405 * Uri.Builder builder = StreamItems.CONTENT_URI.buildUpon(); 3406 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3407 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3408 * Uri streamItemUri = getContentResolver().insert(builder.build(), values); 3409 * long streamItemId = ContentUris.parseId(streamItemUri); 3410 *</pre> 3411 * </dd> 3412 * </dl> 3413 * </dd> 3414 * </p> 3415 * <p> 3416 * Once a {@link StreamItems} entry has been inserted, photos associated with that 3417 * social update can be inserted. For example, after one of the insertions above, 3418 * photos could be added to the stream item in one of the following ways: 3419 * <dl> 3420 * <dt>Via a URI including the stream item ID:</dt> 3421 * <dd> 3422 * <pre> 3423 * values.clear(); 3424 * values.put(StreamItemPhotos.SORT_INDEX, 1); 3425 * values.put(StreamItemPhotos.PHOTO, photoData); 3426 * getContentResolver().insert(Uri.withAppendedPath( 3427 * ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3428 * StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), values); 3429 * </pre> 3430 * </dd> 3431 * <dt>Via {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI}:</dt> 3432 * <dd> 3433 * <pre> 3434 * values.clear(); 3435 * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId); 3436 * values.put(StreamItemPhotos.SORT_INDEX, 1); 3437 * values.put(StreamItemPhotos.PHOTO, photoData); 3438 * getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values); 3439 * </pre> 3440 * <p>Note that this latter form allows the insertion of a stream item and its 3441 * photos in a single transaction, by using {@link ContentProviderOperation} with 3442 * back references to populate the stream item ID in the {@link ContentValues}. 3443 * </dd> 3444 * </dl> 3445 * </p> 3446 * </dd> 3447 * <dt><b>Update</b></dt> 3448 * <dd>Updates can be performed by appending the stream item ID to the 3449 * {@link StreamItems#CONTENT_URI} URI. Only social stream entries that were 3450 * created by the calling package can be updated.</dd> 3451 * <dt><b>Delete</b></dt> 3452 * <dd>Deletes can be performed by appending the stream item ID to the 3453 * {@link StreamItems#CONTENT_URI} URI. Only social stream entries that were 3454 * created by the calling package can be deleted.</dd> 3455 * <dt><b>Query</b></dt> 3456 * <dl> 3457 * <dt>Finding all social stream updates for a given contact</dt> 3458 * <dd>By Contact ID: 3459 * <pre> 3460 * Cursor c = getContentResolver().query(Uri.withAppendedPath( 3461 * ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 3462 * Contacts.StreamItems.CONTENT_DIRECTORY), 3463 * null, null, null, null); 3464 * </pre> 3465 * </dd> 3466 * <dd>By lookup key: 3467 * <pre> 3468 * Cursor c = getContentResolver().query(Contacts.CONTENT_URI.buildUpon() 3469 * .appendPath(lookupKey) 3470 * .appendPath(Contacts.StreamItems.CONTENT_DIRECTORY).build(), 3471 * null, null, null, null); 3472 * </pre> 3473 * </dd> 3474 * <dt>Finding all social stream updates for a given raw contact</dt> 3475 * <dd> 3476 * <pre> 3477 * Cursor c = getContentResolver().query(Uri.withAppendedPath( 3478 * ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3479 * RawContacts.StreamItems.CONTENT_DIRECTORY)), 3480 * null, null, null, null); 3481 * </pre> 3482 * </dd> 3483 * <dt>Querying for a specific stream item by ID</dt> 3484 * <dd> 3485 * <pre> 3486 * Cursor c = getContentResolver().query(ContentUris.withAppendedId( 3487 * StreamItems.CONTENT_URI, streamItemId), 3488 * null, null, null, null); 3489 * </pre> 3490 * </dd> 3491 * </dl> 3492 * 3493 * @deprecated - Do not use. This will not be supported in the future. In the future, 3494 * cursors returned from related queries will be empty. 3495 * 3496 * @removed 3497 */ 3498 @Deprecated 3499 public static final class StreamItems implements BaseColumns, StreamItemsColumns { 3500 /** 3501 * This utility class cannot be instantiated 3502 * 3503 * @deprecated - Do not use. This will not be supported in the future. In the future, 3504 * cursors returned from related queries will be empty. 3505 */ 3506 @Deprecated StreamItems()3507 private StreamItems() { 3508 } 3509 3510 /** 3511 * The content:// style URI for this table, which handles social network stream 3512 * updates for the user's contacts. 3513 * 3514 * @deprecated - Do not use. This will not be supported in the future. In the future, 3515 * cursors returned from related queries will be empty. 3516 */ 3517 @Deprecated 3518 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "stream_items"); 3519 3520 /** 3521 * <p> 3522 * A content:// style URI for the photos stored in a sub-table underneath 3523 * stream items. This is only used for inserts, and updates - queries and deletes 3524 * for photos should be performed by appending 3525 * {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} path to URIs for a 3526 * specific stream item. 3527 * </p> 3528 * <p> 3529 * When using this URI, the stream item ID for the photo(s) must be identified 3530 * in the {@link ContentValues} passed in. 3531 * </p> 3532 * 3533 * @deprecated - Do not use. This will not be supported in the future. In the future, 3534 * cursors returned from related queries will be empty. 3535 */ 3536 @Deprecated 3537 public static final Uri CONTENT_PHOTO_URI = Uri.withAppendedPath(CONTENT_URI, "photo"); 3538 3539 /** 3540 * This URI allows the caller to query for the maximum number of stream items 3541 * that will be stored under any single raw contact. 3542 * 3543 * @deprecated - Do not use. This will not be supported in the future. In the future, 3544 * cursors returned from related queries will be empty. 3545 */ 3546 @Deprecated 3547 public static final Uri CONTENT_LIMIT_URI = 3548 Uri.withAppendedPath(AUTHORITY_URI, "stream_items_limit"); 3549 3550 /** 3551 * The MIME type of a directory of stream items. 3552 * 3553 * @deprecated - Do not use. This will not be supported in the future. In the future, 3554 * cursors returned from related queries will be empty. 3555 */ 3556 @Deprecated 3557 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item"; 3558 3559 /** 3560 * The MIME type of a single stream item. 3561 * 3562 * @deprecated - Do not use. This will not be supported in the future. In the future, 3563 * cursors returned from related queries will be empty. 3564 */ 3565 @Deprecated 3566 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item"; 3567 3568 /** 3569 * Queries to {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI} will 3570 * contain this column, with the value indicating the maximum number of 3571 * stream items that will be stored under any single raw contact. 3572 * 3573 * @deprecated - Do not use. This will not be supported in the future. In the future, 3574 * cursors returned from related queries will be empty. 3575 */ 3576 @Deprecated 3577 public static final String MAX_ITEMS = "max_items"; 3578 3579 /** 3580 * <p> 3581 * A sub-directory of a single stream item entry that contains all of its 3582 * photo rows. To access this 3583 * directory append {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} to 3584 * an individual stream item URI. 3585 * </p> 3586 * <p> 3587 * Access to social stream photos requires additional permissions beyond the read/write 3588 * contact permissions required by the provider. Querying for social stream photos 3589 * requires android.permission.READ_SOCIAL_STREAM permission, and inserting or updating 3590 * social stream photos requires android.permission.WRITE_SOCIAL_STREAM permission. 3591 * </p> 3592 * 3593 * @deprecated - Do not use. This will not be supported in the future. In the future, 3594 * cursors returned from related queries will be empty. 3595 * 3596 * @removed 3597 */ 3598 @Deprecated 3599 public static final class StreamItemPhotos 3600 implements BaseColumns, StreamItemPhotosColumns { 3601 /** 3602 * No public constructor since this is a utility class 3603 * 3604 * @deprecated - Do not use. This will not be supported in the future. In the future, 3605 * cursors returned from related queries will be empty. 3606 */ 3607 @Deprecated StreamItemPhotos()3608 private StreamItemPhotos() { 3609 } 3610 3611 /** 3612 * The directory twig for this sub-table 3613 * 3614 * @deprecated - Do not use. This will not be supported in the future. In the future, 3615 * cursors returned from related queries will be empty. 3616 */ 3617 @Deprecated 3618 public static final String CONTENT_DIRECTORY = "photo"; 3619 3620 /** 3621 * The MIME type of a directory of stream item photos. 3622 * 3623 * @deprecated - Do not use. This will not be supported in the future. In the future, 3624 * cursors returned from related queries will be empty. 3625 */ 3626 @Deprecated 3627 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo"; 3628 3629 /** 3630 * The MIME type of a single stream item photo. 3631 * 3632 * @deprecated - Do not use. This will not be supported in the future. In the future, 3633 * cursors returned from related queries will be empty. 3634 */ 3635 @Deprecated 3636 public static final String CONTENT_ITEM_TYPE 3637 = "vnd.android.cursor.item/stream_item_photo"; 3638 } 3639 } 3640 3641 /** 3642 * Columns in the StreamItems table. 3643 * 3644 * @see ContactsContract.StreamItems 3645 * @deprecated - Do not use. This will not be supported in the future. In the future, 3646 * cursors returned from related queries will be empty. 3647 * 3648 * @removed 3649 */ 3650 @Deprecated 3651 protected interface StreamItemsColumns { 3652 /** 3653 * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} 3654 * that this stream item belongs to. 3655 * 3656 * <p>Type: INTEGER</p> 3657 * <p>read-only</p> 3658 * 3659 * @deprecated - Do not use. This will not be supported in the future. In the future, 3660 * cursors returned from related queries will be empty. 3661 */ 3662 @Deprecated 3663 public static final String CONTACT_ID = "contact_id"; 3664 3665 /** 3666 * A reference to the {@link android.provider.ContactsContract.Contacts#LOOKUP_KEY} 3667 * that this stream item belongs to. 3668 * 3669 * <p>Type: TEXT</p> 3670 * <p>read-only</p> 3671 * 3672 * @deprecated - Do not use. This will not be supported in the future. In the future, 3673 * cursors returned from related queries will be empty. 3674 */ 3675 @Deprecated 3676 public static final String CONTACT_LOOKUP_KEY = "contact_lookup"; 3677 3678 /** 3679 * A reference to the {@link RawContacts#_ID} 3680 * that this stream item belongs to. 3681 * <p>Type: INTEGER</p> 3682 * 3683 * @deprecated - Do not use. This will not be supported in the future. In the future, 3684 * cursors returned from related queries will be empty. 3685 */ 3686 @Deprecated 3687 public static final String RAW_CONTACT_ID = "raw_contact_id"; 3688 3689 /** 3690 * The package name to use when creating {@link Resources} objects for 3691 * this stream item. This value is only designed for use when building 3692 * user interfaces, and should not be used to infer the owner. 3693 * <P>Type: TEXT</P> 3694 * 3695 * @deprecated - Do not use. This will not be supported in the future. In the future, 3696 * cursors returned from related queries will be empty. 3697 */ 3698 @Deprecated 3699 public static final String RES_PACKAGE = "res_package"; 3700 3701 /** 3702 * The account type to which the raw_contact of this item is associated. See 3703 * {@link RawContacts#ACCOUNT_TYPE} 3704 * 3705 * <p>Type: TEXT</p> 3706 * <p>read-only</p> 3707 * 3708 * @deprecated - Do not use. This will not be supported in the future. In the future, 3709 * cursors returned from related queries will be empty. 3710 */ 3711 @Deprecated 3712 public static final String ACCOUNT_TYPE = "account_type"; 3713 3714 /** 3715 * The account name to which the raw_contact of this item is associated. See 3716 * {@link RawContacts#ACCOUNT_NAME} 3717 * 3718 * <p>Type: TEXT</p> 3719 * <p>read-only</p> 3720 * 3721 * @deprecated - Do not use. This will not be supported in the future. In the future, 3722 * cursors returned from related queries will be empty. 3723 */ 3724 @Deprecated 3725 public static final String ACCOUNT_NAME = "account_name"; 3726 3727 /** 3728 * The data set within the account that the raw_contact of this row belongs to. This allows 3729 * multiple sync adapters for the same account type to distinguish between 3730 * each others' data. 3731 * {@link RawContacts#DATA_SET} 3732 * 3733 * <P>Type: TEXT</P> 3734 * <p>read-only</p> 3735 * 3736 * @deprecated - Do not use. This will not be supported in the future. In the future, 3737 * cursors returned from related queries will be empty. 3738 */ 3739 @Deprecated 3740 public static final String DATA_SET = "data_set"; 3741 3742 /** 3743 * The source_id of the raw_contact that this row belongs to. 3744 * {@link RawContacts#SOURCE_ID} 3745 * 3746 * <P>Type: TEXT</P> 3747 * <p>read-only</p> 3748 * 3749 * @deprecated - Do not use. This will not be supported in the future. In the future, 3750 * cursors returned from related queries will be empty. 3751 */ 3752 @Deprecated 3753 public static final String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id"; 3754 3755 /** 3756 * The resource name of the icon for the source of the stream item. 3757 * This resource should be scoped by the {@link #RES_PACKAGE}. As this can only reference 3758 * drawables, the "@drawable/" prefix must be omitted. 3759 * <P>Type: TEXT</P> 3760 * 3761 * @deprecated - Do not use. This will not be supported in the future. In the future, 3762 * cursors returned from related queries will be empty. 3763 */ 3764 @Deprecated 3765 public static final String RES_ICON = "icon"; 3766 3767 /** 3768 * The resource name of the label describing the source of the status update, e.g. "Google 3769 * Talk". This resource should be scoped by the {@link #RES_PACKAGE}. As this can only 3770 * reference strings, the "@string/" prefix must be omitted. 3771 * <p>Type: TEXT</p> 3772 * 3773 * @deprecated - Do not use. This will not be supported in the future. In the future, 3774 * cursors returned from related queries will be empty. 3775 */ 3776 @Deprecated 3777 public static final String RES_LABEL = "label"; 3778 3779 /** 3780 * <P> 3781 * The main textual contents of the item. Typically this is content 3782 * that was posted by the source of this stream item, but it can also 3783 * be a textual representation of an action (e.g. ”Checked in at Joe's”). 3784 * This text is displayed to the user and allows formatting and embedded 3785 * resource images via HTML (as parseable via 3786 * {@link android.text.Html#fromHtml}). 3787 * </P> 3788 * <P> 3789 * Long content may be truncated and/or ellipsized - the exact behavior 3790 * is unspecified, but it should not break tags. 3791 * </P> 3792 * <P>Type: TEXT</P> 3793 * 3794 * @deprecated - Do not use. This will not be supported in the future. In the future, 3795 * cursors returned from related queries will be empty. 3796 */ 3797 @Deprecated 3798 public static final String TEXT = "text"; 3799 3800 /** 3801 * The absolute time (milliseconds since epoch) when this stream item was 3802 * inserted/updated. 3803 * <P>Type: NUMBER</P> 3804 * 3805 * @deprecated - Do not use. This will not be supported in the future. In the future, 3806 * cursors returned from related queries will be empty. 3807 */ 3808 @Deprecated 3809 public static final String TIMESTAMP = "timestamp"; 3810 3811 /** 3812 * <P> 3813 * Summary information about the stream item, for example to indicate how 3814 * many people have reshared it, how many have liked it, how many thumbs 3815 * up and/or thumbs down it has, what the original source was, etc. 3816 * </P> 3817 * <P> 3818 * This text is displayed to the user and allows simple formatting via 3819 * HTML, in the same manner as {@link #TEXT} allows. 3820 * </P> 3821 * <P> 3822 * Long content may be truncated and/or ellipsized - the exact behavior 3823 * is unspecified, but it should not break tags. 3824 * </P> 3825 * <P>Type: TEXT</P> 3826 * 3827 * @deprecated - Do not use. This will not be supported in the future. In the future, 3828 * cursors returned from related queries will be empty. 3829 */ 3830 @Deprecated 3831 public static final String COMMENTS = "comments"; 3832 3833 /** 3834 * Generic column for use by sync adapters. 3835 * 3836 * @deprecated - Do not use. This will not be supported in the future. In the future, 3837 * cursors returned from related queries will be empty. 3838 */ 3839 @Deprecated 3840 public static final String SYNC1 = "stream_item_sync1"; 3841 /** 3842 * Generic column for use by sync adapters. 3843 * 3844 * @deprecated - Do not use. This will not be supported in the future. In the future, 3845 * cursors returned from related queries will be empty. 3846 */ 3847 @Deprecated 3848 public static final String SYNC2 = "stream_item_sync2"; 3849 /** 3850 * Generic column for use by sync adapters. 3851 * 3852 * @deprecated - Do not use. This will not be supported in the future. In the future, 3853 * cursors returned from related queries will be empty. 3854 */ 3855 @Deprecated 3856 public static final String SYNC3 = "stream_item_sync3"; 3857 /** 3858 * Generic column for use by sync adapters. 3859 * 3860 * @deprecated - Do not use. This will not be supported in the future. In the future, 3861 * cursors returned from related queries will be empty. 3862 */ 3863 @Deprecated 3864 public static final String SYNC4 = "stream_item_sync4"; 3865 } 3866 3867 /** 3868 * <p> 3869 * Constants for the stream_item_photos table, which contains photos associated with 3870 * social stream updates. 3871 * </p> 3872 * <p> 3873 * Access to social stream photos requires additional permissions beyond the read/write 3874 * contact permissions required by the provider. Querying for social stream photos 3875 * requires android.permission.READ_SOCIAL_STREAM permission, and inserting or updating 3876 * social stream photos requires android.permission.WRITE_SOCIAL_STREAM permission. 3877 * </p> 3878 * <h3>Account check</h3> 3879 * <p> 3880 * The content URIs to the insert, update and delete operations are required to have the account 3881 * information matching that of the owning raw contact as query parameters, namely 3882 * {@link RawContacts#ACCOUNT_TYPE} and {@link RawContacts#ACCOUNT_NAME}. 3883 * {@link RawContacts#DATA_SET} isn't required. 3884 * </p> 3885 * <h3>Operations</h3> 3886 * <dl> 3887 * <dt><b>Insert</b></dt> 3888 * <dd> 3889 * <p>Social stream photo entries are associated with a social stream item. Photos 3890 * can be inserted into a social stream item in a couple of ways: 3891 * <dl> 3892 * <dt> 3893 * Via the {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} sub-path of a 3894 * stream item: 3895 * </dt> 3896 * <dd> 3897 * <pre> 3898 * ContentValues values = new ContentValues(); 3899 * values.put(StreamItemPhotos.SORT_INDEX, 1); 3900 * values.put(StreamItemPhotos.PHOTO, photoData); 3901 * Uri.Builder builder = StreamItems.CONTENT_URI.buildUpon(); 3902 * ContentUris.appendId(builder, streamItemId); 3903 * builder.appendEncodedPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY); 3904 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3905 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3906 * Uri photoUri = getContentResolver().insert(builder.build(), values); 3907 * long photoId = ContentUris.parseId(photoUri); 3908 * </pre> 3909 * </dd> 3910 * <dt>Via the {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI} URI:</dt> 3911 * <dd> 3912 * <pre> 3913 * ContentValues values = new ContentValues(); 3914 * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId); 3915 * values.put(StreamItemPhotos.SORT_INDEX, 1); 3916 * values.put(StreamItemPhotos.PHOTO, photoData); 3917 * Uri.Builder builder = StreamItems.CONTENT_PHOTO_URI.buildUpon(); 3918 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3919 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3920 * Uri photoUri = getContentResolver().insert(builder.build(), values); 3921 * long photoId = ContentUris.parseId(photoUri); 3922 * </pre> 3923 * </dd> 3924 * </dl> 3925 * </p> 3926 * </dd> 3927 * <dt><b>Update</b></dt> 3928 * <dd> 3929 * <p>Updates can only be made against a specific {@link StreamItemPhotos} entry, 3930 * identified by both the stream item ID it belongs to and the stream item photo ID. 3931 * This can be specified in two ways. 3932 * <dl> 3933 * <dt>Via the {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} sub-path of a 3934 * stream item: 3935 * </dt> 3936 * <dd> 3937 * <pre> 3938 * ContentValues values = new ContentValues(); 3939 * values.put(StreamItemPhotos.PHOTO, newPhotoData); 3940 * Uri.Builder builder = StreamItems.CONTENT_URI.buildUpon(); 3941 * ContentUris.appendId(builder, streamItemId); 3942 * builder.appendEncodedPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY); 3943 * ContentUris.appendId(builder, streamItemPhotoId); 3944 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3945 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3946 * getContentResolver().update(builder.build(), values, null, null); 3947 * </pre> 3948 * </dd> 3949 * <dt>Via the {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI} URI:</dt> 3950 * <dd> 3951 * <pre> 3952 * ContentValues values = new ContentValues(); 3953 * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId); 3954 * values.put(StreamItemPhotos.PHOTO, newPhotoData); 3955 * Uri.Builder builder = StreamItems.CONTENT_PHOTO_URI.buildUpon(); 3956 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3957 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3958 * getContentResolver().update(builder.build(), values); 3959 * </pre> 3960 * </dd> 3961 * </dl> 3962 * </p> 3963 * </dd> 3964 * <dt><b>Delete</b></dt> 3965 * <dd>Deletes can be made against either a specific photo item in a stream item, or 3966 * against all or a selected subset of photo items under a stream item. 3967 * For example: 3968 * <dl> 3969 * <dt>Deleting a single photo via the 3970 * {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} sub-path of a stream item: 3971 * </dt> 3972 * <dd> 3973 * <pre> 3974 * Uri.Builder builder = StreamItems.CONTENT_URI.buildUpon(); 3975 * ContentUris.appendId(builder, streamItemId); 3976 * builder.appendEncodedPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY); 3977 * ContentUris.appendId(builder, streamItemPhotoId); 3978 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3979 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3980 * getContentResolver().delete(builder.build(), null, null); 3981 * </pre> 3982 * </dd> 3983 * <dt>Deleting all photos under a stream item</dt> 3984 * <dd> 3985 * <pre> 3986 * Uri.Builder builder = StreamItems.CONTENT_URI.buildUpon(); 3987 * ContentUris.appendId(builder, streamItemId); 3988 * builder.appendEncodedPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY); 3989 * builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); 3990 * builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); 3991 * getContentResolver().delete(builder.build(), null, null); 3992 * </pre> 3993 * </dd> 3994 * </dl> 3995 * </dd> 3996 * <dt><b>Query</b></dt> 3997 * <dl> 3998 * <dt>Querying for a specific photo in a stream item</dt> 3999 * <dd> 4000 * <pre> 4001 * Cursor c = getContentResolver().query( 4002 * ContentUris.withAppendedId( 4003 * Uri.withAppendedPath( 4004 * ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId) 4005 * StreamItems.StreamItemPhotos#CONTENT_DIRECTORY), 4006 * streamItemPhotoId), null, null, null, null); 4007 * </pre> 4008 * </dd> 4009 * <dt>Querying for all photos in a stream item</dt> 4010 * <dd> 4011 * <pre> 4012 * Cursor c = getContentResolver().query( 4013 * Uri.withAppendedPath( 4014 * ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId) 4015 * StreamItems.StreamItemPhotos#CONTENT_DIRECTORY), 4016 * null, null, null, StreamItemPhotos.SORT_INDEX); 4017 * </pre> 4018 * </dl> 4019 * The record will contain both a {@link StreamItemPhotos#PHOTO_FILE_ID} and a 4020 * {@link StreamItemPhotos#PHOTO_URI}. The {@link StreamItemPhotos#PHOTO_FILE_ID} 4021 * can be used in conjunction with the {@link ContactsContract.DisplayPhoto} API to 4022 * retrieve photo content, or you can open the {@link StreamItemPhotos#PHOTO_URI} as 4023 * an asset file, as follows: 4024 * <pre> 4025 * public InputStream openDisplayPhoto(String photoUri) { 4026 * try { 4027 * AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(photoUri, "r"); 4028 * return fd.createInputStream(); 4029 * } catch (IOException e) { 4030 * return null; 4031 * } 4032 * } 4033 * <pre> 4034 * </dd> 4035 * </dl> 4036 * 4037 * @deprecated - Do not use. This will not be supported in the future. In the future, 4038 * cursors returned from related queries will be empty. 4039 * 4040 * @removed 4041 */ 4042 @Deprecated 4043 public static final class StreamItemPhotos implements BaseColumns, StreamItemPhotosColumns { 4044 /** 4045 * No public constructor since this is a utility class 4046 * 4047 * @deprecated - Do not use. This will not be supported in the future. In the future, 4048 * cursors returned from related queries will be empty. 4049 */ 4050 @Deprecated StreamItemPhotos()4051 private StreamItemPhotos() { 4052 } 4053 4054 /** 4055 * <p> 4056 * The binary representation of the photo. Any size photo can be inserted; 4057 * the provider will resize it appropriately for storage and display. 4058 * </p> 4059 * <p> 4060 * This is only intended for use when inserting or updating a stream item photo. 4061 * To retrieve the photo that was stored, open {@link StreamItemPhotos#PHOTO_URI} 4062 * as an asset file. 4063 * </p> 4064 * <P>Type: BLOB</P> 4065 * 4066 * @deprecated - Do not use. This will not be supported in the future. In the future, 4067 * cursors returned from related queries will be empty. 4068 */ 4069 @Deprecated 4070 public static final String PHOTO = "photo"; 4071 } 4072 4073 /** 4074 * Columns in the StreamItemPhotos table. 4075 * 4076 * @see ContactsContract.StreamItemPhotos 4077 * @deprecated - Do not use. This will not be supported in the future. In the future, 4078 * cursors returned from related queries will be empty. 4079 * 4080 * @removed 4081 */ 4082 @Deprecated 4083 protected interface StreamItemPhotosColumns { 4084 /** 4085 * A reference to the {@link StreamItems#_ID} this photo is associated with. 4086 * <P>Type: NUMBER</P> 4087 * 4088 * @deprecated - Do not use. This will not be supported in the future. In the future, 4089 * cursors returned from related queries will be empty. 4090 */ 4091 @Deprecated 4092 public static final String STREAM_ITEM_ID = "stream_item_id"; 4093 4094 /** 4095 * An integer to use for sort order for photos in the stream item. If not 4096 * specified, the {@link StreamItemPhotos#_ID} will be used for sorting. 4097 * <P>Type: NUMBER</P> 4098 * 4099 * @deprecated - Do not use. This will not be supported in the future. In the future, 4100 * cursors returned from related queries will be empty. 4101 */ 4102 @Deprecated 4103 public static final String SORT_INDEX = "sort_index"; 4104 4105 /** 4106 * Photo file ID for the photo. 4107 * See {@link ContactsContract.DisplayPhoto}. 4108 * <P>Type: NUMBER</P> 4109 * 4110 * @deprecated - Do not use. This will not be supported in the future. In the future, 4111 * cursors returned from related queries will be empty. 4112 */ 4113 @Deprecated 4114 public static final String PHOTO_FILE_ID = "photo_file_id"; 4115 4116 /** 4117 * URI for retrieving the photo content, automatically populated. Callers 4118 * may retrieve the photo content by opening this URI as an asset file. 4119 * <P>Type: TEXT</P> 4120 * 4121 * @deprecated - Do not use. This will not be supported in the future. In the future, 4122 * cursors returned from related queries will be empty. 4123 */ 4124 @Deprecated 4125 public static final String PHOTO_URI = "photo_uri"; 4126 4127 /** 4128 * Generic column for use by sync adapters. 4129 * 4130 * @deprecated - Do not use. This will not be supported in the future. In the future, 4131 * cursors returned from related queries will be empty. 4132 */ 4133 @Deprecated 4134 public static final String SYNC1 = "stream_item_photo_sync1"; 4135 /** 4136 * Generic column for use by sync adapters. 4137 * 4138 * @deprecated - Do not use. This will not be supported in the future. In the future, 4139 * cursors returned from related queries will be empty. 4140 */ 4141 @Deprecated 4142 public static final String SYNC2 = "stream_item_photo_sync2"; 4143 /** 4144 * Generic column for use by sync adapters. 4145 * 4146 * @deprecated - Do not use. This will not be supported in the future. In the future, 4147 * cursors returned from related queries will be empty. 4148 */ 4149 @Deprecated 4150 public static final String SYNC3 = "stream_item_photo_sync3"; 4151 /** 4152 * Generic column for use by sync adapters. 4153 * 4154 * @deprecated - Do not use. This will not be supported in the future. In the future, 4155 * cursors returned from related queries will be empty. 4156 */ 4157 @Deprecated 4158 public static final String SYNC4 = "stream_item_photo_sync4"; 4159 } 4160 4161 /** 4162 * <p> 4163 * Constants for the photo files table, which tracks metadata for hi-res photos 4164 * stored in the file system. 4165 * </p> 4166 * 4167 * @hide 4168 */ 4169 public static final class PhotoFiles implements BaseColumns, PhotoFilesColumns { 4170 /** 4171 * No public constructor since this is a utility class 4172 */ PhotoFiles()4173 private PhotoFiles() { 4174 } 4175 } 4176 4177 /** 4178 * Columns in the PhotoFiles table. 4179 * 4180 * @see ContactsContract.PhotoFiles 4181 * 4182 * @hide 4183 */ 4184 protected interface PhotoFilesColumns { 4185 4186 /** 4187 * The height, in pixels, of the photo this entry is associated with. 4188 * <P>Type: NUMBER</P> 4189 */ 4190 public static final String HEIGHT = "height"; 4191 4192 /** 4193 * The width, in pixels, of the photo this entry is associated with. 4194 * <P>Type: NUMBER</P> 4195 */ 4196 public static final String WIDTH = "width"; 4197 4198 /** 4199 * The size, in bytes, of the photo stored on disk. 4200 * <P>Type: NUMBER</P> 4201 */ 4202 public static final String FILESIZE = "filesize"; 4203 } 4204 4205 /** 4206 * Columns in the Data table. 4207 * 4208 * @see ContactsContract.Data 4209 */ 4210 protected interface DataColumns { 4211 /** 4212 * The package name to use when creating {@link Resources} objects for 4213 * this data row. This value is only designed for use when building user 4214 * interfaces, and should not be used to infer the owner. 4215 */ 4216 public static final String RES_PACKAGE = "res_package"; 4217 4218 /** 4219 * The MIME type of the item represented by this row. 4220 */ 4221 public static final String MIMETYPE = "mimetype"; 4222 4223 /** 4224 * Hash id on the data fields, used for backup and restore. 4225 * 4226 * @hide 4227 * @deprecated This column was never public since added. It will not be supported 4228 * as of Android version {@link android.os.Build.VERSION_CODES#R}. 4229 */ 4230 @Deprecated 4231 public static final String HASH_ID = "hash_id"; 4232 4233 /** 4234 * A reference to the {@link RawContacts#_ID} 4235 * that this data belongs to. 4236 */ 4237 public static final String RAW_CONTACT_ID = "raw_contact_id"; 4238 4239 /** 4240 * Whether this is the primary entry of its kind for the raw contact it belongs to. 4241 * <P>Type: INTEGER (if set, non-0 means true)</P> 4242 */ 4243 public static final String IS_PRIMARY = "is_primary"; 4244 4245 /** 4246 * Whether this is the primary entry of its kind for the aggregate 4247 * contact it belongs to. Any data record that is "super primary" must 4248 * also be "primary". 4249 * <P>Type: INTEGER (if set, non-0 means true)</P> 4250 */ 4251 public static final String IS_SUPER_PRIMARY = "is_super_primary"; 4252 4253 /** 4254 * The "read-only" flag: "0" by default, "1" if the row cannot be modified or 4255 * deleted except by a sync adapter. See {@link ContactsContract#CALLER_IS_SYNCADAPTER}. 4256 * <P>Type: INTEGER</P> 4257 */ 4258 public static final String IS_READ_ONLY = "is_read_only"; 4259 4260 /** 4261 * The version of this data record. This is a read-only value. The data column is 4262 * guaranteed to not change without the version going up. This value is monotonically 4263 * increasing. 4264 * <P>Type: INTEGER</P> 4265 */ 4266 public static final String DATA_VERSION = "data_version"; 4267 4268 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4269 public static final String DATA1 = "data1"; 4270 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4271 public static final String DATA2 = "data2"; 4272 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4273 public static final String DATA3 = "data3"; 4274 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4275 public static final String DATA4 = "data4"; 4276 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4277 public static final String DATA5 = "data5"; 4278 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4279 public static final String DATA6 = "data6"; 4280 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4281 public static final String DATA7 = "data7"; 4282 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4283 public static final String DATA8 = "data8"; 4284 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4285 public static final String DATA9 = "data9"; 4286 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4287 public static final String DATA10 = "data10"; 4288 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4289 public static final String DATA11 = "data11"; 4290 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4291 public static final String DATA12 = "data12"; 4292 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4293 public static final String DATA13 = "data13"; 4294 /** Generic data column, the meaning is {@link #MIMETYPE} specific */ 4295 public static final String DATA14 = "data14"; 4296 /** 4297 * Generic data column, the meaning is {@link #MIMETYPE} specific. By convention, 4298 * this field is used to store BLOBs (binary data). 4299 */ 4300 public static final String DATA15 = "data15"; 4301 4302 /** Generic column for use by sync adapters. */ 4303 public static final String SYNC1 = "data_sync1"; 4304 /** Generic column for use by sync adapters. */ 4305 public static final String SYNC2 = "data_sync2"; 4306 /** Generic column for use by sync adapters. */ 4307 public static final String SYNC3 = "data_sync3"; 4308 /** Generic column for use by sync adapters. */ 4309 public static final String SYNC4 = "data_sync4"; 4310 4311 /** 4312 * Carrier presence information. 4313 * <P> 4314 * Type: INTEGER (A bitmask of CARRIER_PRESENCE_* fields) 4315 * </P> 4316 * 4317 * @deprecated The contacts database will only show presence 4318 * information on devices where 4319 * {@link android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is true, 4320 * otherwise use {@link android.telephony.ims.RcsUceAdapter}. 4321 */ 4322 @Deprecated 4323 public static final String CARRIER_PRESENCE = "carrier_presence"; 4324 4325 /** 4326 * Indicates that the entry is Video Telephony (VT) capable on the 4327 * current carrier. An allowed bitmask of {@link #CARRIER_PRESENCE}. 4328 * 4329 * @deprecated Same as {@link DataColumns#CARRIER_PRESENCE}. 4330 * 4331 */ 4332 @Deprecated 4333 public static final int CARRIER_PRESENCE_VT_CAPABLE = 0x01; 4334 4335 /** 4336 * The flattened {@link android.content.ComponentName} of a {@link 4337 * android.telecom.PhoneAccountHandle} that is the preferred {@code PhoneAccountHandle} to 4338 * call the contact with. 4339 * 4340 * <p> On a multi-SIM device this field can be used in a {@link CommonDataKinds.Phone} row 4341 * to indicate the {@link PhoneAccountHandle} to call the number with, instead of using 4342 * {@link android.telecom.TelecomManager#getDefaultOutgoingPhoneAccount(String)} or asking 4343 * every time. 4344 * 4345 * <p>{@link android.telecom.TelecomManager#placeCall(Uri, android.os.Bundle)} 4346 * should be called with {@link android.telecom.TelecomManager#EXTRA_PHONE_ACCOUNT_HANDLE} 4347 * set to the {@link PhoneAccountHandle} using the {@link ComponentName} from this field. 4348 * 4349 * @see #PREFERRED_PHONE_ACCOUNT_ID 4350 * @see PhoneAccountHandle#getComponentName() 4351 * @see ComponentName#flattenToString() 4352 */ 4353 String PREFERRED_PHONE_ACCOUNT_COMPONENT_NAME = "preferred_phone_account_component_name"; 4354 4355 /** 4356 * The ID of a {@link 4357 * android.telecom.PhoneAccountHandle} that is the preferred {@code PhoneAccountHandle} to 4358 * call the contact with. Used by {@link CommonDataKinds.Phone}. 4359 * 4360 * <p> On a multi-SIM device this field can be used in a {@link CommonDataKinds.Phone} row 4361 * to indicate the {@link PhoneAccountHandle} to call the number with, instead of using 4362 * {@link android.telecom.TelecomManager#getDefaultOutgoingPhoneAccount(String)} or asking 4363 * every time. 4364 * 4365 * <p>{@link android.telecom.TelecomManager#placeCall(Uri, android.os.Bundle)} 4366 * should be called with {@link android.telecom.TelecomManager#EXTRA_PHONE_ACCOUNT_HANDLE} 4367 * set to the {@link PhoneAccountHandle} using the id from this field. 4368 * 4369 * @see #PREFERRED_PHONE_ACCOUNT_COMPONENT_NAME 4370 * @see PhoneAccountHandle#getId() 4371 */ 4372 String PREFERRED_PHONE_ACCOUNT_ID = "preferred_phone_account_id"; 4373 } 4374 4375 /** 4376 * Columns in the Data_Usage_Stat table 4377 */ 4378 protected interface DataUsageStatColumns { 4379 /** 4380 * The last time (in milliseconds) this {@link Data} was used. 4381 * @deprecated Contacts affinity information is no longer supported as of 4382 * Android version {@link android.os.Build.VERSION_CODES#Q}. 4383 * This column always contains 0. 4384 * 4385 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 4386 * this field is obsolete, regardless of Android version. For more information, see the 4387 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 4388 * page.</p> 4389 */ 4390 @Deprecated 4391 public static final String LAST_TIME_USED = "last_time_used"; 4392 4393 /** 4394 * The number of times the referenced {@link Data} has been used. 4395 * @deprecated Contacts affinity information is no longer supported as of 4396 * Android version {@link android.os.Build.VERSION_CODES#Q}. 4397 * This column always contains 0. 4398 * 4399 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 4400 * this field is obsolete, regardless of Android version. For more information, see the 4401 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 4402 * page.</p> 4403 */ 4404 @Deprecated 4405 public static final String TIMES_USED = "times_used"; 4406 4407 /** @hide Raw value. */ 4408 public static final String RAW_LAST_TIME_USED = HIDDEN_COLUMN_PREFIX + LAST_TIME_USED; 4409 4410 /** @hide Raw value. */ 4411 public static final String RAW_TIMES_USED = HIDDEN_COLUMN_PREFIX + TIMES_USED; 4412 4413 /** 4414 * @hide 4415 * Low res version. Same as {@link #LAST_TIME_USED} but use it in CP2 for clarification. 4416 */ 4417 public static final String LR_LAST_TIME_USED = LAST_TIME_USED; 4418 4419 /** 4420 * @hide 4421 * Low res version. Same as {@link #TIMES_USED} but use it in CP2 for clarification. 4422 */ 4423 public static final String LR_TIMES_USED = TIMES_USED; 4424 } 4425 4426 /** 4427 * Combines all columns returned by {@link ContactsContract.Data} table queries. 4428 * 4429 * @see ContactsContract.Data 4430 */ 4431 protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns, 4432 RawContactsColumns, ContactsColumns, ContactNameColumns, ContactOptionsColumns, 4433 ContactStatusColumns, DataUsageStatColumns { 4434 } 4435 4436 /** 4437 * <p> 4438 * Constants for the data table, which contains data points tied to a raw 4439 * contact. Each row of the data table is typically used to store a single 4440 * piece of contact 4441 * information (such as a phone number) and its 4442 * associated metadata (such as whether it is a work or home number). 4443 * </p> 4444 * <h3>Data kinds</h3> 4445 * <p> 4446 * Data is a generic table that can hold any kind of contact data. 4447 * The kind of data stored in a given row is specified by the row's 4448 * {@link #MIMETYPE} value, which determines the meaning of the 4449 * generic columns {@link #DATA1} through 4450 * {@link #DATA15}. 4451 * For example, if the data kind is 4452 * {@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}, then the column 4453 * {@link #DATA1} stores the 4454 * phone number, but if the data kind is 4455 * {@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}, then {@link #DATA1} 4456 * stores the email address. 4457 * Sync adapters and applications can introduce their own data kinds. 4458 * </p> 4459 * <p> 4460 * ContactsContract defines a small number of pre-defined data kinds, e.g. 4461 * {@link CommonDataKinds.Phone}, {@link CommonDataKinds.Email} etc. As a 4462 * convenience, these classes define data kind specific aliases for DATA1 etc. 4463 * For example, {@link CommonDataKinds.Phone Phone.NUMBER} is the same as 4464 * {@link ContactsContract.Data Data.DATA1}. 4465 * </p> 4466 * <p> 4467 * {@link #DATA1} is an indexed column and should be used for the data element that is 4468 * expected to be most frequently used in query selections. For example, in the 4469 * case of a row representing email addresses {@link #DATA1} should probably 4470 * be used for the email address itself, while {@link #DATA2} etc can be 4471 * used for auxiliary information like type of email address. 4472 * <p> 4473 * <p> 4474 * By convention, {@link #DATA15} is used for storing BLOBs (binary data). 4475 * </p> 4476 * <p> 4477 * The sync adapter for a given account type must correctly handle every data type 4478 * used in the corresponding raw contacts. Otherwise it could result in lost or 4479 * corrupted data. 4480 * </p> 4481 * <p> 4482 * Similarly, you should refrain from introducing new kinds of data for an other 4483 * party's account types. For example, if you add a data row for 4484 * "favorite song" to a raw contact owned by a Google account, it will not 4485 * get synced to the server, because the Google sync adapter does not know 4486 * how to handle this data kind. Thus new data kinds are typically 4487 * introduced along with new account types, i.e. new sync adapters. 4488 * </p> 4489 * <h3>Batch operations</h3> 4490 * <p> 4491 * Data rows can be inserted/updated/deleted using the traditional 4492 * {@link ContentResolver#insert}, {@link ContentResolver#update} and 4493 * {@link ContentResolver#delete} methods, however the newer mechanism based 4494 * on a batch of {@link ContentProviderOperation} will prove to be a better 4495 * choice in almost all cases. All operations in a batch are executed in a 4496 * single transaction, which ensures that the phone-side and server-side 4497 * state of a raw contact are always consistent. Also, the batch-based 4498 * approach is far more efficient: not only are the database operations 4499 * faster when executed in a single transaction, but also sending a batch of 4500 * commands to the content provider saves a lot of time on context switching 4501 * between your process and the process in which the content provider runs. 4502 * </p> 4503 * <p> 4504 * The flip side of using batched operations is that a large batch may lock 4505 * up the database for a long time preventing other applications from 4506 * accessing data and potentially causing ANRs ("Application Not Responding" 4507 * dialogs.) 4508 * </p> 4509 * <p> 4510 * To avoid such lockups of the database, make sure to insert "yield points" 4511 * in the batch. A yield point indicates to the content provider that before 4512 * executing the next operation it can commit the changes that have already 4513 * been made, yield to other requests, open another transaction and continue 4514 * processing operations. A yield point will not automatically commit the 4515 * transaction, but only if there is another request waiting on the 4516 * database. Normally a sync adapter should insert a yield point at the 4517 * beginning of each raw contact operation sequence in the batch. See 4518 * {@link ContentProviderOperation.Builder#withYieldAllowed(boolean)}. 4519 * </p> 4520 * <h3>Operations</h3> 4521 * <dl> 4522 * <dt><b>Insert</b></dt> 4523 * <dd> 4524 * <p> 4525 * An individual data row can be inserted using the traditional 4526 * {@link ContentResolver#insert(Uri, ContentValues)} method. Multiple rows 4527 * should always be inserted as a batch. 4528 * </p> 4529 * <p> 4530 * An example of a traditional insert: 4531 * <pre> 4532 * ContentValues values = new ContentValues(); 4533 * values.put(Data.RAW_CONTACT_ID, rawContactId); 4534 * values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 4535 * values.put(Phone.NUMBER, "1-800-GOOG-411"); 4536 * values.put(Phone.TYPE, Phone.TYPE_CUSTOM); 4537 * values.put(Phone.LABEL, "free directory assistance"); 4538 * Uri dataUri = getContentResolver().insert(Data.CONTENT_URI, values); 4539 * </pre> 4540 * <p> 4541 * The same done using ContentProviderOperations: 4542 * <pre> 4543 * ArrayList<ContentProviderOperation> ops = 4544 * new ArrayList<ContentProviderOperation>(); 4545 * 4546 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 4547 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 4548 * .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE) 4549 * .withValue(Phone.NUMBER, "1-800-GOOG-411") 4550 * .withValue(Phone.TYPE, Phone.TYPE_CUSTOM) 4551 * .withValue(Phone.LABEL, "free directory assistance") 4552 * .build()); 4553 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 4554 * </pre> 4555 * </p> 4556 * <dt><b>Update</b></dt> 4557 * <dd> 4558 * <p> 4559 * Just as with insert, update can be done incrementally or as a batch, 4560 * the batch mode being the preferred method: 4561 * <pre> 4562 * ArrayList<ContentProviderOperation> ops = 4563 * new ArrayList<ContentProviderOperation>(); 4564 * 4565 * ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI) 4566 * .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}) 4567 * .withValue(Email.DATA, "somebody@android.com") 4568 * .build()); 4569 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 4570 * </pre> 4571 * </p> 4572 * </dd> 4573 * <dt><b>Delete</b></dt> 4574 * <dd> 4575 * <p> 4576 * Just as with insert and update, deletion can be done either using the 4577 * {@link ContentResolver#delete} method or using a ContentProviderOperation: 4578 * <pre> 4579 * ArrayList<ContentProviderOperation> ops = 4580 * new ArrayList<ContentProviderOperation>(); 4581 * 4582 * ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI) 4583 * .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}) 4584 * .build()); 4585 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 4586 * </pre> 4587 * </p> 4588 * </dd> 4589 * <dt><b>Query</b></dt> 4590 * <dd> 4591 * <p> 4592 * <dl> 4593 * <dt>Finding all Data of a given type for a given contact</dt> 4594 * <dd> 4595 * <pre> 4596 * Cursor c = getContentResolver().query(Data.CONTENT_URI, 4597 * new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL}, 4598 * Data.CONTACT_ID + "=?" + " AND " 4599 * + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", 4600 * new String[] {String.valueOf(contactId)}, null); 4601 * </pre> 4602 * </p> 4603 * <p> 4604 * </dd> 4605 * <dt>Finding all Data of a given type for a given raw contact</dt> 4606 * <dd> 4607 * <pre> 4608 * Cursor c = getContentResolver().query(Data.CONTENT_URI, 4609 * new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL}, 4610 * Data.RAW_CONTACT_ID + "=?" + " AND " 4611 * + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", 4612 * new String[] {String.valueOf(rawContactId)}, null); 4613 * </pre> 4614 * </dd> 4615 * <dt>Finding all Data for a given raw contact</dt> 4616 * <dd> 4617 * Most sync adapters will want to read all data rows for a raw contact 4618 * along with the raw contact itself. For that you should use the 4619 * {@link RawContactsEntity}. See also {@link RawContacts}. 4620 * </dd> 4621 * </dl> 4622 * </p> 4623 * </dd> 4624 * </dl> 4625 * <h2>Columns</h2> 4626 * <p> 4627 * Many columns are available via a {@link Data#CONTENT_URI} query. For best performance you 4628 * should explicitly specify a projection to only those columns that you need. 4629 * </p> 4630 * <table class="jd-sumtable"> 4631 * <tr> 4632 * <th colspan='4'>Data</th> 4633 * </tr> 4634 * <tr> 4635 * <td style="width: 7em;">long</td> 4636 * <td style="width: 20em;">{@link #_ID}</td> 4637 * <td style="width: 5em;">read-only</td> 4638 * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words, 4639 * it would be a bad idea to delete and reinsert a data row. A sync adapter should 4640 * always do an update instead.</td> 4641 * </tr> 4642 * <tr> 4643 * <td>String</td> 4644 * <td>{@link #MIMETYPE}</td> 4645 * <td>read/write-once</td> 4646 * <td> 4647 * <p>The MIME type of the item represented by this row. Examples of common 4648 * MIME types are: 4649 * <ul> 4650 * <li>{@link CommonDataKinds.StructuredName StructuredName.CONTENT_ITEM_TYPE}</li> 4651 * <li>{@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}</li> 4652 * <li>{@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}</li> 4653 * <li>{@link CommonDataKinds.Photo Photo.CONTENT_ITEM_TYPE}</li> 4654 * <li>{@link CommonDataKinds.Organization Organization.CONTENT_ITEM_TYPE}</li> 4655 * <li>{@link CommonDataKinds.Im Im.CONTENT_ITEM_TYPE}</li> 4656 * <li>{@link CommonDataKinds.Nickname Nickname.CONTENT_ITEM_TYPE}</li> 4657 * <li>{@link CommonDataKinds.Note Note.CONTENT_ITEM_TYPE}</li> 4658 * <li>{@link CommonDataKinds.StructuredPostal StructuredPostal.CONTENT_ITEM_TYPE}</li> 4659 * <li>{@link CommonDataKinds.GroupMembership GroupMembership.CONTENT_ITEM_TYPE}</li> 4660 * <li>{@link CommonDataKinds.Website Website.CONTENT_ITEM_TYPE}</li> 4661 * <li>{@link CommonDataKinds.Event Event.CONTENT_ITEM_TYPE}</li> 4662 * <li>{@link CommonDataKinds.Relation Relation.CONTENT_ITEM_TYPE}</li> 4663 * <li>{@link CommonDataKinds.SipAddress SipAddress.CONTENT_ITEM_TYPE}</li> 4664 * </ul> 4665 * </p> 4666 * </td> 4667 * </tr> 4668 * <tr> 4669 * <td>long</td> 4670 * <td>{@link #RAW_CONTACT_ID}</td> 4671 * <td>read/write-once</td> 4672 * <td>The id of the row in the {@link RawContacts} table that this data belongs to.</td> 4673 * </tr> 4674 * <tr> 4675 * <td>int</td> 4676 * <td>{@link #IS_PRIMARY}</td> 4677 * <td>read/write</td> 4678 * <td>Whether this is the primary entry of its kind for the raw contact it belongs to. 4679 * "1" if true, "0" if false. 4680 * </td> 4681 * </tr> 4682 * <tr> 4683 * <td>int</td> 4684 * <td>{@link #IS_SUPER_PRIMARY}</td> 4685 * <td>read/write</td> 4686 * <td>Whether this is the primary entry of its kind for the aggregate 4687 * contact it belongs to. Any data record that is "super primary" must 4688 * also be "primary". For example, the super-primary entry may be 4689 * interpreted as the default contact value of its kind (for example, 4690 * the default phone number to use for the contact).</td> 4691 * </tr> 4692 * <tr> 4693 * <td>int</td> 4694 * <td>{@link #DATA_VERSION}</td> 4695 * <td>read-only</td> 4696 * <td>The version of this data record. Whenever the data row changes 4697 * the version goes up. This value is monotonically increasing.</td> 4698 * </tr> 4699 * <tr> 4700 * <td>Any type</td> 4701 * <td> 4702 * {@link #DATA1}<br> 4703 * {@link #DATA2}<br> 4704 * {@link #DATA3}<br> 4705 * {@link #DATA4}<br> 4706 * {@link #DATA5}<br> 4707 * {@link #DATA6}<br> 4708 * {@link #DATA7}<br> 4709 * {@link #DATA8}<br> 4710 * {@link #DATA9}<br> 4711 * {@link #DATA10}<br> 4712 * {@link #DATA11}<br> 4713 * {@link #DATA12}<br> 4714 * {@link #DATA13}<br> 4715 * {@link #DATA14}<br> 4716 * {@link #DATA15} 4717 * </td> 4718 * <td>read/write</td> 4719 * <td> 4720 * <p> 4721 * Generic data columns. The meaning of each column is determined by the 4722 * {@link #MIMETYPE}. By convention, {@link #DATA15} is used for storing 4723 * BLOBs (binary data). 4724 * </p> 4725 * <p> 4726 * Data columns whose meaning is not explicitly defined for a given MIMETYPE 4727 * should not be used. There is no guarantee that any sync adapter will 4728 * preserve them. Sync adapters themselves should not use such columns either, 4729 * but should instead use {@link #SYNC1}-{@link #SYNC4}. 4730 * </p> 4731 * </td> 4732 * </tr> 4733 * <tr> 4734 * <td>Any type</td> 4735 * <td> 4736 * {@link #SYNC1}<br> 4737 * {@link #SYNC2}<br> 4738 * {@link #SYNC3}<br> 4739 * {@link #SYNC4} 4740 * </td> 4741 * <td>read/write</td> 4742 * <td>Generic columns for use by sync adapters. For example, a Photo row 4743 * may store the image URL in SYNC1, a status (not loaded, loading, loaded, error) 4744 * in SYNC2, server-side version number in SYNC3 and error code in SYNC4.</td> 4745 * </tr> 4746 * </table> 4747 * 4748 * <p> 4749 * Some columns from the most recent associated status update are also available 4750 * through an implicit join. 4751 * </p> 4752 * <table class="jd-sumtable"> 4753 * <tr> 4754 * <th colspan='4'>Join with {@link StatusUpdates}</th> 4755 * </tr> 4756 * <tr> 4757 * <td style="width: 7em;">int</td> 4758 * <td style="width: 20em;">{@link #PRESENCE}</td> 4759 * <td style="width: 5em;">read-only</td> 4760 * <td>IM presence status linked to this data row. Compare with 4761 * {@link #CONTACT_PRESENCE}, which contains the contact's presence across 4762 * all IM rows. See {@link StatusUpdates} for individual status definitions. 4763 * The provider may choose not to store this value 4764 * in persistent storage. The expectation is that presence status will be 4765 * updated on a regular basis. 4766 * </td> 4767 * </tr> 4768 * <tr> 4769 * <td>String</td> 4770 * <td>{@link #STATUS}</td> 4771 * <td>read-only</td> 4772 * <td>Latest status update linked with this data row.</td> 4773 * </tr> 4774 * <tr> 4775 * <td>long</td> 4776 * <td>{@link #STATUS_TIMESTAMP}</td> 4777 * <td>read-only</td> 4778 * <td>The absolute time in milliseconds when the latest status was 4779 * inserted/updated for this data row.</td> 4780 * </tr> 4781 * <tr> 4782 * <td>String</td> 4783 * <td>{@link #STATUS_RES_PACKAGE}</td> 4784 * <td>read-only</td> 4785 * <td>The package containing resources for this status: label and icon.</td> 4786 * </tr> 4787 * <tr> 4788 * <td>long</td> 4789 * <td>{@link #STATUS_LABEL}</td> 4790 * <td>read-only</td> 4791 * <td>The resource ID of the label describing the source of status update linked 4792 * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 4793 * </tr> 4794 * <tr> 4795 * <td>long</td> 4796 * <td>{@link #STATUS_ICON}</td> 4797 * <td>read-only</td> 4798 * <td>The resource ID of the icon for the source of the status update linked 4799 * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 4800 * </tr> 4801 * </table> 4802 * 4803 * <p> 4804 * Some columns from the associated raw contact are also available through an 4805 * implicit join. The other columns are excluded as uninteresting in this 4806 * context. 4807 * </p> 4808 * 4809 * <table class="jd-sumtable"> 4810 * <tr> 4811 * <th colspan='4'>Join with {@link ContactsContract.RawContacts}</th> 4812 * </tr> 4813 * <tr> 4814 * <td style="width: 7em;">long</td> 4815 * <td style="width: 20em;">{@link #CONTACT_ID}</td> 4816 * <td style="width: 5em;">read-only</td> 4817 * <td>The id of the row in the {@link Contacts} table that this data belongs 4818 * to.</td> 4819 * </tr> 4820 * <tr> 4821 * <td>int</td> 4822 * <td>{@link #AGGREGATION_MODE}</td> 4823 * <td>read-only</td> 4824 * <td>See {@link RawContacts}.</td> 4825 * </tr> 4826 * <tr> 4827 * <td>int</td> 4828 * <td>{@link #DELETED}</td> 4829 * <td>read-only</td> 4830 * <td>See {@link RawContacts}.</td> 4831 * </tr> 4832 * </table> 4833 * 4834 * <p> 4835 * The ID column for the associated aggregated contact table 4836 * {@link ContactsContract.Contacts} is available 4837 * via the implicit join to the {@link RawContacts} table, see above. 4838 * The remaining columns from this table are also 4839 * available, through an implicit join. This 4840 * facilitates lookup by 4841 * the value of a single data element, such as the email address. 4842 * </p> 4843 * 4844 * <table class="jd-sumtable"> 4845 * <tr> 4846 * <th colspan='4'>Join with {@link ContactsContract.Contacts}</th> 4847 * </tr> 4848 * <tr> 4849 * <td style="width: 7em;">String</td> 4850 * <td style="width: 20em;">{@link #LOOKUP_KEY}</td> 4851 * <td style="width: 5em;">read-only</td> 4852 * <td>See {@link ContactsContract.Contacts}</td> 4853 * </tr> 4854 * <tr> 4855 * <td>String</td> 4856 * <td>{@link #DISPLAY_NAME}</td> 4857 * <td>read-only</td> 4858 * <td>See {@link ContactsContract.Contacts}</td> 4859 * </tr> 4860 * <tr> 4861 * <td>long</td> 4862 * <td>{@link #PHOTO_ID}</td> 4863 * <td>read-only</td> 4864 * <td>See {@link ContactsContract.Contacts}.</td> 4865 * </tr> 4866 * <tr> 4867 * <td>int</td> 4868 * <td>{@link #IN_VISIBLE_GROUP}</td> 4869 * <td>read-only</td> 4870 * <td>See {@link ContactsContract.Contacts}.</td> 4871 * </tr> 4872 * <tr> 4873 * <td>int</td> 4874 * <td>{@link #HAS_PHONE_NUMBER}</td> 4875 * <td>read-only</td> 4876 * <td>See {@link ContactsContract.Contacts}.</td> 4877 * </tr> 4878 * <tr> 4879 * <td>int</td> 4880 * <td>{@link #STARRED}</td> 4881 * <td>read-only</td> 4882 * <td>See {@link ContactsContract.Contacts}.</td> 4883 * </tr> 4884 * <tr> 4885 * <td>String</td> 4886 * <td>{@link #CUSTOM_RINGTONE}</td> 4887 * <td>read-only</td> 4888 * <td>See {@link ContactsContract.Contacts}.</td> 4889 * </tr> 4890 * <tr> 4891 * <td>int</td> 4892 * <td>{@link #SEND_TO_VOICEMAIL}</td> 4893 * <td>read-only</td> 4894 * <td>See {@link ContactsContract.Contacts}.</td> 4895 * </tr> 4896 * <tr> 4897 * <td>int</td> 4898 * <td>{@link #CONTACT_PRESENCE}</td> 4899 * <td>read-only</td> 4900 * <td>See {@link ContactsContract.Contacts}.</td> 4901 * </tr> 4902 * <tr> 4903 * <td>String</td> 4904 * <td>{@link #CONTACT_STATUS}</td> 4905 * <td>read-only</td> 4906 * <td>See {@link ContactsContract.Contacts}.</td> 4907 * </tr> 4908 * <tr> 4909 * <td>long</td> 4910 * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td> 4911 * <td>read-only</td> 4912 * <td>See {@link ContactsContract.Contacts}.</td> 4913 * </tr> 4914 * <tr> 4915 * <td>String</td> 4916 * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td> 4917 * <td>read-only</td> 4918 * <td>See {@link ContactsContract.Contacts}.</td> 4919 * </tr> 4920 * <tr> 4921 * <td>long</td> 4922 * <td>{@link #CONTACT_STATUS_LABEL}</td> 4923 * <td>read-only</td> 4924 * <td>See {@link ContactsContract.Contacts}.</td> 4925 * </tr> 4926 * <tr> 4927 * <td>long</td> 4928 * <td>{@link #CONTACT_STATUS_ICON}</td> 4929 * <td>read-only</td> 4930 * <td>See {@link ContactsContract.Contacts}.</td> 4931 * </tr> 4932 * </table> 4933 */ 4934 public final static class Data implements DataColumnsWithJoins, ContactCounts { 4935 /** 4936 * This utility class cannot be instantiated 4937 */ Data()4938 private Data() {} 4939 4940 /** 4941 * The content:// style URI for this table, which requests a directory 4942 * of data rows matching the selection criteria. 4943 */ 4944 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data"); 4945 4946 /** 4947 * The content:// style URI for this table in managed profile, which requests a directory 4948 * of data rows matching the selection criteria. 4949 * 4950 * @hide 4951 */ 4952 static final Uri ENTERPRISE_CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, 4953 "data_enterprise"); 4954 4955 /** 4956 * A boolean parameter for {@link Data#CONTENT_URI}. 4957 * This specifies whether or not the returned data items should be filtered to show 4958 * data items belonging to visible contacts only. 4959 */ 4960 public static final String VISIBLE_CONTACTS_ONLY = "visible_contacts_only"; 4961 4962 /** 4963 * The MIME type of the results from {@link #CONTENT_URI}. 4964 */ 4965 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; 4966 4967 /** 4968 * <p> 4969 * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 4970 * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} 4971 * entry of the given {@link ContactsContract.Data} entry. 4972 * </p> 4973 * <p> 4974 * Returns the Uri for the contact in the first entry returned by 4975 * {@link ContentResolver#query(Uri, String[], String, String[], String)} 4976 * for the provided {@code dataUri}. If the query returns null or empty 4977 * results, silently returns null. 4978 * </p> 4979 */ getContactLookupUri(ContentResolver resolver, Uri dataUri)4980 public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { 4981 final Cursor cursor = resolver.query(dataUri, new String[] { 4982 RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY 4983 }, null, null, null); 4984 4985 Uri lookupUri = null; 4986 try { 4987 if (cursor != null && cursor.moveToFirst()) { 4988 final long contactId = cursor.getLong(0); 4989 final String lookupKey = cursor.getString(1); 4990 return Contacts.getLookupUri(contactId, lookupKey); 4991 } 4992 } finally { 4993 if (cursor != null) cursor.close(); 4994 } 4995 return lookupUri; 4996 } 4997 } 4998 4999 /** 5000 * <p> 5001 * Constants for the raw contacts entities table, which can be thought of as 5002 * an outer join of the raw_contacts table with the data table. It is a strictly 5003 * read-only table. 5004 * </p> 5005 * <p> 5006 * If a raw contact has data rows, the RawContactsEntity cursor will contain 5007 * a one row for each data row. If the raw contact has no data rows, the 5008 * cursor will still contain one row with the raw contact-level information 5009 * and nulls for data columns. 5010 * 5011 * <pre> 5012 * Uri entityUri = ContentUris.withAppendedId(RawContactsEntity.CONTENT_URI, rawContactId); 5013 * Cursor c = getContentResolver().query(entityUri, 5014 * new String[]{ 5015 * RawContactsEntity.SOURCE_ID, 5016 * RawContactsEntity.DATA_ID, 5017 * RawContactsEntity.MIMETYPE, 5018 * RawContactsEntity.DATA1 5019 * }, null, null, null); 5020 * try { 5021 * while (c.moveToNext()) { 5022 * String sourceId = c.getString(0); 5023 * if (!c.isNull(1)) { 5024 * String mimeType = c.getString(2); 5025 * String data = c.getString(3); 5026 * ... 5027 * } 5028 * } 5029 * } finally { 5030 * c.close(); 5031 * } 5032 * </pre> 5033 * 5034 * <h3>Columns</h3> 5035 * RawContactsEntity has a combination of RawContact and Data columns. 5036 * 5037 * <table class="jd-sumtable"> 5038 * <tr> 5039 * <th colspan='4'>RawContacts</th> 5040 * </tr> 5041 * <tr> 5042 * <td style="width: 7em;">long</td> 5043 * <td style="width: 20em;">{@link #_ID}</td> 5044 * <td style="width: 5em;">read-only</td> 5045 * <td>Raw contact row ID. See {@link RawContacts}.</td> 5046 * </tr> 5047 * <tr> 5048 * <td>long</td> 5049 * <td>{@link #CONTACT_ID}</td> 5050 * <td>read-only</td> 5051 * <td>See {@link RawContacts}.</td> 5052 * </tr> 5053 * <tr> 5054 * <td>int</td> 5055 * <td>{@link #AGGREGATION_MODE}</td> 5056 * <td>read-only</td> 5057 * <td>See {@link RawContacts}.</td> 5058 * </tr> 5059 * <tr> 5060 * <td>int</td> 5061 * <td>{@link #DELETED}</td> 5062 * <td>read-only</td> 5063 * <td>See {@link RawContacts}.</td> 5064 * </tr> 5065 * </table> 5066 * 5067 * <table class="jd-sumtable"> 5068 * <tr> 5069 * <th colspan='4'>Data</th> 5070 * </tr> 5071 * <tr> 5072 * <td style="width: 7em;">long</td> 5073 * <td style="width: 20em;">{@link #DATA_ID}</td> 5074 * <td style="width: 5em;">read-only</td> 5075 * <td>Data row ID. It will be null if the raw contact has no data rows.</td> 5076 * </tr> 5077 * <tr> 5078 * <td>String</td> 5079 * <td>{@link #MIMETYPE}</td> 5080 * <td>read-only</td> 5081 * <td>See {@link ContactsContract.Data}.</td> 5082 * </tr> 5083 * <tr> 5084 * <td>int</td> 5085 * <td>{@link #IS_PRIMARY}</td> 5086 * <td>read-only</td> 5087 * <td>See {@link ContactsContract.Data}.</td> 5088 * </tr> 5089 * <tr> 5090 * <td>int</td> 5091 * <td>{@link #IS_SUPER_PRIMARY}</td> 5092 * <td>read-only</td> 5093 * <td>See {@link ContactsContract.Data}.</td> 5094 * </tr> 5095 * <tr> 5096 * <td>int</td> 5097 * <td>{@link #DATA_VERSION}</td> 5098 * <td>read-only</td> 5099 * <td>See {@link ContactsContract.Data}.</td> 5100 * </tr> 5101 * <tr> 5102 * <td>Any type</td> 5103 * <td> 5104 * {@link #DATA1}<br> 5105 * {@link #DATA2}<br> 5106 * {@link #DATA3}<br> 5107 * {@link #DATA4}<br> 5108 * {@link #DATA5}<br> 5109 * {@link #DATA6}<br> 5110 * {@link #DATA7}<br> 5111 * {@link #DATA8}<br> 5112 * {@link #DATA9}<br> 5113 * {@link #DATA10}<br> 5114 * {@link #DATA11}<br> 5115 * {@link #DATA12}<br> 5116 * {@link #DATA13}<br> 5117 * {@link #DATA14}<br> 5118 * {@link #DATA15} 5119 * </td> 5120 * <td>read-only</td> 5121 * <td>See {@link ContactsContract.Data}.</td> 5122 * </tr> 5123 * <tr> 5124 * <td>Any type</td> 5125 * <td> 5126 * {@link #SYNC1}<br> 5127 * {@link #SYNC2}<br> 5128 * {@link #SYNC3}<br> 5129 * {@link #SYNC4} 5130 * </td> 5131 * <td>read-only</td> 5132 * <td>See {@link ContactsContract.Data}.</td> 5133 * </tr> 5134 * </table> 5135 */ 5136 public final static class RawContactsEntity 5137 implements BaseColumns, DataColumns, RawContactsColumns { 5138 /** 5139 * This utility class cannot be instantiated 5140 */ RawContactsEntity()5141 private RawContactsEntity() {} 5142 5143 /** 5144 * The content:// style URI for this table 5145 */ 5146 public static final Uri CONTENT_URI = 5147 Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities"); 5148 5149 /** 5150 * The content:// style URI for this table in corp profile 5151 * 5152 * @hide 5153 */ 5154 @TestApi 5155 public static final Uri CORP_CONTENT_URI = 5156 Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities_corp"); 5157 5158 /** 5159 * The content:// style URI for this table, specific to the user's profile. 5160 */ 5161 public static final Uri PROFILE_CONTENT_URI = 5162 Uri.withAppendedPath(Profile.CONTENT_URI, "raw_contact_entities"); 5163 5164 /** 5165 * The MIME type of {@link #CONTENT_URI} providing a directory of raw contact entities. 5166 */ 5167 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity"; 5168 5169 /** 5170 * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward 5171 * Data.CONTENT_URI contains only exportable data. 5172 * 5173 * This flag is useful (currently) only for vCard exporter in Contacts app, which 5174 * needs to exclude "un-exportable" data from available data to export, while 5175 * Contacts app itself has priviledge to access all data including "un-expotable" 5176 * ones and providers return all of them regardless of the callers' intention. 5177 * <P>Type: INTEGER</p> 5178 * 5179 * @hide Maybe available only in Eclair and not really ready for public use. 5180 * TODO: remove, or implement this feature completely. As of now (Eclair), 5181 * we only use this flag in queryEntities(), not query(). 5182 */ 5183 public static final String FOR_EXPORT_ONLY = "for_export_only"; 5184 5185 /** 5186 * The ID of the data column. The value will be null if this raw contact has no data rows. 5187 * <P>Type: INTEGER</P> 5188 */ 5189 public static final String DATA_ID = "data_id"; 5190 } 5191 5192 /** 5193 * @see PhoneLookup 5194 */ 5195 protected interface PhoneLookupColumns { 5196 /** 5197 * The ID of the data row. 5198 * <P>Type: INTEGER</P> 5199 */ 5200 public static final String DATA_ID = "data_id"; 5201 /** 5202 * A reference to the {@link ContactsContract.Contacts#_ID} that this 5203 * data belongs to. 5204 * <P>Type: INTEGER</P> 5205 */ 5206 public static final String CONTACT_ID = "contact_id"; 5207 /** 5208 * The phone number as the user entered it. 5209 * <P>Type: TEXT</P> 5210 */ 5211 public static final String NUMBER = "number"; 5212 5213 /** 5214 * The type of phone number, for example Home or Work. 5215 * <P>Type: INTEGER</P> 5216 */ 5217 public static final String TYPE = "type"; 5218 5219 /** 5220 * The user defined label for the phone number. 5221 * <P>Type: TEXT</P> 5222 */ 5223 public static final String LABEL = "label"; 5224 5225 /** 5226 * The phone number's E164 representation. 5227 * <P>Type: TEXT</P> 5228 */ 5229 public static final String NORMALIZED_NUMBER = "normalized_number"; 5230 } 5231 5232 /** 5233 * A table that represents the result of looking up a phone number, for 5234 * example for caller ID. To perform a lookup you must append the number you 5235 * want to find to {@link #CONTENT_FILTER_URI}. This query is highly 5236 * optimized. 5237 * <pre> 5238 * Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); 5239 * resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,... 5240 * </pre> 5241 * 5242 * <h3>Columns</h3> 5243 * 5244 * <table class="jd-sumtable"> 5245 * <tr> 5246 * <th colspan='4'>PhoneLookup</th> 5247 * </tr> 5248 * <tr> 5249 * <td>String</td> 5250 * <td>{@link #NUMBER}</td> 5251 * <td>read-only</td> 5252 * <td>Phone number.</td> 5253 * </tr> 5254 * <tr> 5255 * <td>String</td> 5256 * <td>{@link #TYPE}</td> 5257 * <td>read-only</td> 5258 * <td>Phone number type. See {@link CommonDataKinds.Phone}.</td> 5259 * </tr> 5260 * <tr> 5261 * <td>String</td> 5262 * <td>{@link #LABEL}</td> 5263 * <td>read-only</td> 5264 * <td>Custom label for the phone number. See {@link CommonDataKinds.Phone}.</td> 5265 * </tr> 5266 * </table> 5267 * <p> 5268 * Columns from the Contacts table are also available through a join. 5269 * </p> 5270 * <table class="jd-sumtable"> 5271 * <tr> 5272 * <th colspan='4'>Join with {@link Contacts}</th> 5273 * </tr> 5274 * <tr> 5275 * <td>long</td> 5276 * <td>{@link #_ID}</td> 5277 * <td>read-only</td> 5278 * <td>Contact ID.</td> 5279 * </tr> 5280 * <tr> 5281 * <td>long</td> 5282 * <td>{@link #CONTACT_ID}</td> 5283 * <td>read-only</td> 5284 * <td>Contact ID.</td> 5285 * </tr> 5286 * <tr> 5287 * <td>long</td> 5288 * <td>{@link #DATA_ID}</td> 5289 * <td>read-only</td> 5290 * <td>Data ID.</td> 5291 * </tr> 5292 * <tr> 5293 * <td>String</td> 5294 * <td>{@link #LOOKUP_KEY}</td> 5295 * <td>read-only</td> 5296 * <td>See {@link ContactsContract.Contacts}</td> 5297 * </tr> 5298 * <tr> 5299 * <td>String</td> 5300 * <td>{@link #DISPLAY_NAME}</td> 5301 * <td>read-only</td> 5302 * <td>See {@link ContactsContract.Contacts}</td> 5303 * </tr> 5304 * <tr> 5305 * <td>long</td> 5306 * <td>{@link #PHOTO_ID}</td> 5307 * <td>read-only</td> 5308 * <td>See {@link ContactsContract.Contacts}.</td> 5309 * </tr> 5310 * <tr> 5311 * <td>int</td> 5312 * <td>{@link #IN_VISIBLE_GROUP}</td> 5313 * <td>read-only</td> 5314 * <td>See {@link ContactsContract.Contacts}.</td> 5315 * </tr> 5316 * <tr> 5317 * <td>int</td> 5318 * <td>{@link #HAS_PHONE_NUMBER}</td> 5319 * <td>read-only</td> 5320 * <td>See {@link ContactsContract.Contacts}.</td> 5321 * </tr> 5322 * <tr> 5323 * <td>int</td> 5324 * <td>{@link #STARRED}</td> 5325 * <td>read-only</td> 5326 * <td>See {@link ContactsContract.Contacts}.</td> 5327 * </tr> 5328 * <tr> 5329 * <td>String</td> 5330 * <td>{@link #CUSTOM_RINGTONE}</td> 5331 * <td>read-only</td> 5332 * <td>See {@link ContactsContract.Contacts}.</td> 5333 * </tr> 5334 * <tr> 5335 * <td>int</td> 5336 * <td>{@link #SEND_TO_VOICEMAIL}</td> 5337 * <td>read-only</td> 5338 * <td>See {@link ContactsContract.Contacts}.</td> 5339 * </tr> 5340 * </table> 5341 */ 5342 public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns, 5343 ContactsColumns, ContactOptionsColumns, ContactNameColumns { 5344 /** 5345 * This utility class cannot be instantiated 5346 */ PhoneLookup()5347 private PhoneLookup() {} 5348 5349 /** 5350 * The content:// style URI for this table. 5351 * 5352 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this 5353 * field doesn't sort results based on contacts frequency. For more information, see the 5354 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 5355 * page. 5356 * 5357 * Append the phone number you want to lookup 5358 * to this URI and query it to perform a lookup. For example: 5359 * <pre> 5360 * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, 5361 * Uri.encode(phoneNumber)); 5362 * </pre> 5363 */ 5364 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI, 5365 "phone_lookup"); 5366 5367 /** 5368 * <p>URI used for the "enterprise caller-id".</p> 5369 * 5370 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this 5371 * field doesn't sort results based on contacts frequency. For more information, see the 5372 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 5373 * page. 5374 * 5375 * <p> 5376 * It supports the same semantics as {@link #CONTENT_FILTER_URI} and returns the same 5377 * columns. If the device has no corp profile that is linked to the current profile, it 5378 * behaves in the exact same way as {@link #CONTENT_FILTER_URI}. If there is a corp profile 5379 * linked to the current profile, it first queries against the personal contact database, 5380 * and if no matching contacts are found there, then queries against the 5381 * corp contacts database. 5382 * </p> 5383 * <p> 5384 * If a result is from the corp profile, it makes the following changes to the data: 5385 * <ul> 5386 * <li> 5387 * {@link #PHOTO_THUMBNAIL_URI} and {@link #PHOTO_URI} will be rewritten to special 5388 * URIs. Use {@link ContentResolver#openAssetFileDescriptor} or its siblings to 5389 * load pictures from them. 5390 * {@link #PHOTO_ID} and {@link #PHOTO_FILE_ID} will be set to null. Do not use them. 5391 * </li> 5392 * <li> 5393 * Corp contacts will get artificial {@link #_ID}s. In order to tell whether a contact 5394 * is from the corp profile, use 5395 * {@link ContactsContract.Contacts#isEnterpriseContactId(long)}. 5396 * </li> 5397 * <li> 5398 * Corp contacts will get artificial {@link #LOOKUP_KEY}s too. 5399 * </li> 5400 * <li> 5401 * Returned work contact IDs and lookup keys are not accepted in places that not 5402 * explicitly say to accept them. 5403 * </li> 5404 * </ul> 5405 * <p> 5406 * A contact lookup URL built by 5407 * {@link ContactsContract.Contacts#getLookupUri(long, String)} 5408 * with an {@link #_ID} and a {@link #LOOKUP_KEY} returned by this API can be passed to 5409 * {@link ContactsContract.QuickContact#showQuickContact} even if a contact is from the 5410 * corp profile. 5411 * </p> 5412 * 5413 * <pre> 5414 * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, 5415 * Uri.encode(phoneNumber)); 5416 * </pre> 5417 */ 5418 public static final Uri ENTERPRISE_CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI, 5419 "phone_lookup_enterprise"); 5420 5421 /** 5422 * The MIME type of {@link #CONTENT_FILTER_URI} providing a directory of phone lookup rows. 5423 * 5424 * @hide 5425 */ 5426 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_lookup"; 5427 5428 /** 5429 * If this boolean parameter is set to true, then the appended query is treated as a 5430 * SIP address and the lookup will be performed against SIP addresses in the user's 5431 * contacts. 5432 */ 5433 public static final String QUERY_PARAMETER_SIP_ADDRESS = "sip"; 5434 } 5435 5436 /** 5437 * Additional data mixed in with {@link StatusColumns} to link 5438 * back to specific {@link ContactsContract.Data#_ID} entries. 5439 * 5440 * @see StatusUpdates 5441 */ 5442 protected interface PresenceColumns { 5443 5444 /** 5445 * Reference to the {@link Data#_ID} entry that owns this presence. 5446 * <P>Type: INTEGER</P> 5447 */ 5448 public static final String DATA_ID = "presence_data_id"; 5449 5450 /** 5451 * See {@link CommonDataKinds.Im} for a list of defined protocol constants. 5452 * <p>Type: NUMBER</p> 5453 */ 5454 public static final String PROTOCOL = "protocol"; 5455 5456 /** 5457 * Name of the custom protocol. Should be supplied along with the {@link #PROTOCOL} value 5458 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. Should be null or 5459 * omitted if {@link #PROTOCOL} value is not 5460 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. 5461 * 5462 * <p>Type: NUMBER</p> 5463 */ 5464 public static final String CUSTOM_PROTOCOL = "custom_protocol"; 5465 5466 /** 5467 * The IM handle the presence item is for. The handle is scoped to 5468 * {@link #PROTOCOL}. 5469 * <P>Type: TEXT</P> 5470 */ 5471 public static final String IM_HANDLE = "im_handle"; 5472 5473 /** 5474 * The IM account for the local user that the presence data came from. 5475 * <P>Type: TEXT</P> 5476 */ 5477 public static final String IM_ACCOUNT = "im_account"; 5478 } 5479 5480 /** 5481 * <p> 5482 * A status update is linked to a {@link ContactsContract.Data} row and captures 5483 * the user's latest status update via the corresponding source, e.g. 5484 * "Having lunch" via "Google Talk". 5485 * </p> 5486 * <p> 5487 * There are two ways a status update can be inserted: by explicitly linking 5488 * it to a Data row using {@link #DATA_ID} or indirectly linking it to a data row 5489 * using a combination of {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and 5490 * {@link #IM_HANDLE}. There is no difference between insert and update, you can use 5491 * either. 5492 * </p> 5493 * <p> 5494 * Inserting or updating a status update for the user's profile requires either using 5495 * the {@link #DATA_ID} to identify the data row to attach the update to, or 5496 * {@link StatusUpdates#PROFILE_CONTENT_URI} to ensure that the change is scoped to the 5497 * profile. 5498 * </p> 5499 * <p> 5500 * You cannot use {@link ContentResolver#update} to change a status, but 5501 * {@link ContentResolver#insert} will replace the latests status if it already 5502 * exists. 5503 * </p> 5504 * <p> 5505 * Use {@link ContentResolver#bulkInsert(Uri, ContentValues[])} to insert/update statuses 5506 * for multiple contacts at once. 5507 * </p> 5508 * 5509 * <h3>Columns</h3> 5510 * <table class="jd-sumtable"> 5511 * <tr> 5512 * <th colspan='4'>StatusUpdates</th> 5513 * </tr> 5514 * <tr> 5515 * <td>long</td> 5516 * <td>{@link #DATA_ID}</td> 5517 * <td>read/write</td> 5518 * <td>Reference to the {@link Data#_ID} entry that owns this presence. If this 5519 * field is <i>not</i> specified, the provider will attempt to find a data row 5520 * that matches the {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and 5521 * {@link #IM_HANDLE} columns. 5522 * </td> 5523 * </tr> 5524 * <tr> 5525 * <td>long</td> 5526 * <td>{@link #PROTOCOL}</td> 5527 * <td>read/write</td> 5528 * <td>See {@link CommonDataKinds.Im} for a list of defined protocol constants.</td> 5529 * </tr> 5530 * <tr> 5531 * <td>String</td> 5532 * <td>{@link #CUSTOM_PROTOCOL}</td> 5533 * <td>read/write</td> 5534 * <td>Name of the custom protocol. Should be supplied along with the {@link #PROTOCOL} value 5535 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. Should be null or 5536 * omitted if {@link #PROTOCOL} value is not 5537 * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.</td> 5538 * </tr> 5539 * <tr> 5540 * <td>String</td> 5541 * <td>{@link #IM_HANDLE}</td> 5542 * <td>read/write</td> 5543 * <td> The IM handle the presence item is for. The handle is scoped to 5544 * {@link #PROTOCOL}.</td> 5545 * </tr> 5546 * <tr> 5547 * <td>String</td> 5548 * <td>{@link #IM_ACCOUNT}</td> 5549 * <td>read/write</td> 5550 * <td>The IM account for the local user that the presence data came from.</td> 5551 * </tr> 5552 * <tr> 5553 * <td>int</td> 5554 * <td>{@link #PRESENCE}</td> 5555 * <td>read/write</td> 5556 * <td>Contact IM presence status. The allowed values are: 5557 * <p> 5558 * <ul> 5559 * <li>{@link #OFFLINE}</li> 5560 * <li>{@link #INVISIBLE}</li> 5561 * <li>{@link #AWAY}</li> 5562 * <li>{@link #IDLE}</li> 5563 * <li>{@link #DO_NOT_DISTURB}</li> 5564 * <li>{@link #AVAILABLE}</li> 5565 * </ul> 5566 * </p> 5567 * <p> 5568 * Since presence status is inherently volatile, the content provider 5569 * may choose not to store this field in long-term storage. 5570 * </p> 5571 * </td> 5572 * </tr> 5573 * <tr> 5574 * <td>int</td> 5575 * <td>{@link #CHAT_CAPABILITY}</td> 5576 * <td>read/write</td> 5577 * <td>Contact IM chat compatibility value. The allowed values combinations of the following 5578 * flags. If None of these flags is set, the device can only do text messaging. 5579 * <p> 5580 * <ul> 5581 * <li>{@link #CAPABILITY_HAS_VIDEO}</li> 5582 * <li>{@link #CAPABILITY_HAS_VOICE}</li> 5583 * <li>{@link #CAPABILITY_HAS_CAMERA}</li> 5584 * </ul> 5585 * </p> 5586 * <p> 5587 * Since chat compatibility is inherently volatile as the contact's availability moves from 5588 * one device to another, the content provider may choose not to store this field in long-term 5589 * storage. 5590 * </p> 5591 * </td> 5592 * </tr> 5593 * <tr> 5594 * <td>String</td> 5595 * <td>{@link #STATUS}</td> 5596 * <td>read/write</td> 5597 * <td>Contact's latest status update, e.g. "having toast for breakfast"</td> 5598 * </tr> 5599 * <tr> 5600 * <td>long</td> 5601 * <td>{@link #STATUS_TIMESTAMP}</td> 5602 * <td>read/write</td> 5603 * <td>The absolute time in milliseconds when the status was 5604 * entered by the user. If this value is not provided, the provider will follow 5605 * this logic: if there was no prior status update, the value will be left as null. 5606 * If there was a prior status update, the provider will default this field 5607 * to the current time.</td> 5608 * </tr> 5609 * <tr> 5610 * <td>String</td> 5611 * <td>{@link #STATUS_RES_PACKAGE}</td> 5612 * <td>read/write</td> 5613 * <td> The package containing resources for this status: label and icon.</td> 5614 * </tr> 5615 * <tr> 5616 * <td>long</td> 5617 * <td>{@link #STATUS_LABEL}</td> 5618 * <td>read/write</td> 5619 * <td>The resource ID of the label describing the source of contact status, 5620 * e.g. "Google Talk". This resource is scoped by the 5621 * {@link #STATUS_RES_PACKAGE}.</td> 5622 * </tr> 5623 * <tr> 5624 * <td>long</td> 5625 * <td>{@link #STATUS_ICON}</td> 5626 * <td>read/write</td> 5627 * <td>The resource ID of the icon for the source of contact status. This 5628 * resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td> 5629 * </tr> 5630 * </table> 5631 */ 5632 public static class StatusUpdates implements StatusColumns, PresenceColumns { 5633 5634 /** 5635 * This utility class cannot be instantiated 5636 */ StatusUpdates()5637 private StatusUpdates() {} 5638 5639 /** 5640 * The content:// style URI for this table 5641 */ 5642 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "status_updates"); 5643 5644 /** 5645 * The content:// style URI for this table, specific to the user's profile. 5646 */ 5647 public static final Uri PROFILE_CONTENT_URI = 5648 Uri.withAppendedPath(Profile.CONTENT_URI, "status_updates"); 5649 5650 /** 5651 * Gets the resource ID for the proper presence icon. 5652 * 5653 * @param status the status to get the icon for 5654 * @return the resource ID for the proper presence icon 5655 */ getPresenceIconResourceId(int status)5656 public static final int getPresenceIconResourceId(int status) { 5657 switch (status) { 5658 case AVAILABLE: 5659 return android.R.drawable.presence_online; 5660 case IDLE: 5661 case AWAY: 5662 return android.R.drawable.presence_away; 5663 case DO_NOT_DISTURB: 5664 return android.R.drawable.presence_busy; 5665 case INVISIBLE: 5666 return android.R.drawable.presence_invisible; 5667 case OFFLINE: 5668 default: 5669 return android.R.drawable.presence_offline; 5670 } 5671 } 5672 5673 /** 5674 * Returns the precedence of the status code the higher number being the higher precedence. 5675 * 5676 * @param status The status code. 5677 * @return An integer representing the precedence, 0 being the lowest. 5678 */ getPresencePrecedence(int status)5679 public static final int getPresencePrecedence(int status) { 5680 // Keep this function here incase we want to enforce a different precedence than the 5681 // natural order of the status constants. 5682 return status; 5683 } 5684 5685 /** 5686 * The MIME type of {@link #CONTENT_URI} providing a directory of 5687 * status update details. 5688 */ 5689 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/status-update"; 5690 5691 /** 5692 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single 5693 * status update detail. 5694 */ 5695 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update"; 5696 } 5697 5698 /** 5699 * @deprecated This old name was never meant to be made public. Do not use. 5700 */ 5701 @Deprecated 5702 public static final class Presence extends StatusUpdates { 5703 5704 } 5705 5706 /** 5707 * Additional column returned by 5708 * {@link ContactsContract.Contacts#CONTENT_FILTER_URI Contacts.CONTENT_FILTER_URI} explaining 5709 * why the filter matched the contact. This column will contain extracts from the contact's 5710 * constituent {@link Data Data} items, formatted in a way that indicates the section of the 5711 * snippet that matched the filter. 5712 * 5713 * <p> 5714 * The following example searches for all contacts that match the query "presi" and requests 5715 * the snippet column as well. 5716 * <pre> 5717 * Builder builder = Contacts.CONTENT_FILTER_URI.buildUpon(); 5718 * builder.appendPath("presi"); 5719 * // Defer snippeting to the client side if possible, for performance reasons. 5720 * builder.appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY,"1"); 5721 * 5722 * Cursor cursor = getContentResolver().query(builder.build()); 5723 * 5724 * Bundle extras = cursor.getExtras(); 5725 * if (extras.getBoolean(ContactsContract.DEFERRED_SNIPPETING)) { 5726 * // Do our own snippet formatting. 5727 * // For a contact with the email address (president@organization.com), the snippet 5728 * // column will contain the string "president@organization.com". 5729 * } else { 5730 * // The snippet has already been pre-formatted, we can display it as is. 5731 * // For a contact with the email address (president@organization.com), the snippet 5732 * // column will contain the string "[presi]dent@organization.com". 5733 * } 5734 * </pre> 5735 * </p> 5736 */ 5737 public static class SearchSnippets { 5738 5739 /** 5740 * The search snippet constructed by SQLite snippeting functionality. 5741 * <p> 5742 * The snippet may contain (parts of) several data elements belonging to the contact, 5743 * with the matching parts optionally surrounded by special characters that indicate the 5744 * start and end of matching text. 5745 * 5746 * For example, if a contact has an address "123 Main Street", using a filter "mai" would 5747 * return the formatted snippet "123 [Mai]n street". 5748 * 5749 * @see <a href="http://www.sqlite.org/fts3.html#snippet"> 5750 * http://www.sqlite.org/fts3.html#snippet</a> 5751 */ 5752 public static final String SNIPPET = "snippet"; 5753 5754 /** 5755 * Comma-separated parameters for the generation of the snippet: 5756 * <ul> 5757 * <li>The "start match" text. Default is '['</li> 5758 * <li>The "end match" text. Default is ']'</li> 5759 * <li>The "ellipsis" text. Default is "..."</li> 5760 * <li>Maximum number of tokens to include in the snippet. Can be either 5761 * a positive or a negative number: A positive number indicates how many 5762 * tokens can be returned in total. A negative number indicates how many 5763 * tokens can be returned per occurrence of the search terms.</li> 5764 * </ul> 5765 * 5766 * @hide 5767 */ 5768 public static final String SNIPPET_ARGS_PARAM_KEY = "snippet_args"; 5769 5770 /** 5771 * The key to ask the provider to defer the formatting of the snippet to the client if 5772 * possible, for performance reasons. 5773 * A value of 1 indicates true, 0 indicates false. False is the default. 5774 * When a cursor is returned to the client, it should check for an extra with the name 5775 * {@link ContactsContract#DEFERRED_SNIPPETING} in the cursor. If it exists, the client 5776 * should do its own formatting of the snippet. If it doesn't exist, the snippet column 5777 * in the cursor should already contain a formatted snippet. 5778 */ 5779 public static final String DEFERRED_SNIPPETING_KEY = "deferred_snippeting"; 5780 } 5781 5782 /** 5783 * Container for definitions of common data types stored in the {@link ContactsContract.Data} 5784 * table. 5785 */ 5786 public static final class CommonDataKinds { 5787 /** 5788 * This utility class cannot be instantiated 5789 */ CommonDataKinds()5790 private CommonDataKinds() {} 5791 5792 /** 5793 * The {@link Data#RES_PACKAGE} value for common data that should be 5794 * shown using a default style. 5795 * 5796 * @hide RES_PACKAGE is hidden 5797 */ 5798 public static final String PACKAGE_COMMON = "common"; 5799 5800 /** 5801 * The base types that all "Typed" data kinds support. 5802 */ 5803 public interface BaseTypes { 5804 /** 5805 * A custom type. The custom label should be supplied by user. 5806 */ 5807 public static int TYPE_CUSTOM = 0; 5808 } 5809 5810 /** 5811 * Columns common across the specific types. 5812 */ 5813 protected interface CommonColumns extends BaseTypes { 5814 /** 5815 * The data for the contact method. 5816 * <P>Type: TEXT</P> 5817 */ 5818 public static final String DATA = DataColumns.DATA1; 5819 5820 /** 5821 * The type of data, for example Home or Work. 5822 * <P>Type: INTEGER</P> 5823 */ 5824 public static final String TYPE = DataColumns.DATA2; 5825 5826 /** 5827 * The user defined label for the the contact method. 5828 * <P>Type: TEXT</P> 5829 */ 5830 public static final String LABEL = DataColumns.DATA3; 5831 } 5832 5833 /** 5834 * A data kind representing the contact's proper name. You can use all 5835 * columns defined for {@link ContactsContract.Data} as well as the following aliases. 5836 * 5837 * <h2>Column aliases</h2> 5838 * <table class="jd-sumtable"> 5839 * <tr> 5840 * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th> 5841 * </tr> 5842 * <tr> 5843 * <td>String</td> 5844 * <td>{@link #DISPLAY_NAME}</td> 5845 * <td>{@link #DATA1}</td> 5846 * <td></td> 5847 * </tr> 5848 * <tr> 5849 * <td>String</td> 5850 * <td>{@link #GIVEN_NAME}</td> 5851 * <td>{@link #DATA2}</td> 5852 * <td></td> 5853 * </tr> 5854 * <tr> 5855 * <td>String</td> 5856 * <td>{@link #FAMILY_NAME}</td> 5857 * <td>{@link #DATA3}</td> 5858 * <td></td> 5859 * </tr> 5860 * <tr> 5861 * <td>String</td> 5862 * <td>{@link #PREFIX}</td> 5863 * <td>{@link #DATA4}</td> 5864 * <td>Common prefixes in English names are "Mr", "Ms", "Dr" etc.</td> 5865 * </tr> 5866 * <tr> 5867 * <td>String</td> 5868 * <td>{@link #MIDDLE_NAME}</td> 5869 * <td>{@link #DATA5}</td> 5870 * <td></td> 5871 * </tr> 5872 * <tr> 5873 * <td>String</td> 5874 * <td>{@link #SUFFIX}</td> 5875 * <td>{@link #DATA6}</td> 5876 * <td>Common suffixes in English names are "Sr", "Jr", "III" etc.</td> 5877 * </tr> 5878 * <tr> 5879 * <td>String</td> 5880 * <td>{@link #PHONETIC_GIVEN_NAME}</td> 5881 * <td>{@link #DATA7}</td> 5882 * <td>Used for phonetic spelling of the name, e.g. Pinyin, Katakana, Hiragana</td> 5883 * </tr> 5884 * <tr> 5885 * <td>String</td> 5886 * <td>{@link #PHONETIC_MIDDLE_NAME}</td> 5887 * <td>{@link #DATA8}</td> 5888 * <td></td> 5889 * </tr> 5890 * <tr> 5891 * <td>String</td> 5892 * <td>{@link #PHONETIC_FAMILY_NAME}</td> 5893 * <td>{@link #DATA9}</td> 5894 * <td></td> 5895 * </tr> 5896 * </table> 5897 */ 5898 public static final class StructuredName implements DataColumnsWithJoins, ContactCounts { 5899 /** 5900 * This utility class cannot be instantiated 5901 */ StructuredName()5902 private StructuredName() {} 5903 5904 /** MIME type used when storing this in data table. */ 5905 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name"; 5906 5907 /** 5908 * The name that should be used to display the contact. 5909 * <i>Unstructured component of the name should be consistent with 5910 * its structured representation.</i> 5911 * <p> 5912 * Type: TEXT 5913 */ 5914 public static final String DISPLAY_NAME = DATA1; 5915 5916 /** 5917 * The given name for the contact. 5918 * <P>Type: TEXT</P> 5919 */ 5920 public static final String GIVEN_NAME = DATA2; 5921 5922 /** 5923 * The family name for the contact. 5924 * <P>Type: TEXT</P> 5925 */ 5926 public static final String FAMILY_NAME = DATA3; 5927 5928 /** 5929 * The contact's honorific prefix, e.g. "Sir" 5930 * <P>Type: TEXT</P> 5931 */ 5932 public static final String PREFIX = DATA4; 5933 5934 /** 5935 * The contact's middle name 5936 * <P>Type: TEXT</P> 5937 */ 5938 public static final String MIDDLE_NAME = DATA5; 5939 5940 /** 5941 * The contact's honorific suffix, e.g. "Jr" 5942 */ 5943 public static final String SUFFIX = DATA6; 5944 5945 /** 5946 * The phonetic version of the given name for the contact. 5947 * <P>Type: TEXT</P> 5948 */ 5949 public static final String PHONETIC_GIVEN_NAME = DATA7; 5950 5951 /** 5952 * The phonetic version of the additional name for the contact. 5953 * <P>Type: TEXT</P> 5954 */ 5955 public static final String PHONETIC_MIDDLE_NAME = DATA8; 5956 5957 /** 5958 * The phonetic version of the family name for the contact. 5959 * <P>Type: TEXT</P> 5960 */ 5961 public static final String PHONETIC_FAMILY_NAME = DATA9; 5962 5963 /** 5964 * The style used for combining given/middle/family name into a full name. 5965 * See {@link ContactsContract.FullNameStyle}. 5966 */ 5967 public static final String FULL_NAME_STYLE = DATA10; 5968 5969 /** 5970 * The alphabet used for capturing the phonetic name. 5971 * See ContactsContract.PhoneticNameStyle. 5972 */ 5973 public static final String PHONETIC_NAME_STYLE = DATA11; 5974 } 5975 5976 /** 5977 * <p>A data kind representing the contact's nickname. For example, for 5978 * Bob Parr ("Mr. Incredible"): 5979 * <pre> 5980 * ArrayList<ContentProviderOperation> ops = 5981 * new ArrayList<ContentProviderOperation>(); 5982 * 5983 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 5984 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 5985 * .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 5986 * .withValue(StructuredName.DISPLAY_NAME, "Bob Parr") 5987 * .build()); 5988 * 5989 * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI) 5990 * .withValue(Data.RAW_CONTACT_ID, rawContactId) 5991 * .withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE) 5992 * .withValue(Nickname.NAME, "Mr. Incredible") 5993 * .withValue(Nickname.TYPE, Nickname.TYPE_CUSTOM) 5994 * .withValue(Nickname.LABEL, "Superhero") 5995 * .build()); 5996 * 5997 * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 5998 * </pre> 5999 * </p> 6000 * <p> 6001 * You can use all columns defined for {@link ContactsContract.Data} as well as the 6002 * following aliases. 6003 * </p> 6004 * 6005 * <h2>Column aliases</h2> 6006 * <table class="jd-sumtable"> 6007 * <tr> 6008 * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th> 6009 * </tr> 6010 * <tr> 6011 * <td>String</td> 6012 * <td>{@link #NAME}</td> 6013 * <td>{@link #DATA1}</td> 6014 * <td></td> 6015 * </tr> 6016 * <tr> 6017 * <td>int</td> 6018 * <td>{@link #TYPE}</td> 6019 * <td>{@link #DATA2}</td> 6020 * <td> 6021 * Allowed values are: 6022 * <p> 6023 * <ul> 6024 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 6025 * <li>{@link #TYPE_DEFAULT}</li> 6026 * <li>{@link #TYPE_OTHER_NAME}</li> 6027 * <li>{@link #TYPE_MAIDEN_NAME}</li> 6028 * <li>{@link #TYPE_SHORT_NAME}</li> 6029 * <li>{@link #TYPE_INITIALS}</li> 6030 * </ul> 6031 * </p> 6032 * </td> 6033 * </tr> 6034 * <tr> 6035 * <td>String</td> 6036 * <td>{@link #LABEL}</td> 6037 * <td>{@link #DATA3}</td> 6038 * <td></td> 6039 * </tr> 6040 * </table> 6041 */ 6042 public static final class Nickname implements DataColumnsWithJoins, CommonColumns, 6043 ContactCounts{ 6044 /** 6045 * This utility class cannot be instantiated 6046 */ Nickname()6047 private Nickname() {} 6048 6049 /** MIME type used when storing this in data table. */ 6050 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname"; 6051 6052 public static final int TYPE_DEFAULT = 1; 6053 public static final int TYPE_OTHER_NAME = 2; 6054 public static final int TYPE_MAIDEN_NAME = 3; 6055 /** @deprecated Use TYPE_MAIDEN_NAME instead. */ 6056 @Deprecated 6057 public static final int TYPE_MAINDEN_NAME = 3; 6058 public static final int TYPE_SHORT_NAME = 4; 6059 public static final int TYPE_INITIALS = 5; 6060 6061 /** 6062 * The name itself 6063 */ 6064 public static final String NAME = DATA; 6065 } 6066 6067 /** 6068 * <p> 6069 * A data kind representing a telephone number. 6070 * </p> 6071 * <p> 6072 * You can use all columns defined for {@link ContactsContract.Data} as 6073 * well as the following aliases. 6074 * </p> 6075 * <h2>Column aliases</h2> 6076 * <table class="jd-sumtable"> 6077 * <tr> 6078 * <th>Type</th> 6079 * <th>Alias</th><th colspan='2'>Data column</th> 6080 * </tr> 6081 * <tr> 6082 * <td>String</td> 6083 * <td>{@link #NUMBER}</td> 6084 * <td>{@link #DATA1}</td> 6085 * <td></td> 6086 * </tr> 6087 * <tr> 6088 * <td>int</td> 6089 * <td>{@link #TYPE}</td> 6090 * <td>{@link #DATA2}</td> 6091 * <td>Allowed values are: 6092 * <p> 6093 * <ul> 6094 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 6095 * <li>{@link #TYPE_HOME}</li> 6096 * <li>{@link #TYPE_MOBILE}</li> 6097 * <li>{@link #TYPE_WORK}</li> 6098 * <li>{@link #TYPE_FAX_WORK}</li> 6099 * <li>{@link #TYPE_FAX_HOME}</li> 6100 * <li>{@link #TYPE_PAGER}</li> 6101 * <li>{@link #TYPE_OTHER}</li> 6102 * <li>{@link #TYPE_CALLBACK}</li> 6103 * <li>{@link #TYPE_CAR}</li> 6104 * <li>{@link #TYPE_COMPANY_MAIN}</li> 6105 * <li>{@link #TYPE_ISDN}</li> 6106 * <li>{@link #TYPE_MAIN}</li> 6107 * <li>{@link #TYPE_OTHER_FAX}</li> 6108 * <li>{@link #TYPE_RADIO}</li> 6109 * <li>{@link #TYPE_TELEX}</li> 6110 * <li>{@link #TYPE_TTY_TDD}</li> 6111 * <li>{@link #TYPE_WORK_MOBILE}</li> 6112 * <li>{@link #TYPE_WORK_PAGER}</li> 6113 * <li>{@link #TYPE_ASSISTANT}</li> 6114 * <li>{@link #TYPE_MMS}</li> 6115 * </ul> 6116 * </p> 6117 * </td> 6118 * </tr> 6119 * <tr> 6120 * <td>String</td> 6121 * <td>{@link #LABEL}</td> 6122 * <td>{@link #DATA3}</td> 6123 * <td></td> 6124 * </tr> 6125 * </table> 6126 */ 6127 public static final class Phone implements DataColumnsWithJoins, CommonColumns, 6128 ContactCounts { 6129 /** 6130 * This utility class cannot be instantiated 6131 */ Phone()6132 private Phone() {} 6133 6134 /** MIME type used when storing this in data table. */ 6135 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2"; 6136 6137 /** 6138 * The MIME type of {@link #CONTENT_URI} providing a directory of 6139 * phones. 6140 */ 6141 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2"; 6142 6143 /** 6144 * The content:// style URI for all data records of the 6145 * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the 6146 * associated raw contact and aggregate contact data. 6147 */ 6148 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 6149 "phones"); 6150 6151 /** 6152 * URI used for getting all contacts from primary and managed profile. 6153 * 6154 * It supports the same semantics as {@link #CONTENT_URI} and returns the same 6155 * columns. If the device has no corp profile that is linked to the current profile, it 6156 * behaves in the exact same way as {@link #CONTENT_URI}. If there is a corp profile 6157 * linked to the current profile, it will merge corp profile and current profile's 6158 * results and return 6159 * 6160 * @hide 6161 */ 6162 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 6163 @TestApi 6164 public static final Uri ENTERPRISE_CONTENT_URI = 6165 Uri.withAppendedPath(Data.ENTERPRISE_CONTENT_URI, "phones"); 6166 6167 /** 6168 * <p>The content:// style URL for phone lookup using a filter. The filter returns 6169 * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied 6170 * to display names as well as phone numbers. The filter argument should be passed 6171 * as an additional path segment after this URI. 6172 * 6173 * <p class="caution"><b>Caution: </b>This field doesn't sort results based on contacts 6174 * frequency. For more information, see the 6175 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 6176 * page. 6177 */ 6178 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, 6179 "filter"); 6180 6181 /** 6182 * <p>It supports the similar semantics as {@link #CONTENT_FILTER_URI} and returns the 6183 * same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in 6184 * parameters, otherwise it will throw IllegalArgumentException. 6185 * 6186 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 6187 * this field doesn't sort results based on contacts frequency. For more information, 6188 * see the 6189 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 6190 * page. 6191 */ 6192 public static final Uri ENTERPRISE_CONTENT_FILTER_URI = Uri.withAppendedPath( 6193 CONTENT_URI, "filter_enterprise"); 6194 6195 /** 6196 * A boolean query parameter that can be used with {@link #CONTENT_FILTER_URI}. 6197 * If "1" or "true", display names are searched. If "0" or "false", display names 6198 * are not searched. Default is "1". 6199 */ 6200 public static final String SEARCH_DISPLAY_NAME_KEY = "search_display_name"; 6201 6202 /** 6203 * A boolean query parameter that can be used with {@link #CONTENT_FILTER_URI}. 6204 * If "1" or "true", phone numbers are searched. If "0" or "false", phone numbers 6205 * are not searched. Default is "1". 6206 */ 6207 public static final String SEARCH_PHONE_NUMBER_KEY = "search_phone_number"; 6208 6209 public static final int TYPE_HOME = 1; 6210 public static final int TYPE_MOBILE = 2; 6211 public static final int TYPE_WORK = 3; 6212 public static final int TYPE_FAX_WORK = 4; 6213 public static final int TYPE_FAX_HOME = 5; 6214 public static final int TYPE_PAGER = 6; 6215 public static final int TYPE_OTHER = 7; 6216 public static final int TYPE_CALLBACK = 8; 6217 public static final int TYPE_CAR = 9; 6218 public static final int TYPE_COMPANY_MAIN = 10; 6219 public static final int TYPE_ISDN = 11; 6220 public static final int TYPE_MAIN = 12; 6221 public static final int TYPE_OTHER_FAX = 13; 6222 public static final int TYPE_RADIO = 14; 6223 public static final int TYPE_TELEX = 15; 6224 public static final int TYPE_TTY_TDD = 16; 6225 public static final int TYPE_WORK_MOBILE = 17; 6226 public static final int TYPE_WORK_PAGER = 18; 6227 public static final int TYPE_ASSISTANT = 19; 6228 public static final int TYPE_MMS = 20; 6229 6230 /** 6231 * The phone number as the user entered it. 6232 * <P>Type: TEXT</P> 6233 */ 6234 public static final String NUMBER = DATA; 6235 6236 /** 6237 * The phone number's E164 representation. This value can be omitted in which 6238 * case the provider will try to automatically infer it. (It'll be left null if the 6239 * provider fails to infer.) 6240 * If present, {@link #NUMBER} has to be set as well (it will be ignored otherwise). 6241 * <P>Type: TEXT</P> 6242 */ 6243 public static final String NORMALIZED_NUMBER = DATA4; 6244 6245 /** 6246 * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. 6247 * @hide 6248 */ 6249 @Deprecated getDisplayLabel(Context context, int type, CharSequence label, CharSequence[] labelArray)6250 public static final CharSequence getDisplayLabel(Context context, int type, 6251 CharSequence label, CharSequence[] labelArray) { 6252 return getTypeLabel(context.getResources(), type, label); 6253 } 6254 6255 /** 6256 * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. 6257 * @hide 6258 */ 6259 @Deprecated 6260 @UnsupportedAppUsage getDisplayLabel(Context context, int type, CharSequence label)6261 public static final CharSequence getDisplayLabel(Context context, int type, 6262 CharSequence label) { 6263 return getTypeLabel(context.getResources(), type, label); 6264 } 6265 6266 /** 6267 * Return the string resource that best describes the given 6268 * {@link #TYPE}. Will always return a valid resource. 6269 */ getTypeLabelResource(int type)6270 public static final int getTypeLabelResource(int type) { 6271 switch (type) { 6272 case TYPE_HOME: return com.android.internal.R.string.phoneTypeHome; 6273 case TYPE_MOBILE: return com.android.internal.R.string.phoneTypeMobile; 6274 case TYPE_WORK: return com.android.internal.R.string.phoneTypeWork; 6275 case TYPE_FAX_WORK: return com.android.internal.R.string.phoneTypeFaxWork; 6276 case TYPE_FAX_HOME: return com.android.internal.R.string.phoneTypeFaxHome; 6277 case TYPE_PAGER: return com.android.internal.R.string.phoneTypePager; 6278 case TYPE_OTHER: return com.android.internal.R.string.phoneTypeOther; 6279 case TYPE_CALLBACK: return com.android.internal.R.string.phoneTypeCallback; 6280 case TYPE_CAR: return com.android.internal.R.string.phoneTypeCar; 6281 case TYPE_COMPANY_MAIN: return com.android.internal.R.string.phoneTypeCompanyMain; 6282 case TYPE_ISDN: return com.android.internal.R.string.phoneTypeIsdn; 6283 case TYPE_MAIN: return com.android.internal.R.string.phoneTypeMain; 6284 case TYPE_OTHER_FAX: return com.android.internal.R.string.phoneTypeOtherFax; 6285 case TYPE_RADIO: return com.android.internal.R.string.phoneTypeRadio; 6286 case TYPE_TELEX: return com.android.internal.R.string.phoneTypeTelex; 6287 case TYPE_TTY_TDD: return com.android.internal.R.string.phoneTypeTtyTdd; 6288 case TYPE_WORK_MOBILE: return com.android.internal.R.string.phoneTypeWorkMobile; 6289 case TYPE_WORK_PAGER: return com.android.internal.R.string.phoneTypeWorkPager; 6290 case TYPE_ASSISTANT: return com.android.internal.R.string.phoneTypeAssistant; 6291 case TYPE_MMS: return com.android.internal.R.string.phoneTypeMms; 6292 default: return com.android.internal.R.string.phoneTypeCustom; 6293 } 6294 } 6295 6296 /** 6297 * Return a {@link CharSequence} that best describes the given type, 6298 * possibly substituting the given {@link #LABEL} value 6299 * for {@link #TYPE_CUSTOM}. 6300 */ getTypeLabel(Resources res, int type, CharSequence label)6301 public static final CharSequence getTypeLabel(Resources res, int type, 6302 CharSequence label) { 6303 if ((type == TYPE_CUSTOM || type == TYPE_ASSISTANT) && !TextUtils.isEmpty(label)) { 6304 return label; 6305 } else { 6306 final int labelRes = getTypeLabelResource(type); 6307 return res.getText(labelRes); 6308 } 6309 } 6310 } 6311 6312 /** 6313 * <p> 6314 * A data kind representing an email address. 6315 * </p> 6316 * <p> 6317 * You can use all columns defined for {@link ContactsContract.Data} as 6318 * well as the following aliases. 6319 * </p> 6320 * <h2>Column aliases</h2> 6321 * <table class="jd-sumtable"> 6322 * <tr> 6323 * <th>Type</th> 6324 * <th>Alias</th><th colspan='2'>Data column</th> 6325 * </tr> 6326 * <tr> 6327 * <td>String</td> 6328 * <td>{@link #ADDRESS}</td> 6329 * <td>{@link #DATA1}</td> 6330 * <td>Email address itself.</td> 6331 * </tr> 6332 * <tr> 6333 * <td>int</td> 6334 * <td>{@link #TYPE}</td> 6335 * <td>{@link #DATA2}</td> 6336 * <td>Allowed values are: 6337 * <p> 6338 * <ul> 6339 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 6340 * <li>{@link #TYPE_HOME}</li> 6341 * <li>{@link #TYPE_WORK}</li> 6342 * <li>{@link #TYPE_OTHER}</li> 6343 * <li>{@link #TYPE_MOBILE}</li> 6344 * </ul> 6345 * </p> 6346 * </td> 6347 * </tr> 6348 * <tr> 6349 * <td>String</td> 6350 * <td>{@link #LABEL}</td> 6351 * <td>{@link #DATA3}</td> 6352 * <td></td> 6353 * </tr> 6354 * </table> 6355 */ 6356 public static final class Email implements DataColumnsWithJoins, CommonColumns, 6357 ContactCounts { 6358 /* 6359 * This utility class cannot be instantiated 6360 */ Email()6361 private Email() {} 6362 6363 /** MIME type used when storing this in data table. */ 6364 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2"; 6365 6366 /** 6367 * The MIME type of {@link #CONTENT_URI} providing a directory of email addresses. 6368 */ 6369 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2"; 6370 6371 /** 6372 * The content:// style URI for all data records of the 6373 * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the 6374 * associated raw contact and aggregate contact data. 6375 */ 6376 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 6377 "emails"); 6378 6379 /** 6380 * <p> 6381 * The content:// style URL for looking up data rows by email address. The 6382 * lookup argument, an email address, should be passed as an additional path segment 6383 * after this URI. 6384 * </p> 6385 * <p>Example: 6386 * <pre> 6387 * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(email)); 6388 * Cursor c = getContentResolver().query(uri, 6389 * new String[]{Email.CONTACT_ID, Email.DISPLAY_NAME, Email.DATA}, 6390 * null, null, null); 6391 * </pre> 6392 * </p> 6393 */ 6394 public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, 6395 "lookup"); 6396 6397 /** 6398 * <p>URI used for enterprise email lookup.</p> 6399 * 6400 * <p> 6401 * It supports the same semantics as {@link #CONTENT_LOOKUP_URI} and returns the same 6402 * columns. If the device has no corp profile that is linked to the current profile, it 6403 * behaves in the exact same way as {@link #CONTENT_LOOKUP_URI}. If there is a 6404 * corp profile linked to the current profile, it first queries against the personal contact database, 6405 * and if no matching contacts are found there, then queries against the 6406 * corp contacts database. 6407 * </p> 6408 * <p> 6409 * If a result is from the corp profile, it makes the following changes to the data: 6410 * <ul> 6411 * <li> 6412 * {@link #PHOTO_THUMBNAIL_URI} and {@link #PHOTO_URI} will be rewritten to special 6413 * URIs. Use {@link ContentResolver#openAssetFileDescriptor} or its siblings to 6414 * load pictures from them. 6415 * {@link #PHOTO_ID} and {@link #PHOTO_FILE_ID} will be set to null. Do not 6416 * use them. 6417 * </li> 6418 * <li> 6419 * Corp contacts will get artificial {@link #CONTACT_ID}s. In order to tell whether 6420 * a contact 6421 * is from the corp profile, use 6422 * {@link ContactsContract.Contacts#isEnterpriseContactId(long)}. 6423 * </li> 6424 * <li> 6425 * Corp contacts will get artificial {@link #LOOKUP_KEY}s too. 6426 * </li> 6427 * <li> 6428 * Returned work contact IDs and lookup keys are not accepted in places that not 6429 * explicitly say to accept them. 6430 * </li> 6431 * </ul> 6432 * <p> 6433 * A contact lookup URL built by 6434 * {@link ContactsContract.Contacts#getLookupUri(long, String)} 6435 * with an {@link #_ID} and a {@link #LOOKUP_KEY} returned by this API can be passed to 6436 * {@link ContactsContract.QuickContact#showQuickContact} even if a contact is from the 6437 * corp profile. 6438 * </p> 6439 * 6440 * <pre> 6441 * Uri lookupUri = Uri.withAppendedPath(Email.ENTERPRISE_CONTENT_LOOKUP_URI, 6442 * Uri.encode(email)); 6443 * </pre> 6444 */ 6445 public static final Uri ENTERPRISE_CONTENT_LOOKUP_URI = 6446 Uri.withAppendedPath(CONTENT_URI, "lookup_enterprise"); 6447 6448 /** 6449 * <p>The content:// style URL for email lookup using a filter. The filter returns 6450 * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied 6451 * to display names as well as email addresses. The filter argument should be passed 6452 * as an additional path segment after this URI. 6453 * </p> 6454 * 6455 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 6456 * this field doesn't sort results based on contacts frequency. For more information, 6457 * see the 6458 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 6459 * page.</p> 6460 * 6461 * <p>The query in the following example will return "Robert Parr (bob@incredibles.com)" 6462 * as well as "Bob Parr (incredible@android.com)". 6463 * <pre> 6464 * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode("bob")); 6465 * Cursor c = getContentResolver().query(uri, 6466 * new String[]{Email.DISPLAY_NAME, Email.DATA}, 6467 * null, null, null); 6468 * </pre> 6469 * </p> 6470 */ 6471 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, 6472 "filter"); 6473 6474 /** 6475 * <p>It supports the similar semantics as {@link #CONTENT_FILTER_URI} and returns the 6476 * same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in 6477 * parameters, otherwise it will throw IllegalArgumentException. 6478 * 6479 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 6480 * this field doesn't sort results based on contacts frequency. For more information, 6481 * see the 6482 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 6483 * page. 6484 */ 6485 public static final Uri ENTERPRISE_CONTENT_FILTER_URI = Uri.withAppendedPath( 6486 CONTENT_URI, "filter_enterprise"); 6487 6488 /** 6489 * The email address. 6490 * <P>Type: TEXT</P> 6491 */ 6492 public static final String ADDRESS = DATA1; 6493 6494 public static final int TYPE_HOME = 1; 6495 public static final int TYPE_WORK = 2; 6496 public static final int TYPE_OTHER = 3; 6497 public static final int TYPE_MOBILE = 4; 6498 6499 /** 6500 * The display name for the email address 6501 * <P>Type: TEXT</P> 6502 */ 6503 public static final String DISPLAY_NAME = DATA4; 6504 6505 /** 6506 * Return the string resource that best describes the given 6507 * {@link #TYPE}. Will always return a valid resource. 6508 */ getTypeLabelResource(int type)6509 public static final int getTypeLabelResource(int type) { 6510 switch (type) { 6511 case TYPE_HOME: return com.android.internal.R.string.emailTypeHome; 6512 case TYPE_WORK: return com.android.internal.R.string.emailTypeWork; 6513 case TYPE_OTHER: return com.android.internal.R.string.emailTypeOther; 6514 case TYPE_MOBILE: return com.android.internal.R.string.emailTypeMobile; 6515 default: return com.android.internal.R.string.emailTypeCustom; 6516 } 6517 } 6518 6519 /** 6520 * Return a {@link CharSequence} that best describes the given type, 6521 * possibly substituting the given {@link #LABEL} value 6522 * for {@link #TYPE_CUSTOM}. 6523 */ getTypeLabel(Resources res, int type, CharSequence label)6524 public static final CharSequence getTypeLabel(Resources res, int type, 6525 CharSequence label) { 6526 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 6527 return label; 6528 } else { 6529 final int labelRes = getTypeLabelResource(type); 6530 return res.getText(labelRes); 6531 } 6532 } 6533 } 6534 6535 /** 6536 * <p> 6537 * A data kind representing a postal addresses. 6538 * </p> 6539 * <p> 6540 * You can use all columns defined for {@link ContactsContract.Data} as 6541 * well as the following aliases. 6542 * </p> 6543 * <h2>Column aliases</h2> 6544 * <table class="jd-sumtable"> 6545 * <tr> 6546 * <th>Type</th> 6547 * <th>Alias</th><th colspan='2'>Data column</th> 6548 * </tr> 6549 * <tr> 6550 * <td>String</td> 6551 * <td>{@link #FORMATTED_ADDRESS}</td> 6552 * <td>{@link #DATA1}</td> 6553 * <td></td> 6554 * </tr> 6555 * <tr> 6556 * <td>int</td> 6557 * <td>{@link #TYPE}</td> 6558 * <td>{@link #DATA2}</td> 6559 * <td>Allowed values are: 6560 * <p> 6561 * <ul> 6562 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 6563 * <li>{@link #TYPE_HOME}</li> 6564 * <li>{@link #TYPE_WORK}</li> 6565 * <li>{@link #TYPE_OTHER}</li> 6566 * </ul> 6567 * </p> 6568 * </td> 6569 * </tr> 6570 * <tr> 6571 * <td>String</td> 6572 * <td>{@link #LABEL}</td> 6573 * <td>{@link #DATA3}</td> 6574 * <td></td> 6575 * </tr> 6576 * <tr> 6577 * <td>String</td> 6578 * <td>{@link #STREET}</td> 6579 * <td>{@link #DATA4}</td> 6580 * <td></td> 6581 * </tr> 6582 * <tr> 6583 * <td>String</td> 6584 * <td>{@link #POBOX}</td> 6585 * <td>{@link #DATA5}</td> 6586 * <td>Post Office Box number</td> 6587 * </tr> 6588 * <tr> 6589 * <td>String</td> 6590 * <td>{@link #NEIGHBORHOOD}</td> 6591 * <td>{@link #DATA6}</td> 6592 * <td></td> 6593 * </tr> 6594 * <tr> 6595 * <td>String</td> 6596 * <td>{@link #CITY}</td> 6597 * <td>{@link #DATA7}</td> 6598 * <td></td> 6599 * </tr> 6600 * <tr> 6601 * <td>String</td> 6602 * <td>{@link #REGION}</td> 6603 * <td>{@link #DATA8}</td> 6604 * <td></td> 6605 * </tr> 6606 * <tr> 6607 * <td>String</td> 6608 * <td>{@link #POSTCODE}</td> 6609 * <td>{@link #DATA9}</td> 6610 * <td></td> 6611 * </tr> 6612 * <tr> 6613 * <td>String</td> 6614 * <td>{@link #COUNTRY}</td> 6615 * <td>{@link #DATA10}</td> 6616 * <td></td> 6617 * </tr> 6618 * </table> 6619 */ 6620 public static final class StructuredPostal implements DataColumnsWithJoins, CommonColumns, 6621 ContactCounts { 6622 /** 6623 * This utility class cannot be instantiated 6624 */ StructuredPostal()6625 private StructuredPostal() { 6626 } 6627 6628 /** MIME type used when storing this in data table. */ 6629 public static final String CONTENT_ITEM_TYPE = 6630 "vnd.android.cursor.item/postal-address_v2"; 6631 6632 /** 6633 * The MIME type of {@link #CONTENT_URI} providing a directory of 6634 * postal addresses. 6635 */ 6636 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2"; 6637 6638 /** 6639 * The content:// style URI for all data records of the 6640 * {@link StructuredPostal#CONTENT_ITEM_TYPE} MIME type. 6641 */ 6642 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 6643 "postals"); 6644 6645 public static final int TYPE_HOME = 1; 6646 public static final int TYPE_WORK = 2; 6647 public static final int TYPE_OTHER = 3; 6648 6649 /** 6650 * The full, unstructured postal address. <i>This field must be 6651 * consistent with any structured data.</i> 6652 * <p> 6653 * Type: TEXT 6654 */ 6655 public static final String FORMATTED_ADDRESS = DATA; 6656 6657 /** 6658 * Can be street, avenue, road, etc. This element also includes the 6659 * house number and room/apartment/flat/floor number. 6660 * <p> 6661 * Type: TEXT 6662 */ 6663 public static final String STREET = DATA4; 6664 6665 /** 6666 * Covers actual P.O. boxes, drawers, locked bags, etc. This is 6667 * usually but not always mutually exclusive with street. 6668 * <p> 6669 * Type: TEXT 6670 */ 6671 public static final String POBOX = DATA5; 6672 6673 /** 6674 * This is used to disambiguate a street address when a city 6675 * contains more than one street with the same name, or to specify a 6676 * small place whose mail is routed through a larger postal town. In 6677 * China it could be a county or a minor city. 6678 * <p> 6679 * Type: TEXT 6680 */ 6681 public static final String NEIGHBORHOOD = DATA6; 6682 6683 /** 6684 * Can be city, village, town, borough, etc. This is the postal town 6685 * and not necessarily the place of residence or place of business. 6686 * <p> 6687 * Type: TEXT 6688 */ 6689 public static final String CITY = DATA7; 6690 6691 /** 6692 * A state, province, county (in Ireland), Land (in Germany), 6693 * departement (in France), etc. 6694 * <p> 6695 * Type: TEXT 6696 */ 6697 public static final String REGION = DATA8; 6698 6699 /** 6700 * Postal code. Usually country-wide, but sometimes specific to the 6701 * city (e.g. "2" in "Dublin 2, Ireland" addresses). 6702 * <p> 6703 * Type: TEXT 6704 */ 6705 public static final String POSTCODE = DATA9; 6706 6707 /** 6708 * The name or code of the country. 6709 * <p> 6710 * Type: TEXT 6711 */ 6712 public static final String COUNTRY = DATA10; 6713 6714 /** 6715 * Return the string resource that best describes the given 6716 * {@link #TYPE}. Will always return a valid resource. 6717 */ getTypeLabelResource(int type)6718 public static final int getTypeLabelResource(int type) { 6719 switch (type) { 6720 case TYPE_HOME: return com.android.internal.R.string.postalTypeHome; 6721 case TYPE_WORK: return com.android.internal.R.string.postalTypeWork; 6722 case TYPE_OTHER: return com.android.internal.R.string.postalTypeOther; 6723 default: return com.android.internal.R.string.postalTypeCustom; 6724 } 6725 } 6726 6727 /** 6728 * Return a {@link CharSequence} that best describes the given type, 6729 * possibly substituting the given {@link #LABEL} value 6730 * for {@link #TYPE_CUSTOM}. 6731 */ getTypeLabel(Resources res, int type, CharSequence label)6732 public static final CharSequence getTypeLabel(Resources res, int type, 6733 CharSequence label) { 6734 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 6735 return label; 6736 } else { 6737 final int labelRes = getTypeLabelResource(type); 6738 return res.getText(labelRes); 6739 } 6740 } 6741 } 6742 6743 /** 6744 * <p> 6745 * A data kind representing an IM address 6746 * </p> 6747 * <p> 6748 * You can use all columns defined for {@link ContactsContract.Data} as 6749 * well as the following aliases. 6750 * </p> 6751 * <h2>Column aliases</h2> 6752 * <table class="jd-sumtable"> 6753 * <tr> 6754 * <th>Type</th> 6755 * <th>Alias</th><th colspan='2'>Data column</th> 6756 * </tr> 6757 * <tr> 6758 * <td>String</td> 6759 * <td>{@link #DATA}</td> 6760 * <td>{@link #DATA1}</td> 6761 * <td></td> 6762 * </tr> 6763 * <tr> 6764 * <td>int</td> 6765 * <td>{@link #TYPE}</td> 6766 * <td>{@link #DATA2}</td> 6767 * <td>Allowed values are: 6768 * <p> 6769 * <ul> 6770 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 6771 * <li>{@link #TYPE_HOME}</li> 6772 * <li>{@link #TYPE_WORK}</li> 6773 * <li>{@link #TYPE_OTHER}</li> 6774 * </ul> 6775 * </p> 6776 * </td> 6777 * </tr> 6778 * <tr> 6779 * <td>String</td> 6780 * <td>{@link #LABEL}</td> 6781 * <td>{@link #DATA3}</td> 6782 * <td></td> 6783 * </tr> 6784 * <tr> 6785 * <td>String</td> 6786 * <td>{@link #PROTOCOL}</td> 6787 * <td>{@link #DATA5}</td> 6788 * <td> 6789 * <p> 6790 * Allowed value: {@link #PROTOCOL_CUSTOM}. Also provide the actual protocol name 6791 * as {@link #CUSTOM_PROTOCOL}. 6792 * </p> 6793 * </td> 6794 * </tr> 6795 * <tr> 6796 * <td>String</td> 6797 * <td>{@link #CUSTOM_PROTOCOL}</td> 6798 * <td>{@link #DATA6}</td> 6799 * <td></td> 6800 * </tr> 6801 * </table> 6802 */ 6803 public static final class Im implements DataColumnsWithJoins, CommonColumns, ContactCounts { 6804 /** 6805 * This utility class cannot be instantiated 6806 */ Im()6807 private Im() {} 6808 6809 /** MIME type used when storing this in data table. */ 6810 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im"; 6811 6812 public static final int TYPE_HOME = 1; 6813 public static final int TYPE_WORK = 2; 6814 public static final int TYPE_OTHER = 3; 6815 6816 /** 6817 * This column should always be set to {@link #PROTOCOL_CUSTOM} and 6818 * the {@link #CUSTOM_PROTOCOL} should contain the name of the custom protocol. 6819 * The other predefined protocols are deprecated and should not be used. 6820 */ 6821 public static final String PROTOCOL = DATA5; 6822 6823 public static final String CUSTOM_PROTOCOL = DATA6; 6824 6825 /* 6826 * The predefined IM protocol types. 6827 */ 6828 public static final int PROTOCOL_CUSTOM = -1; 6829 /** 6830 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6831 */ 6832 @Deprecated 6833 public static final int PROTOCOL_AIM = 0; 6834 /** 6835 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6836 */ 6837 @Deprecated 6838 public static final int PROTOCOL_MSN = 1; 6839 /** 6840 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6841 */ 6842 @Deprecated 6843 public static final int PROTOCOL_YAHOO = 2; 6844 /** 6845 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6846 */ 6847 @Deprecated 6848 public static final int PROTOCOL_SKYPE = 3; 6849 /** 6850 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6851 */ 6852 @Deprecated 6853 public static final int PROTOCOL_QQ = 4; 6854 /** 6855 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6856 */ 6857 @Deprecated 6858 public static final int PROTOCOL_GOOGLE_TALK = 5; 6859 /** 6860 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6861 */ 6862 @Deprecated 6863 public static final int PROTOCOL_ICQ = 6; 6864 /** 6865 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6866 */ 6867 @Deprecated 6868 public static final int PROTOCOL_JABBER = 7; 6869 /** 6870 * @deprecated Use {@link #PROTOCOL_CUSTOM} with {@link #CUSTOM_PROTOCOL}. 6871 */ 6872 @Deprecated 6873 public static final int PROTOCOL_NETMEETING = 8; 6874 6875 /** 6876 * Return the string resource that best describes the given 6877 * {@link #TYPE}. Will always return a valid resource. 6878 */ getTypeLabelResource(int type)6879 public static final int getTypeLabelResource(int type) { 6880 switch (type) { 6881 case TYPE_HOME: return com.android.internal.R.string.imTypeHome; 6882 case TYPE_WORK: return com.android.internal.R.string.imTypeWork; 6883 case TYPE_OTHER: return com.android.internal.R.string.imTypeOther; 6884 default: return com.android.internal.R.string.imTypeCustom; 6885 } 6886 } 6887 6888 /** 6889 * Return a {@link CharSequence} that best describes the given type, 6890 * possibly substituting the given {@link #LABEL} value 6891 * for {@link #TYPE_CUSTOM}. 6892 */ getTypeLabel(Resources res, int type, CharSequence label)6893 public static final CharSequence getTypeLabel(Resources res, int type, 6894 CharSequence label) { 6895 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 6896 return label; 6897 } else { 6898 final int labelRes = getTypeLabelResource(type); 6899 return res.getText(labelRes); 6900 } 6901 } 6902 6903 /** 6904 * Return the string resource that best describes the given 6905 * {@link #PROTOCOL}. Will always return a valid resource. 6906 */ getProtocolLabelResource(int type)6907 public static final int getProtocolLabelResource(int type) { 6908 switch (type) { 6909 case PROTOCOL_AIM: return com.android.internal.R.string.imProtocolAim; 6910 case PROTOCOL_MSN: return com.android.internal.R.string.imProtocolMsn; 6911 case PROTOCOL_YAHOO: return com.android.internal.R.string.imProtocolYahoo; 6912 case PROTOCOL_SKYPE: return com.android.internal.R.string.imProtocolSkype; 6913 case PROTOCOL_QQ: return com.android.internal.R.string.imProtocolQq; 6914 case PROTOCOL_GOOGLE_TALK: return com.android.internal.R.string.imProtocolGoogleTalk; 6915 case PROTOCOL_ICQ: return com.android.internal.R.string.imProtocolIcq; 6916 case PROTOCOL_JABBER: return com.android.internal.R.string.imProtocolJabber; 6917 case PROTOCOL_NETMEETING: return com.android.internal.R.string.imProtocolNetMeeting; 6918 default: return com.android.internal.R.string.imProtocolCustom; 6919 } 6920 } 6921 6922 /** 6923 * Return a {@link CharSequence} that best describes the given 6924 * protocol, possibly substituting the given 6925 * {@link #CUSTOM_PROTOCOL} value for {@link #PROTOCOL_CUSTOM}. 6926 */ getProtocolLabel(Resources res, int type, CharSequence label)6927 public static final CharSequence getProtocolLabel(Resources res, int type, 6928 CharSequence label) { 6929 if (type == PROTOCOL_CUSTOM && !TextUtils.isEmpty(label)) { 6930 return label; 6931 } else { 6932 final int labelRes = getProtocolLabelResource(type); 6933 return res.getText(labelRes); 6934 } 6935 } 6936 } 6937 6938 /** 6939 * <p> 6940 * A data kind representing an organization. 6941 * </p> 6942 * <p> 6943 * You can use all columns defined for {@link ContactsContract.Data} as 6944 * well as the following aliases. 6945 * </p> 6946 * <h2>Column aliases</h2> 6947 * <table class="jd-sumtable"> 6948 * <tr> 6949 * <th>Type</th> 6950 * <th>Alias</th><th colspan='2'>Data column</th> 6951 * </tr> 6952 * <tr> 6953 * <td>String</td> 6954 * <td>{@link #COMPANY}</td> 6955 * <td>{@link #DATA1}</td> 6956 * <td></td> 6957 * </tr> 6958 * <tr> 6959 * <td>int</td> 6960 * <td>{@link #TYPE}</td> 6961 * <td>{@link #DATA2}</td> 6962 * <td>Allowed values are: 6963 * <p> 6964 * <ul> 6965 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 6966 * <li>{@link #TYPE_WORK}</li> 6967 * <li>{@link #TYPE_OTHER}</li> 6968 * </ul> 6969 * </p> 6970 * </td> 6971 * </tr> 6972 * <tr> 6973 * <td>String</td> 6974 * <td>{@link #LABEL}</td> 6975 * <td>{@link #DATA3}</td> 6976 * <td></td> 6977 * </tr> 6978 * <tr> 6979 * <td>String</td> 6980 * <td>{@link #TITLE}</td> 6981 * <td>{@link #DATA4}</td> 6982 * <td></td> 6983 * </tr> 6984 * <tr> 6985 * <td>String</td> 6986 * <td>{@link #DEPARTMENT}</td> 6987 * <td>{@link #DATA5}</td> 6988 * <td></td> 6989 * </tr> 6990 * <tr> 6991 * <td>String</td> 6992 * <td>{@link #JOB_DESCRIPTION}</td> 6993 * <td>{@link #DATA6}</td> 6994 * <td></td> 6995 * </tr> 6996 * <tr> 6997 * <td>String</td> 6998 * <td>{@link #SYMBOL}</td> 6999 * <td>{@link #DATA7}</td> 7000 * <td></td> 7001 * </tr> 7002 * <tr> 7003 * <td>String</td> 7004 * <td>{@link #PHONETIC_NAME}</td> 7005 * <td>{@link #DATA8}</td> 7006 * <td></td> 7007 * </tr> 7008 * <tr> 7009 * <td>String</td> 7010 * <td>{@link #OFFICE_LOCATION}</td> 7011 * <td>{@link #DATA9}</td> 7012 * <td></td> 7013 * </tr> 7014 * <tr> 7015 * <td>String</td> 7016 * <td>PHONETIC_NAME_STYLE</td> 7017 * <td>{@link #DATA10}</td> 7018 * <td></td> 7019 * </tr> 7020 * </table> 7021 */ 7022 public static final class Organization implements DataColumnsWithJoins, CommonColumns, 7023 ContactCounts { 7024 /** 7025 * This utility class cannot be instantiated 7026 */ Organization()7027 private Organization() {} 7028 7029 /** MIME type used when storing this in data table. */ 7030 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization"; 7031 7032 public static final int TYPE_WORK = 1; 7033 public static final int TYPE_OTHER = 2; 7034 7035 /** 7036 * The company as the user entered it. 7037 * <P>Type: TEXT</P> 7038 */ 7039 public static final String COMPANY = DATA; 7040 7041 /** 7042 * The position title at this company as the user entered it. 7043 * <P>Type: TEXT</P> 7044 */ 7045 public static final String TITLE = DATA4; 7046 7047 /** 7048 * The department at this company as the user entered it. 7049 * <P>Type: TEXT</P> 7050 */ 7051 public static final String DEPARTMENT = DATA5; 7052 7053 /** 7054 * The job description at this company as the user entered it. 7055 * <P>Type: TEXT</P> 7056 */ 7057 public static final String JOB_DESCRIPTION = DATA6; 7058 7059 /** 7060 * The symbol of this company as the user entered it. 7061 * <P>Type: TEXT</P> 7062 */ 7063 public static final String SYMBOL = DATA7; 7064 7065 /** 7066 * The phonetic name of this company as the user entered it. 7067 * <P>Type: TEXT</P> 7068 */ 7069 public static final String PHONETIC_NAME = DATA8; 7070 7071 /** 7072 * The office location of this organization. 7073 * <P>Type: TEXT</P> 7074 */ 7075 public static final String OFFICE_LOCATION = DATA9; 7076 7077 /** 7078 * The alphabet used for capturing the phonetic name. 7079 * See {@link ContactsContract.PhoneticNameStyle}. 7080 */ 7081 public static final String PHONETIC_NAME_STYLE = DATA10; 7082 7083 /** 7084 * Return the string resource that best describes the given 7085 * {@link #TYPE}. Will always return a valid resource. 7086 */ getTypeLabelResource(int type)7087 public static final int getTypeLabelResource(int type) { 7088 switch (type) { 7089 case TYPE_WORK: return com.android.internal.R.string.orgTypeWork; 7090 case TYPE_OTHER: return com.android.internal.R.string.orgTypeOther; 7091 default: return com.android.internal.R.string.orgTypeCustom; 7092 } 7093 } 7094 7095 /** 7096 * Return a {@link CharSequence} that best describes the given type, 7097 * possibly substituting the given {@link #LABEL} value 7098 * for {@link #TYPE_CUSTOM}. 7099 */ getTypeLabel(Resources res, int type, CharSequence label)7100 public static final CharSequence getTypeLabel(Resources res, int type, 7101 CharSequence label) { 7102 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 7103 return label; 7104 } else { 7105 final int labelRes = getTypeLabelResource(type); 7106 return res.getText(labelRes); 7107 } 7108 } 7109 } 7110 7111 /** 7112 * <p> 7113 * A data kind representing a relation. 7114 * </p> 7115 * <p> 7116 * You can use all columns defined for {@link ContactsContract.Data} as 7117 * well as the following aliases. 7118 * </p> 7119 * <h2>Column aliases</h2> 7120 * <table class="jd-sumtable"> 7121 * <tr> 7122 * <th>Type</th> 7123 * <th>Alias</th><th colspan='2'>Data column</th> 7124 * </tr> 7125 * <tr> 7126 * <td>String</td> 7127 * <td>{@link #NAME}</td> 7128 * <td>{@link #DATA1}</td> 7129 * <td></td> 7130 * </tr> 7131 * <tr> 7132 * <td>int</td> 7133 * <td>{@link #TYPE}</td> 7134 * <td>{@link #DATA2}</td> 7135 * <td>Allowed values are: 7136 * <p> 7137 * <ul> 7138 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 7139 * <li>{@link #TYPE_ASSISTANT}</li> 7140 * <li>{@link #TYPE_BROTHER}</li> 7141 * <li>{@link #TYPE_CHILD}</li> 7142 * <li>{@link #TYPE_DOMESTIC_PARTNER}</li> 7143 * <li>{@link #TYPE_FATHER}</li> 7144 * <li>{@link #TYPE_FRIEND}</li> 7145 * <li>{@link #TYPE_MANAGER}</li> 7146 * <li>{@link #TYPE_MOTHER}</li> 7147 * <li>{@link #TYPE_PARENT}</li> 7148 * <li>{@link #TYPE_PARTNER}</li> 7149 * <li>{@link #TYPE_REFERRED_BY}</li> 7150 * <li>{@link #TYPE_RELATIVE}</li> 7151 * <li>{@link #TYPE_SISTER}</li> 7152 * <li>{@link #TYPE_SPOUSE}</li> 7153 * </ul> 7154 * </p> 7155 * </td> 7156 * </tr> 7157 * <tr> 7158 * <td>String</td> 7159 * <td>{@link #LABEL}</td> 7160 * <td>{@link #DATA3}</td> 7161 * <td></td> 7162 * </tr> 7163 * </table> 7164 */ 7165 public static final class Relation implements DataColumnsWithJoins, CommonColumns, 7166 ContactCounts { 7167 /** 7168 * This utility class cannot be instantiated 7169 */ Relation()7170 private Relation() {} 7171 7172 /** MIME type used when storing this in data table. */ 7173 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation"; 7174 7175 public static final int TYPE_ASSISTANT = 1; 7176 public static final int TYPE_BROTHER = 2; 7177 public static final int TYPE_CHILD = 3; 7178 public static final int TYPE_DOMESTIC_PARTNER = 4; 7179 public static final int TYPE_FATHER = 5; 7180 public static final int TYPE_FRIEND = 6; 7181 public static final int TYPE_MANAGER = 7; 7182 public static final int TYPE_MOTHER = 8; 7183 public static final int TYPE_PARENT = 9; 7184 public static final int TYPE_PARTNER = 10; 7185 public static final int TYPE_REFERRED_BY = 11; 7186 public static final int TYPE_RELATIVE = 12; 7187 public static final int TYPE_SISTER = 13; 7188 public static final int TYPE_SPOUSE = 14; 7189 7190 /** 7191 * The name of the relative as the user entered it. 7192 * <P>Type: TEXT</P> 7193 */ 7194 public static final String NAME = DATA; 7195 7196 /** 7197 * Return the string resource that best describes the given 7198 * {@link #TYPE}. Will always return a valid resource. 7199 */ getTypeLabelResource(int type)7200 public static final int getTypeLabelResource(int type) { 7201 switch (type) { 7202 case TYPE_ASSISTANT: return com.android.internal.R.string.relationTypeAssistant; 7203 case TYPE_BROTHER: return com.android.internal.R.string.relationTypeBrother; 7204 case TYPE_CHILD: return com.android.internal.R.string.relationTypeChild; 7205 case TYPE_DOMESTIC_PARTNER: 7206 return com.android.internal.R.string.relationTypeDomesticPartner; 7207 case TYPE_FATHER: return com.android.internal.R.string.relationTypeFather; 7208 case TYPE_FRIEND: return com.android.internal.R.string.relationTypeFriend; 7209 case TYPE_MANAGER: return com.android.internal.R.string.relationTypeManager; 7210 case TYPE_MOTHER: return com.android.internal.R.string.relationTypeMother; 7211 case TYPE_PARENT: return com.android.internal.R.string.relationTypeParent; 7212 case TYPE_PARTNER: return com.android.internal.R.string.relationTypePartner; 7213 case TYPE_REFERRED_BY: 7214 return com.android.internal.R.string.relationTypeReferredBy; 7215 case TYPE_RELATIVE: return com.android.internal.R.string.relationTypeRelative; 7216 case TYPE_SISTER: return com.android.internal.R.string.relationTypeSister; 7217 case TYPE_SPOUSE: return com.android.internal.R.string.relationTypeSpouse; 7218 default: return com.android.internal.R.string.orgTypeCustom; 7219 } 7220 } 7221 7222 /** 7223 * Return a {@link CharSequence} that best describes the given type, 7224 * possibly substituting the given {@link #LABEL} value 7225 * for {@link #TYPE_CUSTOM}. 7226 */ getTypeLabel(Resources res, int type, CharSequence label)7227 public static final CharSequence getTypeLabel(Resources res, int type, 7228 CharSequence label) { 7229 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 7230 return label; 7231 } else { 7232 final int labelRes = getTypeLabelResource(type); 7233 return res.getText(labelRes); 7234 } 7235 } 7236 } 7237 7238 /** 7239 * <p> 7240 * A data kind representing an event. 7241 * </p> 7242 * <p> 7243 * You can use all columns defined for {@link ContactsContract.Data} as 7244 * well as the following aliases. 7245 * </p> 7246 * <h2>Column aliases</h2> 7247 * <table class="jd-sumtable"> 7248 * <tr> 7249 * <th>Type</th> 7250 * <th>Alias</th><th colspan='2'>Data column</th> 7251 * </tr> 7252 * <tr> 7253 * <td>String</td> 7254 * <td>{@link #START_DATE}</td> 7255 * <td>{@link #DATA1}</td> 7256 * <td></td> 7257 * </tr> 7258 * <tr> 7259 * <td>int</td> 7260 * <td>{@link #TYPE}</td> 7261 * <td>{@link #DATA2}</td> 7262 * <td>Allowed values are: 7263 * <p> 7264 * <ul> 7265 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 7266 * <li>{@link #TYPE_ANNIVERSARY}</li> 7267 * <li>{@link #TYPE_OTHER}</li> 7268 * <li>{@link #TYPE_BIRTHDAY}</li> 7269 * </ul> 7270 * </p> 7271 * </td> 7272 * </tr> 7273 * <tr> 7274 * <td>String</td> 7275 * <td>{@link #LABEL}</td> 7276 * <td>{@link #DATA3}</td> 7277 * <td></td> 7278 * </tr> 7279 * </table> 7280 */ 7281 public static final class Event implements DataColumnsWithJoins, CommonColumns, 7282 ContactCounts { 7283 /** 7284 * This utility class cannot be instantiated 7285 */ Event()7286 private Event() {} 7287 7288 /** MIME type used when storing this in data table. */ 7289 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event"; 7290 7291 public static final int TYPE_ANNIVERSARY = 1; 7292 public static final int TYPE_OTHER = 2; 7293 public static final int TYPE_BIRTHDAY = 3; 7294 7295 /** 7296 * The event start date as the user entered it. 7297 * <P>Type: TEXT</P> 7298 */ 7299 public static final String START_DATE = DATA; 7300 7301 /** 7302 * Return the string resource that best describes the given 7303 * {@link #TYPE}. Will always return a valid resource. 7304 */ getTypeResource(Integer type)7305 public static int getTypeResource(Integer type) { 7306 if (type == null) { 7307 return com.android.internal.R.string.eventTypeOther; 7308 } 7309 switch (type) { 7310 case TYPE_ANNIVERSARY: 7311 return com.android.internal.R.string.eventTypeAnniversary; 7312 case TYPE_BIRTHDAY: return com.android.internal.R.string.eventTypeBirthday; 7313 case TYPE_OTHER: return com.android.internal.R.string.eventTypeOther; 7314 default: return com.android.internal.R.string.eventTypeCustom; 7315 } 7316 } 7317 7318 /** 7319 * Return a {@link CharSequence} that best describes the given type, 7320 * possibly substituting the given {@link #LABEL} value 7321 * for {@link #TYPE_CUSTOM}. 7322 */ getTypeLabel(Resources res, int type, CharSequence label)7323 public static final CharSequence getTypeLabel(Resources res, int type, 7324 CharSequence label) { 7325 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 7326 return label; 7327 } else { 7328 final int labelRes = getTypeResource(type); 7329 return res.getText(labelRes); 7330 } 7331 } 7332 } 7333 7334 /** 7335 * <p> 7336 * A data kind representing a photo for the contact. 7337 * </p> 7338 * <p> 7339 * Some sync adapters will choose to download photos in a separate 7340 * pass. A common pattern is to use columns {@link ContactsContract.Data#SYNC1} 7341 * through {@link ContactsContract.Data#SYNC4} to store temporary 7342 * data, e.g. the image URL or ID, state of download, server-side version 7343 * of the image. It is allowed for the {@link #PHOTO} to be null. 7344 * </p> 7345 * <p> 7346 * You can use all columns defined for {@link ContactsContract.Data} as 7347 * well as the following aliases. 7348 * </p> 7349 * <h2>Column aliases</h2> 7350 * <table class="jd-sumtable"> 7351 * <tr> 7352 * <th>Type</th> 7353 * <th>Alias</th><th colspan='2'>Data column</th> 7354 * </tr> 7355 * <tr> 7356 * <td>NUMBER</td> 7357 * <td>{@link #PHOTO_FILE_ID}</td> 7358 * <td>{@link #DATA14}</td> 7359 * <td>ID of the hi-res photo file.</td> 7360 * </tr> 7361 * <tr> 7362 * <td>BLOB</td> 7363 * <td>{@link #PHOTO}</td> 7364 * <td>{@link #DATA15}</td> 7365 * <td>By convention, binary data is stored in DATA15. The thumbnail of the 7366 * photo is stored in this column.</td> 7367 * </tr> 7368 * </table> 7369 */ 7370 public static final class Photo implements DataColumnsWithJoins, ContactCounts { 7371 /** 7372 * This utility class cannot be instantiated 7373 */ Photo()7374 private Photo() {} 7375 7376 /** MIME type used when storing this in data table. */ 7377 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo"; 7378 7379 /** 7380 * Photo file ID for the display photo of the raw contact. 7381 * See {@link ContactsContract.DisplayPhoto}. 7382 * <p> 7383 * Type: NUMBER 7384 */ 7385 public static final String PHOTO_FILE_ID = DATA14; 7386 7387 /** 7388 * Thumbnail photo of the raw contact. This is the raw bytes of an image 7389 * that could be inflated using {@link android.graphics.BitmapFactory}. 7390 * <p> 7391 * Type: BLOB 7392 */ 7393 public static final String PHOTO = DATA15; 7394 } 7395 7396 /** 7397 * <p> 7398 * Notes about the contact. 7399 * </p> 7400 * <p> 7401 * You can use all columns defined for {@link ContactsContract.Data} as 7402 * well as the following aliases. 7403 * </p> 7404 * <h2>Column aliases</h2> 7405 * <table class="jd-sumtable"> 7406 * <tr> 7407 * <th>Type</th> 7408 * <th>Alias</th><th colspan='2'>Data column</th> 7409 * </tr> 7410 * <tr> 7411 * <td>String</td> 7412 * <td>{@link #NOTE}</td> 7413 * <td>{@link #DATA1}</td> 7414 * <td></td> 7415 * </tr> 7416 * </table> 7417 */ 7418 public static final class Note implements DataColumnsWithJoins, ContactCounts { 7419 /** 7420 * This utility class cannot be instantiated 7421 */ Note()7422 private Note() {} 7423 7424 /** MIME type used when storing this in data table. */ 7425 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note"; 7426 7427 /** 7428 * The note text. 7429 * <P>Type: TEXT</P> 7430 */ 7431 public static final String NOTE = DATA1; 7432 } 7433 7434 /** 7435 * <p> 7436 * Group Membership. 7437 * </p> 7438 * <p> 7439 * You can use all columns defined for {@link ContactsContract.Data} as 7440 * well as the following aliases. 7441 * </p> 7442 * <h2>Column aliases</h2> 7443 * <table class="jd-sumtable"> 7444 * <tr> 7445 * <th>Type</th> 7446 * <th>Alias</th><th colspan='2'>Data column</th> 7447 * </tr> 7448 * <tr> 7449 * <td>long</td> 7450 * <td>{@link #GROUP_ROW_ID}</td> 7451 * <td>{@link #DATA1}</td> 7452 * <td></td> 7453 * </tr> 7454 * <tr> 7455 * <td>String</td> 7456 * <td>{@link #GROUP_SOURCE_ID}</td> 7457 * <td>none</td> 7458 * <td> 7459 * <p> 7460 * The sourceid of the group that this group membership refers to. 7461 * Exactly one of this or {@link #GROUP_ROW_ID} must be set when 7462 * inserting a row. 7463 * </p> 7464 * <p> 7465 * If this field is specified, the provider will first try to 7466 * look up a group with this {@link Groups Groups.SOURCE_ID}. If such a group 7467 * is found, it will use the corresponding row id. If the group is not 7468 * found, it will create one. 7469 * </td> 7470 * </tr> 7471 * </table> 7472 */ 7473 public static final class GroupMembership implements DataColumnsWithJoins, ContactCounts { 7474 /** 7475 * This utility class cannot be instantiated 7476 */ GroupMembership()7477 private GroupMembership() {} 7478 7479 /** MIME type used when storing this in data table. */ 7480 public static final String CONTENT_ITEM_TYPE = 7481 "vnd.android.cursor.item/group_membership"; 7482 7483 /** 7484 * The row id of the group that this group membership refers to. Exactly one of 7485 * this or {@link #GROUP_SOURCE_ID} must be set when inserting a row. 7486 * <P>Type: INTEGER</P> 7487 */ 7488 public static final String GROUP_ROW_ID = DATA1; 7489 7490 /** 7491 * The sourceid of the group that this group membership refers to. Exactly one of 7492 * this or {@link #GROUP_ROW_ID} must be set when inserting a row. 7493 * <P>Type: TEXT</P> 7494 */ 7495 public static final String GROUP_SOURCE_ID = "group_sourceid"; 7496 } 7497 7498 /** 7499 * <p> 7500 * A data kind representing a website related to the contact. 7501 * </p> 7502 * <p> 7503 * You can use all columns defined for {@link ContactsContract.Data} as 7504 * well as the following aliases. 7505 * </p> 7506 * <h2>Column aliases</h2> 7507 * <table class="jd-sumtable"> 7508 * <tr> 7509 * <th>Type</th> 7510 * <th>Alias</th><th colspan='2'>Data column</th> 7511 * </tr> 7512 * <tr> 7513 * <td>String</td> 7514 * <td>{@link #URL}</td> 7515 * <td>{@link #DATA1}</td> 7516 * <td></td> 7517 * </tr> 7518 * <tr> 7519 * <td>int</td> 7520 * <td>{@link #TYPE}</td> 7521 * <td>{@link #DATA2}</td> 7522 * <td>Allowed values are: 7523 * <p> 7524 * <ul> 7525 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 7526 * <li>{@link #TYPE_HOMEPAGE}</li> 7527 * <li>{@link #TYPE_BLOG}</li> 7528 * <li>{@link #TYPE_PROFILE}</li> 7529 * <li>{@link #TYPE_HOME}</li> 7530 * <li>{@link #TYPE_WORK}</li> 7531 * <li>{@link #TYPE_FTP}</li> 7532 * <li>{@link #TYPE_OTHER}</li> 7533 * </ul> 7534 * </p> 7535 * </td> 7536 * </tr> 7537 * <tr> 7538 * <td>String</td> 7539 * <td>{@link #LABEL}</td> 7540 * <td>{@link #DATA3}</td> 7541 * <td></td> 7542 * </tr> 7543 * </table> 7544 */ 7545 public static final class Website implements DataColumnsWithJoins, CommonColumns, 7546 ContactCounts { 7547 /** 7548 * This utility class cannot be instantiated 7549 */ Website()7550 private Website() {} 7551 7552 /** MIME type used when storing this in data table. */ 7553 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website"; 7554 7555 public static final int TYPE_HOMEPAGE = 1; 7556 public static final int TYPE_BLOG = 2; 7557 public static final int TYPE_PROFILE = 3; 7558 public static final int TYPE_HOME = 4; 7559 public static final int TYPE_WORK = 5; 7560 public static final int TYPE_FTP = 6; 7561 public static final int TYPE_OTHER = 7; 7562 7563 /** 7564 * The website URL string. 7565 * <P>Type: TEXT</P> 7566 */ 7567 public static final String URL = DATA; 7568 } 7569 7570 /** 7571 * <p> 7572 * A data kind representing a SIP address for the contact. 7573 * </p> 7574 * <p> 7575 * You can use all columns defined for {@link ContactsContract.Data} as 7576 * well as the following aliases. 7577 * </p> 7578 * <h2>Column aliases</h2> 7579 * <table class="jd-sumtable"> 7580 * <tr> 7581 * <th>Type</th> 7582 * <th>Alias</th><th colspan='2'>Data column</th> 7583 * </tr> 7584 * <tr> 7585 * <td>String</td> 7586 * <td>{@link #SIP_ADDRESS}</td> 7587 * <td>{@link #DATA1}</td> 7588 * <td></td> 7589 * </tr> 7590 * <tr> 7591 * <td>int</td> 7592 * <td>{@link #TYPE}</td> 7593 * <td>{@link #DATA2}</td> 7594 * <td>Allowed values are: 7595 * <p> 7596 * <ul> 7597 * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li> 7598 * <li>{@link #TYPE_HOME}</li> 7599 * <li>{@link #TYPE_WORK}</li> 7600 * <li>{@link #TYPE_OTHER}</li> 7601 * </ul> 7602 * </p> 7603 * </td> 7604 * </tr> 7605 * <tr> 7606 * <td>String</td> 7607 * <td>{@link #LABEL}</td> 7608 * <td>{@link #DATA3}</td> 7609 * <td></td> 7610 * </tr> 7611 * </table> 7612 */ 7613 public static final class SipAddress implements DataColumnsWithJoins, CommonColumns, 7614 ContactCounts { 7615 /** 7616 * This utility class cannot be instantiated 7617 */ SipAddress()7618 private SipAddress() {} 7619 7620 /** MIME type used when storing this in data table. */ 7621 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address"; 7622 7623 public static final int TYPE_HOME = 1; 7624 public static final int TYPE_WORK = 2; 7625 public static final int TYPE_OTHER = 3; 7626 7627 /** 7628 * The SIP address. 7629 * <P>Type: TEXT</P> 7630 */ 7631 public static final String SIP_ADDRESS = DATA1; 7632 // ...and TYPE and LABEL come from the CommonColumns interface. 7633 7634 /** 7635 * Return the string resource that best describes the given 7636 * {@link #TYPE}. Will always return a valid resource. 7637 */ getTypeLabelResource(int type)7638 public static final int getTypeLabelResource(int type) { 7639 switch (type) { 7640 case TYPE_HOME: return com.android.internal.R.string.sipAddressTypeHome; 7641 case TYPE_WORK: return com.android.internal.R.string.sipAddressTypeWork; 7642 case TYPE_OTHER: return com.android.internal.R.string.sipAddressTypeOther; 7643 default: return com.android.internal.R.string.sipAddressTypeCustom; 7644 } 7645 } 7646 7647 /** 7648 * Return a {@link CharSequence} that best describes the given type, 7649 * possibly substituting the given {@link #LABEL} value 7650 * for {@link #TYPE_CUSTOM}. 7651 */ getTypeLabel(Resources res, int type, CharSequence label)7652 public static final CharSequence getTypeLabel(Resources res, int type, 7653 CharSequence label) { 7654 if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { 7655 return label; 7656 } else { 7657 final int labelRes = getTypeLabelResource(type); 7658 return res.getText(labelRes); 7659 } 7660 } 7661 } 7662 7663 /** 7664 * A data kind representing an Identity related to the contact. 7665 * <p> 7666 * This can be used as a signal by the aggregator to combine raw contacts into 7667 * contacts, e.g. if two contacts have Identity rows with 7668 * the same NAMESPACE and IDENTITY values the aggregator can know that they refer 7669 * to the same person. 7670 * </p> 7671 */ 7672 public static final class Identity implements DataColumnsWithJoins, ContactCounts { 7673 /** 7674 * This utility class cannot be instantiated 7675 */ Identity()7676 private Identity() {} 7677 7678 /** MIME type used when storing this in data table. */ 7679 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/identity"; 7680 7681 /** 7682 * The identity string. 7683 * <P>Type: TEXT</P> 7684 */ 7685 public static final String IDENTITY = DataColumns.DATA1; 7686 7687 /** 7688 * The namespace of the identity string, e.g. "com.google" 7689 * <P>Type: TEXT</P> 7690 */ 7691 public static final String NAMESPACE = DataColumns.DATA2; 7692 } 7693 7694 /** 7695 * <p> 7696 * Convenient functionalities for "callable" data. Note that, this is NOT a separate data 7697 * kind. 7698 * </p> 7699 * <p> 7700 * This URI allows the ContactsProvider to return a unified result for "callable" data 7701 * that users can use for calling purposes. {@link Phone} and {@link SipAddress} are the 7702 * current examples for "callable", but may be expanded to the other types. 7703 * </p> 7704 * <p> 7705 * Each returned row may have a different MIMETYPE and thus different interpretation for 7706 * each column. For example the meaning for {@link Phone}'s type is different than 7707 * {@link SipAddress}'s. 7708 * </p> 7709 */ 7710 public static final class Callable implements DataColumnsWithJoins, CommonColumns, 7711 ContactCounts { 7712 /** 7713 * Similar to {@link Phone#CONTENT_URI}, but returns callable data instead of only 7714 * phone numbers. 7715 */ 7716 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 7717 "callables"); 7718 /** 7719 * <p>Similar to {@link Phone#CONTENT_FILTER_URI}, but allows users to filter callable 7720 * data. 7721 * 7722 * <p class="caution"><b>Caution: </b>This field no longer sorts results based on 7723 * contacts frequency. For more information, see the 7724 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 7725 * page. 7726 */ 7727 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, 7728 "filter"); 7729 7730 /** 7731 * <p>Similar to {@link Phone#ENTERPRISE_CONTENT_FILTER_URI}, but allows users to filter 7732 * callable data. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in 7733 * parameters, otherwise it will throw IllegalArgumentException. 7734 * 7735 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 7736 * this field doesn't sort results based on contacts frequency. For more information, 7737 * see the 7738 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 7739 * page.</p> 7740 */ 7741 public static final Uri ENTERPRISE_CONTENT_FILTER_URI = Uri.withAppendedPath( 7742 CONTENT_URI, "filter_enterprise"); 7743 } 7744 7745 /** 7746 * A special class of data items, used to refer to types of data that can be used to attempt 7747 * to start communicating with a person ({@link Phone} and {@link Email}). Note that this 7748 * is NOT a separate data kind. 7749 * 7750 * This URI allows the ContactsProvider to return a unified result for data items that users 7751 * can use to initiate communications with another contact. {@link Phone} and {@link Email} 7752 * are the current data types in this category. 7753 */ 7754 public static final class Contactables implements DataColumnsWithJoins, CommonColumns, 7755 ContactCounts { 7756 /** 7757 * The content:// style URI for these data items, which requests a directory of data 7758 * rows matching the selection criteria. 7759 */ 7760 public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, 7761 "contactables"); 7762 7763 /** 7764 * <p>The content:// style URI for these data items, which allows for a query parameter 7765 * to be appended onto the end to filter for data items matching the query. 7766 * 7767 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 7768 * this field doesn't sort results based on contacts frequency. For more information, 7769 * see the 7770 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 7771 * page. 7772 */ 7773 public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath( 7774 Contactables.CONTENT_URI, "filter"); 7775 7776 /** 7777 * A boolean parameter for {@link Data#CONTENT_URI}. 7778 * This specifies whether or not the returned data items should be filtered to show 7779 * data items belonging to visible contacts only. 7780 */ 7781 public static final String VISIBLE_CONTACTS_ONLY = "visible_contacts_only"; 7782 } 7783 } 7784 7785 /** 7786 * @see Groups 7787 */ 7788 protected interface GroupsColumns { 7789 /** 7790 * The data set within the account that this group belongs to. This allows 7791 * multiple sync adapters for the same account type to distinguish between 7792 * each others' group data. 7793 * 7794 * This is empty by default, and is completely optional. It only needs to 7795 * be populated if multiple sync adapters are entering distinct group data 7796 * for the same account type and account name. 7797 * <P>Type: TEXT</P> 7798 */ 7799 public static final String DATA_SET = "data_set"; 7800 7801 /** 7802 * A concatenation of the account type and data set (delimited by a forward 7803 * slash) - if the data set is empty, this will be the same as the account 7804 * type. For applications that need to be aware of the data set, this can 7805 * be used instead of account type to distinguish sets of data. This is 7806 * never intended to be used for specifying accounts. 7807 * @hide 7808 */ 7809 public static final String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set"; 7810 7811 /** 7812 * The display title of this group. 7813 * <p> 7814 * Type: TEXT 7815 */ 7816 public static final String TITLE = "title"; 7817 7818 /** 7819 * The package name to use when creating {@link Resources} objects for 7820 * this group. This value is only designed for use when building user 7821 * interfaces, and should not be used to infer the owner. 7822 */ 7823 public static final String RES_PACKAGE = "res_package"; 7824 7825 /** 7826 * The display title of this group to load as a resource from 7827 * {@link #RES_PACKAGE}, which may be localized. 7828 * <P>Type: TEXT</P> 7829 */ 7830 public static final String TITLE_RES = "title_res"; 7831 7832 /** 7833 * Notes about the group. 7834 * <p> 7835 * Type: TEXT 7836 */ 7837 public static final String NOTES = "notes"; 7838 7839 /** 7840 * The ID of this group if it is a System Group, i.e. a group that has a special meaning 7841 * to the sync adapter, null otherwise. 7842 * <P>Type: TEXT</P> 7843 */ 7844 public static final String SYSTEM_ID = "system_id"; 7845 7846 /** 7847 * The total number of {@link Contacts} that have 7848 * {@link CommonDataKinds.GroupMembership} in this group. Read-only value that is only 7849 * present when querying {@link Groups#CONTENT_SUMMARY_URI}. 7850 * <p> 7851 * Type: INTEGER 7852 */ 7853 public static final String SUMMARY_COUNT = "summ_count"; 7854 7855 /** 7856 * A boolean query parameter that can be used with {@link Groups#CONTENT_SUMMARY_URI}. 7857 * It will additionally return {@link #SUMMARY_GROUP_COUNT_PER_ACCOUNT}. 7858 * 7859 * @hide 7860 */ 7861 public static final String PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT = 7862 "return_group_count_per_account"; 7863 7864 /** 7865 * The total number of groups of the account that a group belongs to. 7866 * This column is available only when the parameter 7867 * {@link #PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT} is specified in 7868 * {@link Groups#CONTENT_SUMMARY_URI}. 7869 * 7870 * For example, when the account "A" has two groups "group1" and "group2", and the account 7871 * "B" has a group "group3", the rows for "group1" and "group2" return "2" and the row for 7872 * "group3" returns "1" for this column. 7873 * 7874 * Note: This counts only non-favorites, non-auto-add, and not deleted groups. 7875 * 7876 * Type: INTEGER 7877 * @hide 7878 */ 7879 public static final String SUMMARY_GROUP_COUNT_PER_ACCOUNT = "group_count_per_account"; 7880 7881 /** 7882 * The total number of {@link Contacts} that have both 7883 * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers. 7884 * Read-only value that is only present when querying 7885 * {@link Groups#CONTENT_SUMMARY_URI}. 7886 * <p> 7887 * Type: INTEGER 7888 */ 7889 public static final String SUMMARY_WITH_PHONES = "summ_phones"; 7890 7891 /** 7892 * Flag indicating if the contacts belonging to this group should be 7893 * visible in any user interface. 7894 * <p> 7895 * Type: INTEGER (boolean) 7896 */ 7897 public static final String GROUP_VISIBLE = "group_visible"; 7898 7899 /** 7900 * The "deleted" flag: "0" by default, "1" if the row has been marked 7901 * for deletion. When {@link android.content.ContentResolver#delete} is 7902 * called on a group, it is marked for deletion. The sync adaptor 7903 * deletes the group on the server and then calls ContactResolver.delete 7904 * once more, this time setting the the 7905 * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to 7906 * finalize the data removal. 7907 * <P>Type: INTEGER</P> 7908 */ 7909 public static final String DELETED = "deleted"; 7910 7911 /** 7912 * Whether this group should be synced if the SYNC_EVERYTHING settings 7913 * is false for this group's account. 7914 * <p> 7915 * Type: INTEGER (boolean) 7916 */ 7917 public static final String SHOULD_SYNC = "should_sync"; 7918 7919 /** 7920 * Any newly created contacts will automatically be added to groups that have this 7921 * flag set to true. 7922 * <p> 7923 * Type: INTEGER (boolean) 7924 */ 7925 public static final String AUTO_ADD = "auto_add"; 7926 7927 /** 7928 * When a contacts is marked as a favorites it will be automatically added 7929 * to the groups that have this flag set, and when it is removed from favorites 7930 * it will be removed from these groups. 7931 * <p> 7932 * Type: INTEGER (boolean) 7933 */ 7934 public static final String FAVORITES = "favorites"; 7935 7936 /** 7937 * The "read-only" flag: "0" by default, "1" if the row cannot be modified or 7938 * deleted except by a sync adapter. See {@link ContactsContract#CALLER_IS_SYNCADAPTER}. 7939 * <P>Type: INTEGER</P> 7940 */ 7941 public static final String GROUP_IS_READ_ONLY = "group_is_read_only"; 7942 } 7943 7944 /** 7945 * Constants for the groups table. Only per-account groups are supported. 7946 * <h2>Columns</h2> 7947 * <table class="jd-sumtable"> 7948 * <tr> 7949 * <th colspan='4'>Groups</th> 7950 * </tr> 7951 * <tr> 7952 * <td>long</td> 7953 * <td>{@link #_ID}</td> 7954 * <td>read-only</td> 7955 * <td>Row ID. Sync adapter should try to preserve row IDs during updates. 7956 * In other words, it would be a really bad idea to delete and reinsert a 7957 * group. A sync adapter should always do an update instead.</td> 7958 * </tr> 7959 # <tr> 7960 * <td>String</td> 7961 * <td>{@link #DATA_SET}</td> 7962 * <td>read/write-once</td> 7963 * <td> 7964 * <p> 7965 * The data set within the account that this group belongs to. This allows 7966 * multiple sync adapters for the same account type to distinguish between 7967 * each others' group data. The combination of {@link #ACCOUNT_TYPE}, 7968 * {@link #ACCOUNT_NAME}, and {@link #DATA_SET} identifies a set of data 7969 * that is associated with a single sync adapter. 7970 * </p> 7971 * <p> 7972 * This is empty by default, and is completely optional. It only needs to 7973 * be populated if multiple sync adapters are entering distinct data for 7974 * the same account type and account name. 7975 * </p> 7976 * <p> 7977 * It should be set at the time the group is inserted and never changed 7978 * afterwards. 7979 * </p> 7980 * </td> 7981 * </tr> 7982 * <tr> 7983 * <td>String</td> 7984 * <td>{@link #TITLE}</td> 7985 * <td>read/write</td> 7986 * <td>The display title of this group.</td> 7987 * </tr> 7988 * <tr> 7989 * <td>String</td> 7990 * <td>{@link #NOTES}</td> 7991 * <td>read/write</td> 7992 * <td>Notes about the group.</td> 7993 * </tr> 7994 * <tr> 7995 * <td>String</td> 7996 * <td>{@link #SYSTEM_ID}</td> 7997 * <td>read/write</td> 7998 * <td>The ID of this group if it is a System Group, i.e. a group that has a 7999 * special meaning to the sync adapter, null otherwise.</td> 8000 * </tr> 8001 * <tr> 8002 * <td>int</td> 8003 * <td>{@link #SUMMARY_COUNT}</td> 8004 * <td>read-only</td> 8005 * <td>The total number of {@link Contacts} that have 8006 * {@link CommonDataKinds.GroupMembership} in this group. Read-only value 8007 * that is only present when querying {@link Groups#CONTENT_SUMMARY_URI}.</td> 8008 * </tr> 8009 * <tr> 8010 * <td>int</td> 8011 * <td>{@link #SUMMARY_WITH_PHONES}</td> 8012 * <td>read-only</td> 8013 * <td>The total number of {@link Contacts} that have both 8014 * {@link CommonDataKinds.GroupMembership} in this group, and also have 8015 * phone numbers. Read-only value that is only present when querying 8016 * {@link Groups#CONTENT_SUMMARY_URI}.</td> 8017 * </tr> 8018 * <tr> 8019 * <td>int</td> 8020 * <td>{@link #GROUP_VISIBLE}</td> 8021 * <td>read-only</td> 8022 * <td>Flag indicating if the contacts belonging to this group should be 8023 * visible in any user interface. Allowed values: 0 and 1.</td> 8024 * </tr> 8025 * <tr> 8026 * <td>int</td> 8027 * <td>{@link #DELETED}</td> 8028 * <td>read/write</td> 8029 * <td>The "deleted" flag: "0" by default, "1" if the row has been marked 8030 * for deletion. When {@link android.content.ContentResolver#delete} is 8031 * called on a group, it is marked for deletion. The sync adaptor deletes 8032 * the group on the server and then calls ContactResolver.delete once more, 8033 * this time setting the the {@link ContactsContract#CALLER_IS_SYNCADAPTER} 8034 * query parameter to finalize the data removal.</td> 8035 * </tr> 8036 * <tr> 8037 * <td>int</td> 8038 * <td>{@link #SHOULD_SYNC}</td> 8039 * <td>read/write</td> 8040 * <td>Whether this group should be synced if the SYNC_EVERYTHING settings 8041 * is false for this group's account.</td> 8042 * </tr> 8043 * </table> 8044 */ 8045 public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns { 8046 /** 8047 * This utility class cannot be instantiated 8048 */ Groups()8049 private Groups() { 8050 } 8051 8052 /** 8053 * The content:// style URI for this table 8054 */ 8055 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "groups"); 8056 8057 /** 8058 * The content:// style URI for this table joined with details data from 8059 * {@link ContactsContract.Data}. 8060 */ 8061 public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI, 8062 "groups_summary"); 8063 8064 /** 8065 * The MIME type of a directory of groups. 8066 */ 8067 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/group"; 8068 8069 /** 8070 * The MIME type of a single group. 8071 */ 8072 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group"; 8073 newEntityIterator(Cursor cursor)8074 public static EntityIterator newEntityIterator(Cursor cursor) { 8075 return new EntityIteratorImpl(cursor); 8076 } 8077 8078 private static class EntityIteratorImpl extends CursorEntityIterator { EntityIteratorImpl(Cursor cursor)8079 public EntityIteratorImpl(Cursor cursor) { 8080 super(cursor); 8081 } 8082 8083 @Override getEntityAndIncrementCursor(Cursor cursor)8084 public Entity getEntityAndIncrementCursor(Cursor cursor) throws RemoteException { 8085 // we expect the cursor is already at the row we need to read from 8086 final ContentValues values = new ContentValues(); 8087 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, _ID); 8088 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_NAME); 8089 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_TYPE); 8090 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DIRTY); 8091 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, VERSION); 8092 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SOURCE_ID); 8093 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, RES_PACKAGE); 8094 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE); 8095 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE_RES); 8096 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, GROUP_VISIBLE); 8097 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC1); 8098 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC2); 8099 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC3); 8100 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC4); 8101 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYSTEM_ID); 8102 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DELETED); 8103 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, NOTES); 8104 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SHOULD_SYNC); 8105 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, FAVORITES); 8106 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, AUTO_ADD); 8107 cursor.moveToNext(); 8108 return new Entity(values); 8109 } 8110 } 8111 } 8112 8113 /** 8114 * <p> 8115 * Constants for the contact aggregation exceptions table, which contains 8116 * aggregation rules overriding those used by automatic aggregation. This 8117 * type only supports query and update. Neither insert nor delete are 8118 * supported. 8119 * </p> 8120 * <h2>Columns</h2> 8121 * <table class="jd-sumtable"> 8122 * <tr> 8123 * <th colspan='4'>AggregationExceptions</th> 8124 * </tr> 8125 * <tr> 8126 * <td>int</td> 8127 * <td>{@link #TYPE}</td> 8128 * <td>read/write</td> 8129 * <td>The type of exception: {@link #TYPE_KEEP_TOGETHER}, 8130 * {@link #TYPE_KEEP_SEPARATE} or {@link #TYPE_AUTOMATIC}.</td> 8131 * </tr> 8132 * <tr> 8133 * <td>long</td> 8134 * <td>{@link #RAW_CONTACT_ID1}</td> 8135 * <td>read/write</td> 8136 * <td>A reference to the {@link RawContacts#_ID} of the raw contact that 8137 * the rule applies to.</td> 8138 * </tr> 8139 * <tr> 8140 * <td>long</td> 8141 * <td>{@link #RAW_CONTACT_ID2}</td> 8142 * <td>read/write</td> 8143 * <td>A reference to the other {@link RawContacts#_ID} of the raw contact 8144 * that the rule applies to.</td> 8145 * </tr> 8146 * </table> 8147 */ 8148 public static final class AggregationExceptions implements BaseColumns { 8149 /** 8150 * This utility class cannot be instantiated 8151 */ AggregationExceptions()8152 private AggregationExceptions() {} 8153 8154 /** 8155 * The content:// style URI for this table 8156 */ 8157 public static final Uri CONTENT_URI = 8158 Uri.withAppendedPath(AUTHORITY_URI, "aggregation_exceptions"); 8159 8160 /** 8161 * The MIME type of {@link #CONTENT_URI} providing a directory of data. 8162 */ 8163 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception"; 8164 8165 /** 8166 * The MIME type of a {@link #CONTENT_URI} subdirectory of an aggregation exception 8167 */ 8168 public static final String CONTENT_ITEM_TYPE = 8169 "vnd.android.cursor.item/aggregation_exception"; 8170 8171 /** 8172 * The type of exception: {@link #TYPE_KEEP_TOGETHER}, {@link #TYPE_KEEP_SEPARATE} or 8173 * {@link #TYPE_AUTOMATIC}. 8174 * 8175 * <P>Type: INTEGER</P> 8176 */ 8177 public static final String TYPE = "type"; 8178 8179 /** 8180 * Allows the provider to automatically decide whether the specified raw contacts should 8181 * be included in the same aggregate contact or not. 8182 */ 8183 public static final int TYPE_AUTOMATIC = 0; 8184 8185 /** 8186 * Makes sure that the specified raw contacts are included in the same 8187 * aggregate contact. 8188 */ 8189 public static final int TYPE_KEEP_TOGETHER = 1; 8190 8191 /** 8192 * Makes sure that the specified raw contacts are NOT included in the same 8193 * aggregate contact. 8194 */ 8195 public static final int TYPE_KEEP_SEPARATE = 2; 8196 8197 /** 8198 * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to. 8199 */ 8200 public static final String RAW_CONTACT_ID1 = "raw_contact_id1"; 8201 8202 /** 8203 * A reference to the other {@link RawContacts#_ID} of the raw contact that the rule 8204 * applies to. 8205 */ 8206 public static final String RAW_CONTACT_ID2 = "raw_contact_id2"; 8207 } 8208 8209 8210 /** 8211 * Class containing utility methods around determine what accounts in the ContactsProvider are 8212 * related to the SIM cards in the device. 8213 * <p> 8214 * Apps interested in managing contacts from SIM cards can query the ContactsProvider using 8215 * {@link #getSimAccounts(ContentResolver)} to get all accounts that relate to SIM cards. They 8216 * can also register a receiver for the {@link #ACTION_SIM_ACCOUNTS_CHANGED} broadcast to be 8217 * notified when these accounts change. 8218 */ 8219 public static final class SimContacts { 8220 /** 8221 * This utility class cannot be instantiated 8222 */ SimContacts()8223 private SimContacts() { 8224 } 8225 8226 /** 8227 * The method to invoke in order to add a new SIM account for a newly inserted SIM card. 8228 * 8229 * @hide 8230 */ 8231 public static final String ADD_SIM_ACCOUNT_METHOD = "addSimAccount"; 8232 8233 /** 8234 * The method to invoke in order to remove a SIM account once the corresponding SIM card is 8235 * ejected. 8236 * 8237 * @hide 8238 */ 8239 public static final String REMOVE_SIM_ACCOUNT_METHOD = "removeSimAccount"; 8240 8241 /** 8242 * The method to invoke in order to query all SIM accounts. 8243 * 8244 * @hide 8245 */ 8246 public static final String QUERY_SIM_ACCOUNTS_METHOD = "querySimAccounts"; 8247 8248 /** 8249 * Key to add in the outgoing Bundle for the SIM slot. 8250 * 8251 * @hide 8252 */ 8253 public static final String KEY_SIM_SLOT_INDEX = "key_sim_slot_index"; 8254 8255 /** 8256 * Key to add in the outgoing Bundle for the SIM account's EF type. 8257 * See {@link SimAccount#mEfType} for more information. 8258 * 8259 * @hide 8260 */ 8261 public static final String KEY_SIM_EF_TYPE = "key_sim_ef_type"; 8262 8263 /** 8264 * Key to add in the outgoing Bundle for the account name. 8265 * 8266 * @hide 8267 */ 8268 public static final String KEY_ACCOUNT_NAME = "key_sim_account_name"; 8269 8270 /** 8271 * Key to add in the outgoing Bundle for the account type. 8272 * 8273 * @hide 8274 */ 8275 public static final String KEY_ACCOUNT_TYPE = "key_sim_account_type"; 8276 8277 /** 8278 * Key in the incoming Bundle for the all the SIM accounts. 8279 * 8280 * @hide 8281 */ 8282 public static final String KEY_SIM_ACCOUNTS = "key_sim_accounts"; 8283 8284 /** 8285 * Broadcast Action: SIM accounts have changed, call 8286 * {@link #getSimAccounts(ContentResolver)} to get the latest. 8287 */ 8288 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 8289 public static final String ACTION_SIM_ACCOUNTS_CHANGED = 8290 "android.provider.action.SIM_ACCOUNTS_CHANGED"; 8291 8292 /** 8293 * Adds a new SIM account that maps to the corresponding SIM slot. 8294 * 8295 * @param accountName accountName value for the account 8296 * @param accountType accountType value for the account 8297 * @param contentResolver to perform the operation on. 8298 * @param simSlotIndex the SIM slot index of this new account. 8299 * @param efType the EF type of this new account. 8300 * @hide 8301 */ 8302 @SystemApi 8303 @RequiresPermission("android.contacts.permission.MANAGE_SIM_ACCOUNTS") addSimAccount(@onNull ContentResolver contentResolver, @NonNull String accountName, @NonNull String accountType, int simSlotIndex, int efType)8304 public static void addSimAccount(@NonNull ContentResolver contentResolver, 8305 @NonNull String accountName, 8306 @NonNull String accountType, 8307 int simSlotIndex, 8308 int efType) { 8309 if (simSlotIndex < 0) { 8310 throw new IllegalArgumentException("Sim slot is negative"); 8311 } 8312 if (!SimAccount.getValidEfTypes().contains(efType)) { 8313 throw new IllegalArgumentException("Invalid EF type"); 8314 } 8315 if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { 8316 throw new IllegalArgumentException("Account name or type is empty"); 8317 } 8318 8319 Bundle extras = new Bundle(); 8320 extras.putInt(KEY_SIM_SLOT_INDEX, simSlotIndex); 8321 extras.putInt(KEY_SIM_EF_TYPE, efType); 8322 extras.putString(KEY_ACCOUNT_NAME, accountName); 8323 extras.putString(KEY_ACCOUNT_TYPE, accountType); 8324 8325 contentResolver.call(ContactsContract.AUTHORITY_URI, 8326 ContactsContract.SimContacts.ADD_SIM_ACCOUNT_METHOD, 8327 null, extras); 8328 } 8329 8330 /** 8331 * Removes all SIM accounts that map to the corresponding SIM slot. 8332 * 8333 * @param contentResolver to perform the operation on. 8334 * @param simSlotIndex the SIM slot index of the accounts to remove. 8335 * @hide 8336 */ 8337 @SystemApi 8338 @RequiresPermission("android.contacts.permission.MANAGE_SIM_ACCOUNTS") removeSimAccounts(@onNull ContentResolver contentResolver, int simSlotIndex)8339 public static void removeSimAccounts(@NonNull ContentResolver contentResolver, 8340 int simSlotIndex) { 8341 if (simSlotIndex < 0) { 8342 throw new IllegalArgumentException("Sim slot is negative"); 8343 } 8344 8345 Bundle extras = new Bundle(); 8346 extras.putInt(KEY_SIM_SLOT_INDEX, simSlotIndex); 8347 8348 contentResolver.call(ContactsContract.AUTHORITY_URI, 8349 ContactsContract.SimContacts.REMOVE_SIM_ACCOUNT_METHOD, 8350 null, extras); 8351 } 8352 8353 /** 8354 * Returns all known SIM accounts. May be empty but never null. 8355 * 8356 * @param contentResolver content resolver to query. 8357 */ getSimAccounts( @onNull ContentResolver contentResolver)8358 public static @NonNull List<SimAccount> getSimAccounts( 8359 @NonNull ContentResolver contentResolver) { 8360 Bundle response = contentResolver.call(ContactsContract.AUTHORITY_URI, 8361 ContactsContract.SimContacts.QUERY_SIM_ACCOUNTS_METHOD, 8362 null, null); 8363 List<SimAccount> result = response.getParcelableArrayList(KEY_SIM_ACCOUNTS); 8364 8365 if (result == null) { 8366 result = new ArrayList<>(); 8367 } 8368 8369 return result; 8370 } 8371 } 8372 8373 /** 8374 * A parcelable class encapsulating account data for contacts that originate from a SIM card. 8375 */ 8376 public static final class SimAccount implements Parcelable { 8377 /** An invalid EF type identifier. */ 8378 public static final int UNKNOWN_EF_TYPE = 0; 8379 /** EF type identifier for the ADN partition. */ 8380 public static final int ADN_EF_TYPE = 1; 8381 /** EF type identifier for the FDN partition. */ 8382 public static final int FDN_EF_TYPE = 2; 8383 /** EF type identifier for the SDN partition. */ 8384 public static final int SDN_EF_TYPE = 3; 8385 8386 /** 8387 * The account_name of this SIM account. See {@link RawContacts#ACCOUNT_NAME}. 8388 */ 8389 private final String mAccountName; 8390 8391 /** 8392 * The account_type of this SIM account. See {@link RawContacts#ACCOUNT_TYPE}. 8393 */ 8394 private final String mAccountType; 8395 8396 /** 8397 * The slot index of the SIM card this account maps to. See {@link 8398 * android.telephony.SubscriptionInfo#getSimSlotIndex()}. 8399 */ 8400 private final int mSimSlotIndex; 8401 8402 /** 8403 * The EF type of the contacts stored in this account. One of 8404 * {@link #ADN_EF_TYPE}, {@link #SDN_EF_TYPE} or {@link #FDN_EF_TYPE}. 8405 * 8406 * EF type is the Elementary File type of the partition these contacts come from within the 8407 * SIM card. 8408 * 8409 * ADN is the "abbreviated dialing numbers" or the user managed SIM contacts. 8410 * 8411 * SDN is the "service dialing numbers" which are usually preloaded onto the SIM by the 8412 * carrier. 8413 * 8414 * FDN is the "fixed dialing numbers" which are contacts which can only be dialed from that 8415 * SIM, used in cases such as parental control. 8416 */ 8417 private final int mEfType; 8418 8419 /** 8420 * @return A set containing all known EF type values 8421 * @hide 8422 */ getValidEfTypes()8423 public static @NonNull Set<Integer> getValidEfTypes() { 8424 return Sets.newArraySet(ADN_EF_TYPE, SDN_EF_TYPE, FDN_EF_TYPE); 8425 } 8426 8427 /** 8428 * @hide 8429 */ SimAccount(@onNull String accountName, @NonNull String accountType, int simSlotIndex, int efType)8430 public SimAccount(@NonNull String accountName, @NonNull String accountType, 8431 int simSlotIndex, 8432 int efType) { 8433 this.mAccountName = accountName; 8434 this.mAccountType = accountType; 8435 this.mSimSlotIndex = simSlotIndex; 8436 this.mEfType = efType; 8437 } 8438 8439 /** 8440 * @return The account_name of this SIM account. See {@link RawContacts#ACCOUNT_NAME}. 8441 */ getAccountName()8442 public @NonNull String getAccountName() { 8443 return mAccountName; 8444 } 8445 8446 /** 8447 * @return The account_type of this SIM account. See {@link RawContacts#ACCOUNT_TYPE}. 8448 */ getAccountType()8449 public @NonNull String getAccountType() { 8450 return mAccountType; 8451 } 8452 8453 /** 8454 * @return The slot index of the SIM card this account maps to. See 8455 * {@link android.telephony.SubscriptionInfo#getSimSlotIndex()}. 8456 */ getSimSlotIndex()8457 public int getSimSlotIndex() { 8458 return mSimSlotIndex; 8459 } 8460 8461 /** 8462 * @return The EF type of the contacts stored in this account. 8463 */ getEfType()8464 public int getEfType() { 8465 return mEfType; 8466 } 8467 8468 @Override hashCode()8469 public int hashCode() { 8470 return Objects.hash(mAccountName, mAccountType, mSimSlotIndex, mEfType); 8471 } 8472 8473 @Override equals(Object obj)8474 public boolean equals(Object obj) { 8475 if (obj == null) return false; 8476 if (obj == this) return true; 8477 8478 SimAccount toCompare; 8479 try { 8480 toCompare = (SimAccount) obj; 8481 } catch (ClassCastException ex) { 8482 return false; 8483 } 8484 8485 return mSimSlotIndex == toCompare.mSimSlotIndex 8486 && mEfType == toCompare.mEfType 8487 && Objects.equals(mAccountName, toCompare.mAccountName) 8488 && Objects.equals(mAccountType, toCompare.mAccountType); 8489 } 8490 8491 @Override writeToParcel(@onNull Parcel dest, int flags)8492 public void writeToParcel(@NonNull Parcel dest, int flags) { 8493 dest.writeString(mAccountName); 8494 dest.writeString(mAccountType); 8495 dest.writeInt(mSimSlotIndex); 8496 dest.writeInt(mEfType); 8497 } 8498 8499 @Override describeContents()8500 public int describeContents() { 8501 return 0; 8502 } 8503 8504 public static final @NonNull Parcelable.Creator<SimAccount> CREATOR = 8505 new Parcelable.Creator<SimAccount>() { 8506 @Override 8507 public SimAccount createFromParcel(Parcel source) { 8508 String accountName = source.readString(); 8509 String accountType = source.readString(); 8510 int simSlot = source.readInt(); 8511 int efType = source.readInt(); 8512 SimAccount simAccount = new SimAccount(accountName, accountType, simSlot, 8513 efType); 8514 return simAccount; 8515 } 8516 8517 @Override 8518 public SimAccount[] newArray(int size) { 8519 return new SimAccount[size]; 8520 } 8521 }; 8522 } 8523 8524 /** 8525 * @see Settings 8526 */ 8527 protected interface SettingsColumns { 8528 /** 8529 * The name of the account instance to which this row belongs. 8530 * <P>Type: TEXT</P> 8531 */ 8532 public static final String ACCOUNT_NAME = "account_name"; 8533 8534 /** 8535 * The type of account to which this row belongs, which when paired with 8536 * {@link #ACCOUNT_NAME} identifies a specific account. 8537 * <P>Type: TEXT</P> 8538 */ 8539 public static final String ACCOUNT_TYPE = "account_type"; 8540 8541 /** 8542 * The data set within the account that this row belongs to. This allows 8543 * multiple sync adapters for the same account type to distinguish between 8544 * each others' data. 8545 * 8546 * This is empty by default, and is completely optional. It only needs to 8547 * be populated if multiple sync adapters are entering distinct data for 8548 * the same account type and account name. 8549 * <P>Type: TEXT</P> 8550 */ 8551 public static final String DATA_SET = "data_set"; 8552 8553 /** 8554 * Depending on the mode defined by the sync-adapter, this flag controls 8555 * the top-level sync behavior for this data source. 8556 * <p> 8557 * Type: INTEGER (boolean) 8558 */ 8559 public static final String SHOULD_SYNC = "should_sync"; 8560 8561 /** 8562 * Flag indicating if contacts without any {@link CommonDataKinds.GroupMembership} 8563 * entries should be visible in any user interface. 8564 * <p> 8565 * Type: INTEGER (boolean) 8566 */ 8567 public static final String UNGROUPED_VISIBLE = "ungrouped_visible"; 8568 8569 /** 8570 * Read-only flag indicating if this {@link #SHOULD_SYNC} or any 8571 * {@link Groups#SHOULD_SYNC} under this account have been marked as 8572 * unsynced. 8573 */ 8574 public static final String ANY_UNSYNCED = "any_unsynced"; 8575 8576 /** 8577 * Read-only count of {@link Contacts} from a specific source that have 8578 * no {@link CommonDataKinds.GroupMembership} entries. 8579 * <p> 8580 * Type: INTEGER 8581 */ 8582 public static final String UNGROUPED_COUNT = "summ_count"; 8583 8584 /** 8585 * Read-only count of {@link Contacts} from a specific source that have 8586 * no {@link CommonDataKinds.GroupMembership} entries, and also have phone numbers. 8587 * <p> 8588 * Type: INTEGER 8589 */ 8590 public static final String UNGROUPED_WITH_PHONES = "summ_phones"; 8591 } 8592 8593 /** 8594 * <p> 8595 * Contacts-specific settings for various {@link Account}'s. 8596 * </p> 8597 * <h2>Columns</h2> 8598 * <table class="jd-sumtable"> 8599 * <tr> 8600 * <th colspan='4'>Settings</th> 8601 * </tr> 8602 * <tr> 8603 * <td>String</td> 8604 * <td>{@link #ACCOUNT_NAME}</td> 8605 * <td>read/write-once</td> 8606 * <td>The name of the account instance to which this row belongs.</td> 8607 * </tr> 8608 * <tr> 8609 * <td>String</td> 8610 * <td>{@link #ACCOUNT_TYPE}</td> 8611 * <td>read/write-once</td> 8612 * <td>The type of account to which this row belongs, which when paired with 8613 * {@link #ACCOUNT_NAME} identifies a specific account.</td> 8614 * </tr> 8615 * <tr> 8616 * <td>int</td> 8617 * <td>{@link #SHOULD_SYNC}</td> 8618 * <td>read/write</td> 8619 * <td>Depending on the mode defined by the sync-adapter, this flag controls 8620 * the top-level sync behavior for this data source.</td> 8621 * </tr> 8622 * <tr> 8623 * <td>int</td> 8624 * <td>{@link #UNGROUPED_VISIBLE}</td> 8625 * <td>read/write</td> 8626 * <td>Flag indicating if contacts without any 8627 * {@link CommonDataKinds.GroupMembership} entries should be visible in any 8628 * user interface.</td> 8629 * </tr> 8630 * <tr> 8631 * <td>int</td> 8632 * <td>{@link #ANY_UNSYNCED}</td> 8633 * <td>read-only</td> 8634 * <td>Read-only flag indicating if this {@link #SHOULD_SYNC} or any 8635 * {@link Groups#SHOULD_SYNC} under this account have been marked as 8636 * unsynced.</td> 8637 * </tr> 8638 * <tr> 8639 * <td>int</td> 8640 * <td>{@link #UNGROUPED_COUNT}</td> 8641 * <td>read-only</td> 8642 * <td>Read-only count of {@link Contacts} from a specific source that have 8643 * no {@link CommonDataKinds.GroupMembership} entries.</td> 8644 * </tr> 8645 * <tr> 8646 * <td>int</td> 8647 * <td>{@link #UNGROUPED_WITH_PHONES}</td> 8648 * <td>read-only</td> 8649 * <td>Read-only count of {@link Contacts} from a specific source that have 8650 * no {@link CommonDataKinds.GroupMembership} entries, and also have phone 8651 * numbers.</td> 8652 * </tr> 8653 * </table> 8654 */ 8655 public static final class Settings implements SettingsColumns { 8656 /** 8657 * This utility class cannot be instantiated 8658 */ Settings()8659 private Settings() { 8660 } 8661 8662 /** 8663 * The content:// style URI for this table 8664 */ 8665 public static final Uri CONTENT_URI = 8666 Uri.withAppendedPath(AUTHORITY_URI, "settings"); 8667 8668 /** 8669 * The MIME-type of {@link #CONTENT_URI} providing a directory of 8670 * settings. 8671 */ 8672 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting"; 8673 8674 /** 8675 * The MIME-type of {@link #CONTENT_URI} providing a single setting. 8676 */ 8677 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting"; 8678 } 8679 8680 /** 8681 * API for inquiring about the general status of the provider. 8682 */ 8683 public static final class ProviderStatus { 8684 8685 /** 8686 * Not instantiable. 8687 */ ProviderStatus()8688 private ProviderStatus() { 8689 } 8690 8691 /** 8692 * The content:// style URI for this table. Requests to this URI can be 8693 * performed on the UI thread because they are always unblocking. 8694 */ 8695 public static final Uri CONTENT_URI = 8696 Uri.withAppendedPath(AUTHORITY_URI, "provider_status"); 8697 8698 /** 8699 * The MIME-type of {@link #CONTENT_URI} providing a directory of 8700 * settings. 8701 */ 8702 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/provider_status"; 8703 8704 /** 8705 * An integer representing the current status of the provider. 8706 */ 8707 public static final String STATUS = "status"; 8708 8709 /** 8710 * Default status of the provider. 8711 */ 8712 public static final int STATUS_NORMAL = 0; 8713 8714 /** 8715 * The provider won't respond to queries. It is in the middle of a long running task, such 8716 * as a database upgrade or locale change. 8717 */ 8718 public static final int STATUS_BUSY = 1; 8719 8720 /** 8721 * The status that indicates that there are no accounts and no contacts 8722 * on the device. 8723 */ 8724 public static final int STATUS_EMPTY = 2; 8725 8726 /** 8727 * Timestamp (milliseconds since epoch) of when the provider's database was created. 8728 * 8729 * <P>Type: long 8730 */ 8731 public static final String DATABASE_CREATION_TIMESTAMP = "database_creation_timestamp"; 8732 } 8733 8734 /** 8735 * <p> 8736 * API allowing applications to send usage information for each {@link Data} row to the 8737 * Contacts Provider. Applications can also clear all usage information. 8738 * </p> 8739 * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, 8740 * this field is obsolete, regardless of Android version. For more information, see the 8741 * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a> 8742 * page.</p> 8743 * <p> 8744 * With the feedback, Contacts Provider may return more contextually appropriate results for 8745 * Data listing, typically supplied with 8746 * {@link ContactsContract.Contacts#CONTENT_FILTER_URI}, 8747 * {@link ContactsContract.CommonDataKinds.Email#CONTENT_FILTER_URI}, 8748 * {@link ContactsContract.CommonDataKinds.Phone#CONTENT_FILTER_URI}, and users can benefit 8749 * from better ranked (sorted) lists in applications that show auto-complete list. 8750 * </p> 8751 * <p> 8752 * There is no guarantee for how this feedback is used, or even whether it is used at all. 8753 * The ranking algorithm will make best efforts to use the feedback data, but the exact 8754 * implementation, the storage data structures as well as the resulting sort order is device 8755 * and version specific and can change over time. 8756 * </p> 8757 * <p> 8758 * When updating usage information, users of this API need to use 8759 * {@link ContentResolver#update(Uri, ContentValues, String, String[])} with a Uri constructed 8760 * from {@link DataUsageFeedback#FEEDBACK_URI}. The Uri must contain one or more data id(s) as 8761 * its last path. They also need to append a query parameter to the Uri, to specify the type of 8762 * the communication, which enables the Contacts Provider to differentiate between kinds of 8763 * interactions using the same contact data field (for example a phone number can be used to 8764 * make phone calls or send SMS). 8765 * </p> 8766 * <p> 8767 * Selection and selectionArgs are ignored and must be set to null. To get data ids, 8768 * you may need to call {@link ContentResolver#query(Uri, String[], String, String[], String)} 8769 * toward {@link Data#CONTENT_URI}. 8770 * </p> 8771 * <p> 8772 * {@link ContentResolver#update(Uri, ContentValues, String, String[])} returns a positive 8773 * integer when successful, and returns 0 if no contact with that id was found. 8774 * </p> 8775 * <p> 8776 * Example: 8777 * <pre> 8778 * Uri uri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 8779 * .appendPath(TextUtils.join(",", dataIds)) 8780 * .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, 8781 * DataUsageFeedback.USAGE_TYPE_CALL) 8782 * .build(); 8783 * boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0; 8784 * </pre> 8785 * </p> 8786 * <p> 8787 * Applications can also clear all usage information with: 8788 * <pre> 8789 * boolean successful = resolver.delete(DataUsageFeedback.DELETE_USAGE_URI, null, null) > 0; 8790 * </pre> 8791 * </p> 8792 * 8793 * @deprecated Contacts affinity information is no longer supported as of 8794 * Android version {@link android.os.Build.VERSION_CODES#Q}. 8795 * Both update and delete calls are always ignored. 8796 */ 8797 @Deprecated 8798 public static final class DataUsageFeedback { 8799 8800 /** 8801 * The content:// style URI for sending usage feedback. 8802 * Must be used with {@link ContentResolver#update(Uri, ContentValues, String, String[])}. 8803 */ 8804 public static final Uri FEEDBACK_URI = 8805 Uri.withAppendedPath(Data.CONTENT_URI, "usagefeedback"); 8806 8807 /** 8808 * The content:// style URI for deleting all usage information. 8809 * Must be used with {@link ContentResolver#delete(Uri, String, String[])}. 8810 * The {@code where} and {@code selectionArgs} parameters are ignored. 8811 */ 8812 public static final Uri DELETE_USAGE_URI = 8813 Uri.withAppendedPath(Contacts.CONTENT_URI, "delete_usage"); 8814 8815 /** 8816 * <p> 8817 * Name for query parameter specifying the type of data usage. 8818 * </p> 8819 */ 8820 public static final String USAGE_TYPE = "type"; 8821 8822 /** 8823 * <p> 8824 * Type of usage for voice interaction, which includes phone call, voice chat, and 8825 * video chat. 8826 * </p> 8827 */ 8828 public static final String USAGE_TYPE_CALL = "call"; 8829 8830 /** 8831 * <p> 8832 * Type of usage for text interaction involving longer messages, which includes email. 8833 * </p> 8834 */ 8835 public static final String USAGE_TYPE_LONG_TEXT = "long_text"; 8836 8837 /** 8838 * <p> 8839 * Type of usage for text interaction involving shorter messages, which includes SMS, 8840 * text chat with email addresses. 8841 * </p> 8842 */ 8843 public static final String USAGE_TYPE_SHORT_TEXT = "short_text"; 8844 } 8845 8846 /** 8847 * <p> 8848 * Contact-specific information about whether or not a contact has been pinned by the user 8849 * at a particular position within the system contact application's user interface. 8850 * </p> 8851 * 8852 * <p> 8853 * This pinning information can be used by individual applications to customize how 8854 * they order particular pinned contacts. For example, a Dialer application could 8855 * use pinned information to order user-pinned contacts in a top row of favorites. 8856 * </p> 8857 * 8858 * <p> 8859 * It is possible for two or more contacts to occupy the same pinned position (due 8860 * to aggregation and sync), so this pinning information should be used on a best-effort 8861 * basis to order contacts in-application rather than an absolute guide on where a contact 8862 * should be positioned. Contacts returned by the ContactsProvider will not be ordered based 8863 * on this information, so it is up to the client application to reorder these contacts within 8864 * their own UI adhering to (or ignoring as appropriate) information stored in the pinned 8865 * column. 8866 * </p> 8867 * 8868 * <p> 8869 * By default, unpinned contacts will have a pinned position of 8870 * {@link PinnedPositions#UNPINNED}. Client-provided pinned positions can be positive 8871 * integers that are greater than 1. 8872 * </p> 8873 */ 8874 public static final class PinnedPositions { 8875 /** 8876 * The method to invoke in order to undemote a formerly demoted contact. The contact id of 8877 * the contact must be provided as an argument. If the contact was not previously demoted, 8878 * nothing will be done. 8879 * @hide 8880 */ 8881 @TestApi 8882 public static final String UNDEMOTE_METHOD = "undemote"; 8883 8884 /** 8885 * Undemotes a formerly demoted contact. If the contact was not previously demoted, nothing 8886 * will be done. 8887 * 8888 * @param contentResolver to perform the undemote operation on. 8889 * @param contactId the id of the contact to undemote. 8890 */ undemote(ContentResolver contentResolver, long contactId)8891 public static void undemote(ContentResolver contentResolver, long contactId) { 8892 contentResolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD, 8893 String.valueOf(contactId), null); 8894 } 8895 8896 /** 8897 * Pins a contact at a provided position, or unpins a contact. 8898 * 8899 * @param contentResolver to perform the pinning operation on. 8900 * @param pinnedPosition the position to pin the contact at. To unpin a contact, use 8901 * {@link PinnedPositions#UNPINNED}. 8902 */ pin( ContentResolver contentResolver, long contactId, int pinnedPosition)8903 public static void pin( 8904 ContentResolver contentResolver, long contactId, int pinnedPosition) { 8905 final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_URI, String.valueOf(contactId)); 8906 final ContentValues values = new ContentValues(); 8907 values.put(Contacts.PINNED, pinnedPosition); 8908 contentResolver.update(uri, values, null, null); 8909 } 8910 8911 /** 8912 * Default value for the pinned position of an unpinned contact. 8913 */ 8914 public static final int UNPINNED = 0; 8915 8916 /** 8917 * Value of pinned position for a contact that a user has indicated should be considered 8918 * of the lowest priority. It is up to the client application to determine how to present 8919 * such a contact - for example all the way at the bottom of a contact list, or simply 8920 * just hidden from view. 8921 */ 8922 public static final int DEMOTED = -1; 8923 } 8924 8925 /** 8926 * Helper methods to display QuickContact dialogs that display all the information belonging to 8927 * a specific {@link Contacts} entry. 8928 */ 8929 public static final class QuickContact { 8930 /** 8931 * Action used to launch the system contacts application and bring up a QuickContact dialog 8932 * for the provided {@link Contacts} entry. 8933 */ 8934 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 8935 public static final String ACTION_QUICK_CONTACT = 8936 "android.provider.action.QUICK_CONTACT"; 8937 8938 /** 8939 * Extra used to specify pivot dialog location in screen coordinates. 8940 * @deprecated Use {@link Intent#setSourceBounds(Rect)} instead. 8941 * @hide 8942 */ 8943 @Deprecated 8944 public static final String EXTRA_TARGET_RECT = "android.provider.extra.TARGET_RECT"; 8945 8946 /** 8947 * Extra used to specify size of QuickContacts. Not all implementations of QuickContacts 8948 * will respect this extra's value. 8949 * 8950 * One of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}. 8951 */ 8952 public static final String EXTRA_MODE = "android.provider.extra.MODE"; 8953 8954 /** 8955 * Extra used to specify which mimetype should be prioritized in the QuickContacts UI. 8956 * For example, passing the value {@link CommonDataKinds.Phone#CONTENT_ITEM_TYPE} can 8957 * cause phone numbers to be displayed more prominently in QuickContacts. 8958 */ 8959 public static final String EXTRA_PRIORITIZED_MIMETYPE 8960 = "android.provider.extra.PRIORITIZED_MIMETYPE"; 8961 8962 /** 8963 * Extra used to indicate a list of specific MIME-types to exclude and not display in the 8964 * QuickContacts dialog. Stored as a {@link String} array. 8965 */ 8966 public static final String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES"; 8967 8968 /** 8969 * Small QuickContact mode, usually presented with minimal actions. 8970 */ 8971 public static final int MODE_SMALL = 1; 8972 8973 /** 8974 * Medium QuickContact mode, includes actions and light summary describing 8975 * the {@link Contacts} entry being shown. This may include social 8976 * status and presence details. 8977 */ 8978 public static final int MODE_MEDIUM = 2; 8979 8980 /** 8981 * Large QuickContact mode, includes actions and larger, card-like summary 8982 * of the {@link Contacts} entry being shown. This may include detailed 8983 * information, such as a photo. 8984 */ 8985 public static final int MODE_LARGE = 3; 8986 8987 /** @hide */ 8988 public static final int MODE_DEFAULT = MODE_LARGE; 8989 8990 /** 8991 * Constructs the QuickContacts intent with a view's rect. 8992 * @hide 8993 */ composeQuickContactsIntent(Context context, View target, Uri lookupUri, int mode, String[] excludeMimes)8994 public static Intent composeQuickContactsIntent(Context context, View target, Uri lookupUri, 8995 int mode, String[] excludeMimes) { 8996 // Find location and bounds of target view, adjusting based on the 8997 // assumed local density. 8998 final float appScale = context.getResources().getCompatibilityInfo().applicationScale; 8999 final int[] pos = new int[2]; 9000 target.getLocationOnScreen(pos); 9001 9002 final Rect rect = new Rect(); 9003 rect.left = (int) (pos[0] * appScale + 0.5f); 9004 rect.top = (int) (pos[1] * appScale + 0.5f); 9005 rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f); 9006 rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f); 9007 9008 return composeQuickContactsIntent(context, rect, lookupUri, mode, excludeMimes); 9009 } 9010 9011 /** 9012 * Constructs the QuickContacts intent. 9013 * @hide 9014 */ 9015 @UnsupportedAppUsage composeQuickContactsIntent(Context context, Rect target, Uri lookupUri, int mode, String[] excludeMimes)9016 public static Intent composeQuickContactsIntent(Context context, Rect target, 9017 Uri lookupUri, int mode, String[] excludeMimes) { 9018 // When launching from an Activiy, we don't want to start a new task, but otherwise 9019 // we *must* start a new task. (Otherwise startActivity() would crash.) 9020 Context actualContext = context; 9021 while ((actualContext instanceof ContextWrapper) 9022 && !(actualContext instanceof Activity)) { 9023 actualContext = ((ContextWrapper) actualContext).getBaseContext(); 9024 } 9025 final int intentFlags = ((actualContext instanceof Activity) 9026 ? 0 : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) 9027 // Workaround for b/16898764. Declaring singleTop in manifest doesn't work. 9028 | Intent.FLAG_ACTIVITY_SINGLE_TOP; 9029 9030 // Launch pivot dialog through intent for now 9031 final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags); 9032 9033 // NOTE: This logic and rebuildManagedQuickContactsIntent() must be in sync. 9034 intent.setData(lookupUri); 9035 intent.setSourceBounds(target); 9036 intent.putExtra(EXTRA_MODE, mode); 9037 intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes); 9038 return intent; 9039 } 9040 9041 /** 9042 * Constructs a QuickContacts intent based on an incoming intent for DevicePolicyManager 9043 * to strip off anything not necessary. 9044 * 9045 * @hide 9046 */ rebuildManagedQuickContactsIntent(String lookupKey, long contactId, boolean isContactIdIgnored, long directoryId, Intent originalIntent)9047 public static Intent rebuildManagedQuickContactsIntent(String lookupKey, long contactId, 9048 boolean isContactIdIgnored, long directoryId, Intent originalIntent) { 9049 final Intent intent = new Intent(ACTION_QUICK_CONTACT); 9050 // Rebuild the URI from a lookup key and a contact ID. 9051 Uri uri = null; 9052 if (!TextUtils.isEmpty(lookupKey)) { 9053 uri = isContactIdIgnored 9054 ? Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey) 9055 : Contacts.getLookupUri(contactId, lookupKey); 9056 } 9057 if (uri != null && directoryId != Directory.DEFAULT) { 9058 uri = uri.buildUpon().appendQueryParameter( 9059 ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build(); 9060 } 9061 intent.setData(uri); 9062 9063 // Copy flags and always set NEW_TASK because it won't have a parent activity. 9064 intent.setFlags(originalIntent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); 9065 9066 // Copy extras. 9067 intent.setSourceBounds(originalIntent.getSourceBounds()); 9068 intent.putExtra(EXTRA_MODE, originalIntent.getIntExtra(EXTRA_MODE, MODE_DEFAULT)); 9069 intent.putExtra(EXTRA_EXCLUDE_MIMES, 9070 originalIntent.getStringArrayExtra(EXTRA_EXCLUDE_MIMES)); 9071 return intent; 9072 } 9073 9074 9075 /** 9076 * Trigger a dialog that lists the various methods of interacting with 9077 * the requested {@link Contacts} entry. This may be based on available 9078 * {@link ContactsContract.Data} rows under that contact, and may also 9079 * include social status and presence details. 9080 * 9081 * @param context The parent {@link Context} that may be used as the 9082 * parent for this dialog. 9083 * @param target Specific {@link View} from your layout that this dialog 9084 * should be centered around. In particular, if the dialog 9085 * has a "callout" arrow, it will be pointed and centered 9086 * around this {@link View}. 9087 * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 9088 * {@link Uri} that describes a specific contact to feature 9089 * in this dialog. A work lookup uri is supported here, 9090 * see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and 9091 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}. 9092 * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or 9093 * {@link #MODE_LARGE}, indicating the desired dialog size, 9094 * when supported. 9095 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 9096 * to exclude when showing this dialog. For example, when 9097 * already viewing the contact details card, this can be used 9098 * to omit the details entry from the dialog. 9099 */ showQuickContact(Context context, View target, Uri lookupUri, int mode, String[] excludeMimes)9100 public static void showQuickContact(Context context, View target, Uri lookupUri, int mode, 9101 String[] excludeMimes) { 9102 // Trigger with obtained rectangle 9103 Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode, 9104 excludeMimes); 9105 ContactsInternal.startQuickContactWithErrorToast(context, intent); 9106 } 9107 9108 /** 9109 * Trigger a dialog that lists the various methods of interacting with 9110 * the requested {@link Contacts} entry. This may be based on available 9111 * {@link ContactsContract.Data} rows under that contact, and may also 9112 * include social status and presence details. 9113 * 9114 * @param context The parent {@link Context} that may be used as the 9115 * parent for this dialog. 9116 * @param target Specific {@link Rect} that this dialog should be 9117 * centered around, in screen coordinates. In particular, if 9118 * the dialog has a "callout" arrow, it will be pointed and 9119 * centered around this {@link Rect}. If you are running at a 9120 * non-native density, you need to manually adjust using 9121 * {@link DisplayMetrics#density} before calling. 9122 * @param lookupUri A 9123 * {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 9124 * {@link Uri} that describes a specific contact to feature 9125 * in this dialog. A work lookup uri is supported here, 9126 * see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and 9127 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}. 9128 * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or 9129 * {@link #MODE_LARGE}, indicating the desired dialog size, 9130 * when supported. 9131 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 9132 * to exclude when showing this dialog. For example, when 9133 * already viewing the contact details card, this can be used 9134 * to omit the details entry from the dialog. 9135 */ showQuickContact(Context context, Rect target, Uri lookupUri, int mode, String[] excludeMimes)9136 public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode, 9137 String[] excludeMimes) { 9138 Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode, 9139 excludeMimes); 9140 ContactsInternal.startQuickContactWithErrorToast(context, intent); 9141 } 9142 9143 /** 9144 * Trigger a dialog that lists the various methods of interacting with 9145 * the requested {@link Contacts} entry. This may be based on available 9146 * {@link ContactsContract.Data} rows under that contact, and may also 9147 * include social status and presence details. 9148 * 9149 * @param context The parent {@link Context} that may be used as the 9150 * parent for this dialog. 9151 * @param target Specific {@link View} from your layout that this dialog 9152 * should be centered around. In particular, if the dialog 9153 * has a "callout" arrow, it will be pointed and centered 9154 * around this {@link View}. 9155 * @param lookupUri A 9156 * {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 9157 * {@link Uri} that describes a specific contact to feature 9158 * in this dialog. A work lookup uri is supported here, 9159 * see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and 9160 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}. 9161 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 9162 * to exclude when showing this dialog. For example, when 9163 * already viewing the contact details card, this can be used 9164 * to omit the details entry from the dialog. 9165 * @param prioritizedMimeType This mimetype should be prioritized in the QuickContacts UI. 9166 * For example, passing the value 9167 * {@link CommonDataKinds.Phone#CONTENT_ITEM_TYPE} can cause phone numbers to be 9168 * displayed more prominently in QuickContacts. 9169 */ showQuickContact(Context context, View target, Uri lookupUri, String[] excludeMimes, String prioritizedMimeType)9170 public static void showQuickContact(Context context, View target, Uri lookupUri, 9171 String[] excludeMimes, String prioritizedMimeType) { 9172 // Use MODE_LARGE instead of accepting mode as a parameter. The different mode 9173 // values defined in ContactsContract only affect very old implementations 9174 // of QuickContacts. 9175 Intent intent = composeQuickContactsIntent(context, target, lookupUri, MODE_DEFAULT, 9176 excludeMimes); 9177 intent.putExtra(EXTRA_PRIORITIZED_MIMETYPE, prioritizedMimeType); 9178 ContactsInternal.startQuickContactWithErrorToast(context, intent); 9179 } 9180 9181 /** 9182 * Trigger a dialog that lists the various methods of interacting with 9183 * the requested {@link Contacts} entry. This may be based on available 9184 * {@link ContactsContract.Data} rows under that contact, and may also 9185 * include social status and presence details. 9186 * 9187 * @param context The parent {@link Context} that may be used as the 9188 * parent for this dialog. 9189 * @param target Specific {@link Rect} that this dialog should be 9190 * centered around, in screen coordinates. In particular, if 9191 * the dialog has a "callout" arrow, it will be pointed and 9192 * centered around this {@link Rect}. If you are running at a 9193 * non-native density, you need to manually adjust using 9194 * {@link DisplayMetrics#density} before calling. 9195 * @param lookupUri A 9196 * {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style 9197 * {@link Uri} that describes a specific contact to feature 9198 * in this dialog. A work lookup uri is supported here, 9199 * see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and 9200 * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}. 9201 * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types 9202 * to exclude when showing this dialog. For example, when 9203 * already viewing the contact details card, this can be used 9204 * to omit the details entry from the dialog. 9205 * @param prioritizedMimeType This mimetype should be prioritized in the QuickContacts UI. 9206 * For example, passing the value 9207 * {@link CommonDataKinds.Phone#CONTENT_ITEM_TYPE} can cause phone numbers to be 9208 * displayed more prominently in QuickContacts. 9209 */ showQuickContact(Context context, Rect target, Uri lookupUri, String[] excludeMimes, String prioritizedMimeType)9210 public static void showQuickContact(Context context, Rect target, Uri lookupUri, 9211 String[] excludeMimes, String prioritizedMimeType) { 9212 // Use MODE_LARGE instead of accepting mode as a parameter. The different mode 9213 // values defined in ContactsContract only affect very old implementations 9214 // of QuickContacts. 9215 Intent intent = composeQuickContactsIntent(context, target, lookupUri, MODE_DEFAULT, 9216 excludeMimes); 9217 intent.putExtra(EXTRA_PRIORITIZED_MIMETYPE, prioritizedMimeType); 9218 ContactsInternal.startQuickContactWithErrorToast(context, intent); 9219 } 9220 } 9221 9222 /** 9223 * Helper class for accessing full-size photos by photo file ID. 9224 * <p> 9225 * Usage example: 9226 * <dl> 9227 * <dt>Retrieving a full-size photo by photo file ID (see 9228 * {@link ContactsContract.ContactsColumns#PHOTO_FILE_ID}) 9229 * </dt> 9230 * <dd> 9231 * <pre> 9232 * public InputStream openDisplayPhoto(long photoFileId) { 9233 * Uri displayPhotoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoKey); 9234 * try { 9235 * AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor( 9236 * displayPhotoUri, "r"); 9237 * return fd.createInputStream(); 9238 * } catch (IOException e) { 9239 * return null; 9240 * } 9241 * } 9242 * </pre> 9243 * </dd> 9244 * </dl> 9245 * </p> 9246 */ 9247 public static final class DisplayPhoto { 9248 /** 9249 * no public constructor since this is a utility class 9250 */ DisplayPhoto()9251 private DisplayPhoto() {} 9252 9253 /** 9254 * The content:// style URI for this class, which allows access to full-size photos, 9255 * given a key. 9256 */ 9257 public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "display_photo"); 9258 9259 /** 9260 * This URI allows the caller to query for the maximum dimensions of a display photo 9261 * or thumbnail. Requests to this URI can be performed on the UI thread because 9262 * they are always unblocking. 9263 */ 9264 public static final Uri CONTENT_MAX_DIMENSIONS_URI = 9265 Uri.withAppendedPath(AUTHORITY_URI, "photo_dimensions"); 9266 9267 /** 9268 * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will 9269 * contain this column, populated with the maximum height and width (in pixels) 9270 * that will be stored for a display photo. Larger photos will be down-sized to 9271 * fit within a square of this many pixels. 9272 */ 9273 public static final String DISPLAY_MAX_DIM = "display_max_dim"; 9274 9275 /** 9276 * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will 9277 * contain this column, populated with the height and width (in pixels) for photo 9278 * thumbnails. 9279 */ 9280 public static final String THUMBNAIL_MAX_DIM = "thumbnail_max_dim"; 9281 } 9282 9283 /** 9284 * Contains helper classes used to create or manage {@link android.content.Intent Intents} 9285 * that involve contacts. 9286 */ 9287 public static final class Intents { 9288 /** 9289 * This is the intent that is fired when a search suggestion is clicked on. 9290 */ 9291 public static final String SEARCH_SUGGESTION_CLICKED = 9292 "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED"; 9293 9294 /** 9295 * This is the intent that is fired when a search suggestion for dialing a number 9296 * is clicked on. 9297 */ 9298 public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = 9299 "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED"; 9300 9301 /** 9302 * This is the intent that is fired when a search suggestion for creating a contact 9303 * is clicked on. 9304 */ 9305 public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = 9306 "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED"; 9307 9308 /** 9309 * This is the intent that is fired when the contacts database is created. <p> The 9310 * READ_CONTACT permission is required to receive these broadcasts. 9311 * 9312 * <p>Because this is an implicit broadcast, apps targeting Android O will no longer 9313 * receive this broadcast via a manifest broadcast receiver. (Broadcast receivers 9314 * registered at runtime with 9315 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)} will still receive it.) 9316 * Instead, an app can use {@link ProviderStatus#DATABASE_CREATION_TIMESTAMP} to see if the 9317 * contacts database has been initialized when it starts. 9318 */ 9319 public static final String CONTACTS_DATABASE_CREATED = 9320 "android.provider.Contacts.DATABASE_CREATED"; 9321 9322 /** 9323 * Starts an Activity that lets the user pick a contact to attach an image to. 9324 * After picking the contact it launches the image cropper in face detection mode. 9325 */ 9326 public static final String ATTACH_IMAGE = 9327 "com.android.contacts.action.ATTACH_IMAGE"; 9328 9329 /** 9330 * This is the intent that is fired when the user clicks the "invite to the network" button 9331 * on a contact. Only sent to an activity which is explicitly registered by a contact 9332 * provider which supports the "invite to the network" feature. 9333 * <p> 9334 * {@link Intent#getData()} contains the lookup URI for the contact. 9335 */ 9336 public static final String INVITE_CONTACT = 9337 "com.android.contacts.action.INVITE_CONTACT"; 9338 9339 /** 9340 * Takes as input a data URI with a mailto: or tel: scheme. If a single 9341 * contact exists with the given data it will be shown. If no contact 9342 * exists, a dialog will ask the user if they want to create a new 9343 * contact with the provided details filled in. If multiple contacts 9344 * share the data the user will be prompted to pick which contact they 9345 * want to view. 9346 * <p> 9347 * For <code>mailto:</code> URIs, the scheme specific portion must be a 9348 * raw email address, such as one built using 9349 * {@link Uri#fromParts(String, String, String)}. 9350 * <p> 9351 * For <code>tel:</code> URIs, the scheme specific portion is compared 9352 * to existing numbers using the standard caller ID lookup algorithm. 9353 * The number must be properly encoded, for example using 9354 * {@link Uri#fromParts(String, String, String)}. 9355 * <p> 9356 * Any extras from the {@link Insert} class will be passed along to the 9357 * create activity if there are no contacts to show. 9358 * <p> 9359 * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip 9360 * prompting the user when the contact doesn't exist. 9361 */ 9362 public static final String SHOW_OR_CREATE_CONTACT = 9363 "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; 9364 9365 /** 9366 * Activity Action: Initiate a message to someone by voice. The message could be text, 9367 * audio, video or image(photo). This action supports messaging with a specific contact 9368 * regardless of the underlying messaging protocol used. 9369 * <p> 9370 * The action could be originated from the Voice Assistant as a voice interaction. In such 9371 * case, a receiving activity that supports {@link android.content.Intent#CATEGORY_VOICE} 9372 * could check return value of {@link android.app.Activity#isVoiceInteractionRoot} before 9373 * proceeding. By doing this check the activity verifies that the action indeed was 9374 * initiated by Voice Assistant and could send a message right away, without any further 9375 * input from the user. This allows for a smooth user experience when sending a message by 9376 * voice. Note: this activity must also support the {@link 9377 * android.content.Intent#CATEGORY_DEFAULT} so it can be found by {@link 9378 * android.service.voice.VoiceInteractionSession#startVoiceActivity}. 9379 * <p> 9380 * When the action was not initiated by Voice Assistant or when the receiving activity does 9381 * not support {@link android.content.Intent#CATEGORY_VOICE}, the activity must confirm 9382 * with the user before sending the message (because in this case it is unknown which app 9383 * sent the intent, it could be malicious). 9384 * <p> 9385 * To allow the Voice Assistant to help users with contacts disambiguation, the messaging 9386 * app may choose to integrate with the Contacts Provider. You will need to specify a new 9387 * MIME type in order to store your app’s unique contact IDs and optional human readable 9388 * labels in the Data table. The Voice Assistant needs to know this MIME type and {@link 9389 * RawContacts#ACCOUNT_TYPE} that you are using in order to provide the smooth contact 9390 * disambiguation user experience. The following convention should be met when performing 9391 * such integration: 9392 * <ul> 9393 * <li>This activity should have a string meta-data field associated with it, {@link 9394 * #METADATA_ACCOUNT_TYPE}, which defines {@link RawContacts#ACCOUNT_TYPE} for your Contacts 9395 * Provider implementation. The account type should be globally unique, for example you can 9396 * use your app package name as the account type.</li> 9397 * <li>This activity should have a string meta-data field associated with it, {@link 9398 * #METADATA_MIMETYPE}, which defines {@link DataColumns#MIMETYPE} for your Contacts 9399 * Provider implementation. For example, you can use 9400 * "vnd.android.cursor.item/vnd.{$app_package_name}.profile" as MIME type.</li> 9401 * <li>When filling Data table row for METADATA_MIMETYPE, column {@link DataColumns#DATA1} 9402 * should store the unique contact ID as understood by the app. This value will be used in 9403 * the {@link #EXTRA_RECIPIENT_CONTACT_CHAT_ID}.</li> 9404 * <li>Optionally, when filling Data table row for METADATA_MIMETYPE, column {@link 9405 * DataColumns#DATA3} could store a human readable label for the ID. For example it could be 9406 * phone number or human readable username/user_id like "a_super_cool_user_name". This label 9407 * may be shown below the Contact Name by the Voice Assistant as the user completes the 9408 * voice action. If DATA3 is empty, the ID in DATA1 may be shown instead.</li> 9409 * <li><em>Note: Do not use DATA3 to store the Contact Name. The Voice Assistant will 9410 * already get the Contact Name from the RawContact’s display_name.</em></li> 9411 * <li><em>Note: Some apps may choose to use phone number as the unique contact ID in DATA1. 9412 * If this applies to you and you’d like phone number to be shown below the Contact Name by 9413 * the Voice Assistant, then you may choose to leave DATA3 empty.</em></li> 9414 * <li><em>Note: If your app also uses DATA3 to display contact details in the Contacts App, 9415 * make sure it does not include prefix text such as "Message +<phone>" or "Free Message 9416 * +<phone>", etc. If you must show the prefix text in the Contacts App, please use a 9417 * different DATA# column, and update your contacts.xml to point to this new column. </em> 9418 * </li> 9419 * </ul> 9420 * If the app chooses not to integrate with the Contacts Provider (in particular, when 9421 * either METADATA_ACCOUNT_TYPE or METADATA_MIMETYPE field is missing), Voice Assistant 9422 * will use existing phone number entries as contact ID's for such app. 9423 * <p> 9424 * Input: {@link android.content.Intent#getType} is the MIME type of the data being sent. 9425 * The intent sender will always put the concrete mime type in the intent type, like 9426 * "text/plain" or "audio/wav" for example. If the MIME type is "text/plain", message to 9427 * sent will be provided via {@link android.content.Intent#EXTRA_TEXT} as a styled 9428 * CharSequence. Otherwise, the message content will be supplied through {@link 9429 * android.content.Intent#setClipData(ClipData)} as a content provider URI(s). In the latter 9430 * case, EXTRA_TEXT could still be supplied optionally; for example, for audio messages 9431 * ClipData will contain URI of a recording and EXTRA_TEXT could contain the text 9432 * transcription of this recording. 9433 * <p> 9434 * The message can have n recipients. The n-th recipient of the message will be provided as 9435 * n-th elements of {@link #EXTRA_RECIPIENT_CONTACT_URI}, {@link 9436 * #EXTRA_RECIPIENT_CONTACT_CHAT_ID} and {@link #EXTRA_RECIPIENT_CONTACT_NAME} (as a 9437 * consequence, EXTRA_RECIPIENT_CONTACT_URI, EXTRA_RECIPIENT_CONTACT_CHAT_ID and 9438 * EXTRA_RECIPIENT_CONTACT_NAME should all be of length n). If neither of these 3 elements 9439 * is provided (e.g. all 3 are null) for the recipient or if the information provided is 9440 * ambiguous then the activity should prompt the user for the recipient to send the message 9441 * to. 9442 * <p> 9443 * Output: nothing 9444 * 9445 * @see #EXTRA_RECIPIENT_CONTACT_URI 9446 * @see #EXTRA_RECIPIENT_CONTACT_CHAT_ID 9447 * @see #EXTRA_RECIPIENT_CONTACT_NAME 9448 * @see #METADATA_ACCOUNT_TYPE 9449 * @see #METADATA_MIMETYPE 9450 */ 9451 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 9452 public static final String ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS = 9453 "android.provider.action.VOICE_SEND_MESSAGE_TO_CONTACTS"; 9454 9455 /** 9456 * This extra specifies a content provider uri(s) for the contact(s) (if the contacts were 9457 * located in the Contacts Provider), used with {@link 9458 * #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS} to supply the recipient(s). The value of this 9459 * extra is a {@code String[]}. The number of elements in the array should be equal to 9460 * number of recipients (and consistent with {@link #EXTRA_RECIPIENT_CONTACT_CHAT_ID} and 9461 * {@link #EXTRA_RECIPIENT_CONTACT_NAME}). When the value of the element for the particular 9462 * recipient is absent, it will be set to null. 9463 * <p> 9464 * <em>Note: one contact may have multiple accounts (e.g. Chat IDs) on a specific messaging 9465 * platform, so this may be ambiguous. E.g., one contact “John Smith” could have two 9466 * accounts on the same messaging app.</em> 9467 * <p> 9468 * <em>Example value: {"content://com.android.contacts/contacts/16"}</em> 9469 */ 9470 public static final String EXTRA_RECIPIENT_CONTACT_URI = 9471 "android.provider.extra.RECIPIENT_CONTACT_URI"; 9472 9473 /** 9474 * This extra specifies a messaging app’s unique ID(s) for the contact(s), used with {@link 9475 * #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS} to supply the recipient(s). The value of this 9476 * extra is a {@code String[]}. The number of elements in the array should be equal to 9477 * number of recipients (and consistent with {@link #EXTRA_RECIPIENT_CONTACT_URI} and {@link 9478 * #EXTRA_RECIPIENT_CONTACT_NAME}). When the value of the element for the particular 9479 * recipient is absent, it will be set to null. 9480 * <p> 9481 * The value of the elements comes from the {@link DataColumns#DATA1} column in Contacts 9482 * Provider with {@link DataColumns#MIMETYPE} from {@link #METADATA_MIMETYPE} (if both 9483 * {@link #METADATA_ACCOUNT_TYPE} and {@link #METADATA_MIMETYPE} are specified by the app; 9484 * otherwise, the value will be a phone number), and should be the unambiguous contact 9485 * endpoint. This value is app-specific, it could be some proprietary ID or a phone number. 9486 */ 9487 public static final String EXTRA_RECIPIENT_CONTACT_CHAT_ID = 9488 "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID"; 9489 9490 /** 9491 * This extra specifies the contact name (full name from the Contacts Provider), used with 9492 * {@link #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS} to supply the recipient. The value of this 9493 * extra is a {@code String[]}. The number of elements in the array should be equal to 9494 * number of recipients (and consistent with {@link #EXTRA_RECIPIENT_CONTACT_URI} and {@link 9495 * #EXTRA_RECIPIENT_CONTACT_CHAT_ID}). When the value of the element for the particular 9496 * recipient is absent, it will be set to null. 9497 * <p> 9498 * The value of the elements comes from RawContact's display_name column. 9499 * <p> 9500 * <em>Example value: {"Jane Doe"}</em> 9501 */ 9502 public static final String EXTRA_RECIPIENT_CONTACT_NAME = 9503 "android.provider.extra.RECIPIENT_CONTACT_NAME"; 9504 9505 /** 9506 * A string associated with an {@link #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS} activity 9507 * describing {@link RawContacts#ACCOUNT_TYPE} for the corresponding Contacts Provider 9508 * implementation. 9509 */ 9510 public static final String METADATA_ACCOUNT_TYPE = "android.provider.account_type"; 9511 9512 /** 9513 * A string associated with an {@link #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS} activity 9514 * describing {@link DataColumns#MIMETYPE} for the corresponding Contacts Provider 9515 * implementation. 9516 */ 9517 public static final String METADATA_MIMETYPE = "android.provider.mimetype"; 9518 9519 /** 9520 * Starts an Activity that lets the user select the multiple phones from a 9521 * list of phone numbers which come from the contacts or 9522 * {@link #EXTRA_PHONE_URIS}. 9523 * <p> 9524 * The phone numbers being passed in through {@link #EXTRA_PHONE_URIS} 9525 * could belong to the contacts or not, and will be selected by default. 9526 * <p> 9527 * The user's selection will be returned from 9528 * {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)} 9529 * if the resultCode is 9530 * {@link android.app.Activity#RESULT_OK}, the array of picked phone 9531 * numbers are in the Intent's 9532 * {@link #EXTRA_PHONE_URIS}; otherwise, the 9533 * {@link android.app.Activity#RESULT_CANCELED} is returned if the user 9534 * left the Activity without changing the selection. 9535 * 9536 * @hide 9537 */ 9538 public static final String ACTION_GET_MULTIPLE_PHONES = 9539 "com.android.contacts.action.GET_MULTIPLE_PHONES"; 9540 9541 /** 9542 * A broadcast action which is sent when any change has been made to the profile, such 9543 * as the profile name or the picture. A receiver must have 9544 * the android.permission.READ_PROFILE permission. 9545 * 9546 * @hide 9547 */ 9548 public static final String ACTION_PROFILE_CHANGED = 9549 "android.provider.Contacts.PROFILE_CHANGED"; 9550 9551 /** 9552 * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new 9553 * contact if no matching contact found. Otherwise, default behavior is 9554 * to prompt user with dialog before creating. 9555 * <p> 9556 * Type: BOOLEAN 9557 */ 9558 public static final String EXTRA_FORCE_CREATE = 9559 "com.android.contacts.action.FORCE_CREATE"; 9560 9561 /** 9562 * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact 9563 * description to be shown when prompting user about creating a new 9564 * contact. 9565 * <p> 9566 * Type: STRING 9567 */ 9568 public static final String EXTRA_CREATE_DESCRIPTION = 9569 "com.android.contacts.action.CREATE_DESCRIPTION"; 9570 9571 /** 9572 * Used with {@link #ACTION_GET_MULTIPLE_PHONES} as the input or output value. 9573 * <p> 9574 * The phone numbers want to be picked by default should be passed in as 9575 * input value. These phone numbers could belong to the contacts or not. 9576 * <p> 9577 * The phone numbers which were picked by the user are returned as output 9578 * value. 9579 * <p> 9580 * Type: array of URIs, the tel URI is used for the phone numbers which don't 9581 * belong to any contact, the content URI is used for phone id in contacts. 9582 * 9583 * @hide 9584 */ 9585 public static final String EXTRA_PHONE_URIS = 9586 "com.android.contacts.extra.PHONE_URIS"; 9587 9588 /** 9589 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a 9590 * dialog location using screen coordinates. When not specified, the 9591 * dialog will be centered. 9592 * 9593 * @hide 9594 */ 9595 @Deprecated 9596 public static final String EXTRA_TARGET_RECT = "target_rect"; 9597 9598 /** 9599 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a 9600 * desired dialog style, usually a variation on size. One of 9601 * {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}. 9602 * 9603 * @hide 9604 */ 9605 @Deprecated 9606 public static final String EXTRA_MODE = "mode"; 9607 9608 /** 9609 * Value for {@link #EXTRA_MODE} to show a small-sized dialog. 9610 * 9611 * @hide 9612 */ 9613 @Deprecated 9614 public static final int MODE_SMALL = 1; 9615 9616 /** 9617 * Value for {@link #EXTRA_MODE} to show a medium-sized dialog. 9618 * 9619 * @hide 9620 */ 9621 @Deprecated 9622 public static final int MODE_MEDIUM = 2; 9623 9624 /** 9625 * Value for {@link #EXTRA_MODE} to show a large-sized dialog. 9626 * 9627 * @hide 9628 */ 9629 @Deprecated 9630 public static final int MODE_LARGE = 3; 9631 9632 /** 9633 * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to indicate 9634 * a list of specific MIME-types to exclude and not display. Stored as a 9635 * {@link String} array. 9636 * 9637 * @hide 9638 */ 9639 @Deprecated 9640 public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes"; 9641 9642 /** 9643 * Convenience class that contains string constants used 9644 * to create contact {@link android.content.Intent Intents}. 9645 */ 9646 public static final class Insert { 9647 /** The action code to use when adding a contact */ 9648 public static final String ACTION = Intent.ACTION_INSERT; 9649 9650 /** 9651 * If present, forces a bypass of quick insert mode. 9652 */ 9653 public static final String FULL_MODE = "full_mode"; 9654 9655 /** 9656 * The extra field for the contact name. 9657 * <P>Type: String</P> 9658 */ 9659 public static final String NAME = "name"; 9660 9661 // TODO add structured name values here. 9662 9663 /** 9664 * The extra field for the contact phonetic name. 9665 * <P>Type: String</P> 9666 */ 9667 public static final String PHONETIC_NAME = "phonetic_name"; 9668 9669 /** 9670 * The extra field for the contact company. 9671 * <P>Type: String</P> 9672 */ 9673 public static final String COMPANY = "company"; 9674 9675 /** 9676 * The extra field for the contact job title. 9677 * <P>Type: String</P> 9678 */ 9679 public static final String JOB_TITLE = "job_title"; 9680 9681 /** 9682 * The extra field for the contact notes. 9683 * <P>Type: String</P> 9684 */ 9685 public static final String NOTES = "notes"; 9686 9687 /** 9688 * The extra field for the contact phone number. 9689 * <P>Type: String</P> 9690 */ 9691 public static final String PHONE = "phone"; 9692 9693 /** 9694 * The extra field for the contact phone number type. 9695 * <P>Type: Either an integer value from 9696 * {@link CommonDataKinds.Phone}, 9697 * or a string specifying a custom label.</P> 9698 */ 9699 public static final String PHONE_TYPE = "phone_type"; 9700 9701 /** 9702 * The extra field for the phone isprimary flag. 9703 * <P>Type: boolean</P> 9704 */ 9705 public static final String PHONE_ISPRIMARY = "phone_isprimary"; 9706 9707 /** 9708 * The extra field for an optional second contact phone number. 9709 * <P>Type: String</P> 9710 */ 9711 public static final String SECONDARY_PHONE = "secondary_phone"; 9712 9713 /** 9714 * The extra field for an optional second contact phone number type. 9715 * <P>Type: Either an integer value from 9716 * {@link CommonDataKinds.Phone}, 9717 * or a string specifying a custom label.</P> 9718 */ 9719 public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type"; 9720 9721 /** 9722 * The extra field for an optional third contact phone number. 9723 * <P>Type: String</P> 9724 */ 9725 public static final String TERTIARY_PHONE = "tertiary_phone"; 9726 9727 /** 9728 * The extra field for an optional third contact phone number type. 9729 * <P>Type: Either an integer value from 9730 * {@link CommonDataKinds.Phone}, 9731 * or a string specifying a custom label.</P> 9732 */ 9733 public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type"; 9734 9735 /** 9736 * The extra field for the contact email address. 9737 * <P>Type: String</P> 9738 */ 9739 public static final String EMAIL = "email"; 9740 9741 /** 9742 * The extra field for the contact email type. 9743 * <P>Type: Either an integer value from 9744 * {@link CommonDataKinds.Email} 9745 * or a string specifying a custom label.</P> 9746 */ 9747 public static final String EMAIL_TYPE = "email_type"; 9748 9749 /** 9750 * The extra field for the email isprimary flag. 9751 * <P>Type: boolean</P> 9752 */ 9753 public static final String EMAIL_ISPRIMARY = "email_isprimary"; 9754 9755 /** 9756 * The extra field for an optional second contact email address. 9757 * <P>Type: String</P> 9758 */ 9759 public static final String SECONDARY_EMAIL = "secondary_email"; 9760 9761 /** 9762 * The extra field for an optional second contact email type. 9763 * <P>Type: Either an integer value from 9764 * {@link CommonDataKinds.Email} 9765 * or a string specifying a custom label.</P> 9766 */ 9767 public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type"; 9768 9769 /** 9770 * The extra field for an optional third contact email address. 9771 * <P>Type: String</P> 9772 */ 9773 public static final String TERTIARY_EMAIL = "tertiary_email"; 9774 9775 /** 9776 * The extra field for an optional third contact email type. 9777 * <P>Type: Either an integer value from 9778 * {@link CommonDataKinds.Email} 9779 * or a string specifying a custom label.</P> 9780 */ 9781 public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type"; 9782 9783 /** 9784 * The extra field for the contact postal address. 9785 * <P>Type: String</P> 9786 */ 9787 public static final String POSTAL = "postal"; 9788 9789 /** 9790 * The extra field for the contact postal address type. 9791 * <P>Type: Either an integer value from 9792 * {@link CommonDataKinds.StructuredPostal} 9793 * or a string specifying a custom label.</P> 9794 */ 9795 public static final String POSTAL_TYPE = "postal_type"; 9796 9797 /** 9798 * The extra field for the postal isprimary flag. 9799 * <P>Type: boolean</P> 9800 */ 9801 public static final String POSTAL_ISPRIMARY = "postal_isprimary"; 9802 9803 /** 9804 * The extra field for an IM handle. 9805 * <P>Type: String</P> 9806 */ 9807 public static final String IM_HANDLE = "im_handle"; 9808 9809 /** 9810 * The extra field for the IM protocol 9811 */ 9812 public static final String IM_PROTOCOL = "im_protocol"; 9813 9814 /** 9815 * The extra field for the IM isprimary flag. 9816 * <P>Type: boolean</P> 9817 */ 9818 public static final String IM_ISPRIMARY = "im_isprimary"; 9819 9820 /** 9821 * The extra field that allows the client to supply multiple rows of 9822 * arbitrary data for a single contact created using the {@link Intent#ACTION_INSERT} 9823 * or edited using {@link Intent#ACTION_EDIT}. It is an ArrayList of 9824 * {@link ContentValues}, one per data row. Supplying this extra is 9825 * similar to inserting multiple rows into the {@link Data} table, 9826 * except the user gets a chance to see and edit them before saving. 9827 * Each ContentValues object must have a value for {@link Data#MIMETYPE}. 9828 * If supplied values are not visible in the editor UI, they will be 9829 * dropped. Duplicate data will dropped. Some fields 9830 * like {@link CommonDataKinds.Email#TYPE Email.TYPE} may be automatically 9831 * adjusted to comply with the constraints of the specific account type. 9832 * For example, an Exchange contact can only have one phone numbers of type Home, 9833 * so the contact editor may choose a different type for this phone number to 9834 * avoid dropping the valueable part of the row, which is the phone number. 9835 * <p> 9836 * Example: 9837 * <pre> 9838 * ArrayList<ContentValues> data = new ArrayList<ContentValues>(); 9839 * 9840 * ContentValues row1 = new ContentValues(); 9841 * row1.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); 9842 * row1.put(Organization.COMPANY, "Android"); 9843 * data.add(row1); 9844 * 9845 * ContentValues row2 = new ContentValues(); 9846 * row2.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 9847 * row2.put(Email.TYPE, Email.TYPE_CUSTOM); 9848 * row2.put(Email.LABEL, "Green Bot"); 9849 * row2.put(Email.ADDRESS, "android@android.com"); 9850 * data.add(row2); 9851 * 9852 * Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); 9853 * intent.putParcelableArrayListExtra(Insert.DATA, data); 9854 * 9855 * startActivity(intent); 9856 * </pre> 9857 */ 9858 public static final String DATA = "data"; 9859 9860 /** 9861 * Used to specify the account in which to create the new contact. 9862 * <p> 9863 * If this value is not provided, the user is presented with a disambiguation 9864 * dialog to chose an account 9865 * <p> 9866 * Type: {@link Account} 9867 */ 9868 public static final String EXTRA_ACCOUNT = "android.provider.extra.ACCOUNT"; 9869 9870 /** 9871 * Used to specify the data set within the account in which to create the 9872 * new contact. 9873 * <p> 9874 * This value is optional - if it is not specified, the contact will be 9875 * created in the base account, with no data set. 9876 * <p> 9877 * Type: String 9878 */ 9879 public static final String EXTRA_DATA_SET = "android.provider.extra.DATA_SET"; 9880 } 9881 } 9882 9883 /** 9884 * @hide 9885 * @deprecated These columns were never public since added. They will not be supported 9886 * as of Android version {@link android.os.Build.VERSION_CODES#R}. 9887 */ 9888 @Deprecated 9889 @SystemApi 9890 protected interface MetadataSyncColumns { 9891 9892 /** 9893 * The raw contact backup id. 9894 * A reference to the {@link ContactsContract.RawContacts#BACKUP_ID} that save the 9895 * persistent unique id for each raw contact within its source system. 9896 */ 9897 public static final String RAW_CONTACT_BACKUP_ID = "raw_contact_backup_id"; 9898 9899 /** 9900 * The account type to which the raw_contact of this item is associated. See 9901 * {@link RawContacts#ACCOUNT_TYPE} 9902 */ 9903 public static final String ACCOUNT_TYPE = "account_type"; 9904 9905 /** 9906 * The account name to which the raw_contact of this item is associated. See 9907 * {@link RawContacts#ACCOUNT_NAME} 9908 */ 9909 public static final String ACCOUNT_NAME = "account_name"; 9910 9911 /** 9912 * The data set within the account that the raw_contact of this row belongs to. This allows 9913 * multiple sync adapters for the same account type to distinguish between 9914 * each others' data. 9915 * {@link RawContacts#DATA_SET} 9916 */ 9917 public static final String DATA_SET = "data_set"; 9918 9919 /** 9920 * A text column contains the Json string got from People API. The Json string contains 9921 * all the metadata related to the raw contact, i.e., all the data fields and 9922 * aggregation exceptions. 9923 * 9924 * Here is an example of the Json string got from the actual schema. 9925 * <pre> 9926 * { 9927 * "unique_contact_id": { 9928 * "account_type": "CUSTOM_ACCOUNT", 9929 * "custom_account_type": "facebook", 9930 * "account_name": "android-test", 9931 * "contact_id": "1111111", 9932 * "data_set": "FOCUS" 9933 * }, 9934 * "contact_prefs": { 9935 * "send_to_voicemail": true, 9936 * "starred": false, 9937 * "pinned": 2 9938 * }, 9939 * "aggregation_data": [ 9940 * { 9941 * "type": "TOGETHER", 9942 * "contact_ids": [ 9943 * { 9944 * "account_type": "GOOGLE_ACCOUNT", 9945 * "account_name": "android-test2", 9946 * "contact_id": "2222222", 9947 * "data_set": "GOOGLE_PLUS" 9948 * }, 9949 * { 9950 * "account_type": "GOOGLE_ACCOUNT", 9951 * "account_name": "android-test3", 9952 * "contact_id": "3333333", 9953 * "data_set": "CUSTOM", 9954 * "custom_data_set": "custom type" 9955 * } 9956 * ] 9957 * } 9958 * ], 9959 * "field_data": [ 9960 * { 9961 * "field_data_id": "1001", 9962 * "field_data_prefs": { 9963 * "is_primary": true, 9964 * "is_super_primary": true 9965 * }, 9966 * "usage_stats": [ 9967 * { 9968 * "usage_type": "CALL", 9969 * "last_time_used": 10000001, 9970 * "usage_count": 10 9971 * } 9972 * ] 9973 * } 9974 * ] 9975 * } 9976 * </pre> 9977 */ 9978 public static final String DATA = "data"; 9979 9980 /** 9981 * The "deleted" flag: "0" by default, "1" if the row has been marked 9982 * for deletion. When {@link android.content.ContentResolver#delete} is 9983 * called on a raw contact, updating MetadataSync table to set the flag of the raw contact 9984 * as "1", then metadata sync adapter deletes the raw contact metadata on the server. 9985 * <P>Type: INTEGER</P> 9986 */ 9987 public static final String DELETED = "deleted"; 9988 } 9989 9990 /** 9991 * Constants for the metadata sync table. This table is used to cache the metadata_sync data 9992 * from server before it is merged into other CP2 tables. 9993 * 9994 * @hide 9995 * @deprecated These columns were never public since added. They will not be supported 9996 * as of Android version {@link android.os.Build.VERSION_CODES#R}. 9997 */ 9998 @Deprecated 9999 @SystemApi 10000 public static final class MetadataSync implements BaseColumns, MetadataSyncColumns { 10001 10002 /** The authority for the contacts metadata */ 10003 public static final String METADATA_AUTHORITY = "com.android.contacts.metadata"; 10004 10005 /** A content:// style uri to the authority for the contacts metadata */ 10006 public static final Uri METADATA_AUTHORITY_URI = Uri.parse( 10007 "content://" + METADATA_AUTHORITY); 10008 10009 /** 10010 * This utility class cannot be instantiated 10011 */ MetadataSync()10012 private MetadataSync() { 10013 } 10014 10015 /** 10016 * The content:// style URI for this table. 10017 */ 10018 public static final Uri CONTENT_URI = Uri.withAppendedPath(METADATA_AUTHORITY_URI, 10019 "metadata_sync"); 10020 10021 /** 10022 * The MIME type of {@link #CONTENT_URI} providing a directory of contact metadata 10023 */ 10024 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata"; 10025 10026 /** 10027 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single contact metadata. 10028 */ 10029 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata"; 10030 } 10031 10032 /** 10033 * @hide 10034 * @deprecated These columns are no longer supported as of Android version 10035 * {@link android.os.Build.VERSION_CODES#R}. 10036 */ 10037 @Deprecated 10038 @SystemApi 10039 protected interface MetadataSyncStateColumns { 10040 10041 /** 10042 * A reference to the name of the account to which this state belongs 10043 * <P>Type: STRING</P> 10044 */ 10045 public static final String ACCOUNT_TYPE = "account_type"; 10046 10047 /** 10048 * A reference to the type of the account to which this state belongs 10049 * <P>Type: STRING</P> 10050 */ 10051 public static final String ACCOUNT_NAME = "account_name"; 10052 10053 /** 10054 * A reference to the data set within the account to which this state belongs 10055 * <P>Type: STRING</P> 10056 */ 10057 public static final String DATA_SET = "data_set"; 10058 10059 /** 10060 * The sync state associated with this account. 10061 * <P>Type: Blob</P> 10062 */ 10063 public static final String STATE = "state"; 10064 } 10065 10066 /** 10067 * Constants for the metadata_sync_state table. This table is used to store the metadata 10068 * sync state for a set of accounts. 10069 * 10070 * @hide 10071 * @deprecated These columns are no longer supported as of Android version 10072 * {@link android.os.Build.VERSION_CODES#R}. 10073 */ 10074 @Deprecated 10075 @SystemApi 10076 public static final class MetadataSyncState implements BaseColumns, MetadataSyncStateColumns { 10077 10078 /** 10079 * This utility class cannot be instantiated 10080 */ MetadataSyncState()10081 private MetadataSyncState() { 10082 } 10083 10084 /** 10085 * The content:// style URI for this table. 10086 */ 10087 public static final Uri CONTENT_URI = 10088 Uri.withAppendedPath(MetadataSync.METADATA_AUTHORITY_URI, "metadata_sync_state"); 10089 10090 /** 10091 * The MIME type of {@link #CONTENT_URI} providing a directory of contact metadata sync 10092 * states. 10093 */ 10094 public static final String CONTENT_TYPE = 10095 "vnd.android.cursor.dir/contact_metadata_sync_state"; 10096 10097 /** 10098 * The MIME type of a {@link #CONTENT_URI} subdirectory of a single contact metadata sync 10099 * state. 10100 */ 10101 public static final String CONTENT_ITEM_TYPE = 10102 "vnd.android.cursor.item/contact_metadata_sync_state"; 10103 } 10104 } 10105