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