diff options
Diffstat (limited to 'core/java/android/provider')
-rw-r--r-- | core/java/android/provider/Browser.java | 69 | ||||
-rw-r--r-- | core/java/android/provider/Calendar.java | 82 | ||||
-rw-r--r-- | core/java/android/provider/CallLog.java | 10 | ||||
-rw-r--r-- | core/java/android/provider/Checkin.java | 2 | ||||
-rw-r--r-- | core/java/android/provider/Contacts.java | 820 | ||||
-rw-r--r-- | core/java/android/provider/ContactsContract.java | 2722 | ||||
-rw-r--r-- | core/java/android/provider/DrmStore.java | 66 | ||||
-rw-r--r-- | core/java/android/provider/Gmail.java | 20 | ||||
-rw-r--r-- | core/java/android/provider/Im.java | 648 | ||||
-rw-r--r-- | core/java/android/provider/LiveFolders.java | 3 | ||||
-rw-r--r-- | core/java/android/provider/MediaStore.java | 347 | ||||
-rw-r--r-- | core/java/android/provider/Settings.java | 486 | ||||
-rw-r--r-- | core/java/android/provider/SocialContract.java | 187 | ||||
-rw-r--r-- | core/java/android/provider/SubscribedFeeds.java | 31 | ||||
-rw-r--r-- | core/java/android/provider/SyncConstValue.java | 11 | ||||
-rw-r--r-- | core/java/android/provider/SyncStateContract.java | 176 | ||||
-rw-r--r-- | core/java/android/provider/Telephony.java | 87 |
17 files changed, 5289 insertions, 478 deletions
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java index 1ba5e25..c8b7f99 100644 --- a/core/java/android/provider/Browser.java +++ b/core/java/android/provider/Browser.java @@ -107,7 +107,8 @@ public class Browser { public static final String[] HISTORY_PROJECTION = new String[] { BookmarkColumns._ID, BookmarkColumns.URL, BookmarkColumns.VISITS, BookmarkColumns.DATE, BookmarkColumns.BOOKMARK, BookmarkColumns.TITLE, - BookmarkColumns.FAVICON }; + BookmarkColumns.FAVICON, BookmarkColumns.THUMBNAIL, + BookmarkColumns.TOUCH_ICON }; /* these indices dependent on HISTORY_PROJECTION */ public static final int HISTORY_PROJECTION_ID_INDEX = 0; @@ -117,6 +118,14 @@ public class Browser { public static final int HISTORY_PROJECTION_BOOKMARK_INDEX = 4; public static final int HISTORY_PROJECTION_TITLE_INDEX = 5; public static final int HISTORY_PROJECTION_FAVICON_INDEX = 6; + /** + * @hide + */ + public static final int HISTORY_PROJECTION_THUMBNAIL_INDEX = 7; + /** + * @hide + */ + public static final int HISTORY_PROJECTION_TOUCH_ICON_INDEX = 8; /* columns needed to determine whether to truncate history */ public static final String[] TRUNCATE_HISTORY_PROJECTION = new String[] { @@ -165,13 +174,29 @@ public class Browser { } public static final void sendString(Context c, String s) { + sendString(c, s, + c.getText(com.android.internal.R.string.sendText).toString()); + } + + /** + * Find an application to handle the given string and, if found, invoke + * it with the given string as a parameter. + * @param c Context used to launch the new activity. + * @param stringToSend The string to be handled. + * @param chooserDialogTitle The title of the dialog that allows the user + * to select between multiple applications that are all capable of handling + * the string. + * @hide pending API council approval + */ + public static final void sendString(Context c, + String stringToSend, + String chooserDialogTitle) { Intent send = new Intent(Intent.ACTION_SEND); send.setType("text/plain"); - send.putExtra(Intent.EXTRA_TEXT, s); - + send.putExtra(Intent.EXTRA_TEXT, stringToSend); + try { - c.startActivity(Intent.createChooser(send, - c.getText(com.android.internal.R.string.sendText))); + c.startActivity(Intent.createChooser(send, chooserDialogTitle)); } catch(android.content.ActivityNotFoundException ex) { // if no app handles it, do nothing } @@ -249,6 +274,32 @@ public class Browser { } /** + * Returns all the URLs in the history. + * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS} + * @param cr The ContentResolver used to access the database. + * @hide pending API council approval + */ + public static final String[] getVisitedHistory(ContentResolver cr) { + try { + String[] projection = new String[] { + "url" + }; + Cursor c = cr.query(BOOKMARKS_URI, projection, "visits > 0", null, + null); + String[] str = new String[c.getCount()]; + int i = 0; + while (c.moveToNext()) { + str[i] = c.getString(0); + i++; + } + c.deactivate(); + return str; + } catch (IllegalStateException e) { + return new String[0]; + } + } + + /** * If there are more than MAX_HISTORY_COUNT non-bookmark history * items in the bookmark/history table, delete TRUNCATE_N_OLDEST * of them. This is used to keep our history table to a @@ -513,6 +564,14 @@ public class Browser { public static final String TITLE = "title"; public static final String CREATED = "created"; public static final String FAVICON = "favicon"; + /** + * @hide + */ + public static final String THUMBNAIL = "thumbnail"; + /** + * @hide + */ + public static final String TOUCH_ICON = "touch_icon"; } public static class SearchColumns implements BaseColumns { diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java index 4a709f6..f046cef 100644 --- a/core/java/android/provider/Calendar.java +++ b/core/java/android/provider/Calendar.java @@ -32,6 +32,7 @@ import android.text.format.DateUtils; import android.text.format.Time; import android.util.Config; import android.util.Log; +import android.accounts.Account; import com.android.internal.database.ArrayListCursor; import com.google.android.gdata.client.AndroidGDataClient; import com.google.android.gdata.client.AndroidXmlParserFactory; @@ -80,6 +81,11 @@ public final class Calendar { public interface CalendarsColumns { /** + * A string that uniquely identifies this contact to its source + */ + public static final String SOURCE_ID = "sourceid"; + + /** * The color of the calendar * <P>Type: INTEGER (color value)</P> */ @@ -104,6 +110,7 @@ public final class Calendar { public static final int EDITOR_ACCESS = 600; /** Full access to the calendar */ public static final int OWNER_ACCESS = 700; + /** Domain admin */ public static final int ROOT_ACCESS = 800; /** @@ -124,6 +131,12 @@ public final class Calendar { * <p>Type: INTEGER (boolean)</p> */ public static final String SYNC_EVENTS = "sync_events"; + + /** + * Sync state data. + * <p>Type: String (blob)</p> + */ + public static final String SYNC_STATE = "sync_state"; } /** @@ -157,11 +170,12 @@ public final class Calendar { * @param account the account whose rows should be deleted * @return the count of rows that were deleted */ - public static int deleteCalendarsForAccount(ContentResolver cr, - String account) { + public static int deleteCalendarsForAccount(ContentResolver cr, Account account) { // delete all calendars that match this account - return Calendar.Calendars.delete(cr, Calendar.Calendars._SYNC_ACCOUNT + "=?", - new String[] {account}); + return Calendar.Calendars.delete(cr, + Calendar.Calendars._SYNC_ACCOUNT + "=? AND " + + Calendar.Calendars._SYNC_ACCOUNT_TYPE + "=?", + new String[] {account.name, account.type}); } /** @@ -170,9 +184,6 @@ public final class Calendar { public static final Uri CONTENT_URI = Uri.parse("content://calendar/calendars"); - public static final Uri LIVE_CONTENT_URI = - Uri.parse("content://calendar/calendars?update=1"); - /** * The default sort order for this table */ @@ -207,6 +218,13 @@ public final class Calendar { * <P>Type: INTEGER (boolean)</P> */ public static final String HIDDEN = "hidden"; + + /** + * The owner account for this calendar, based on the calendar feed. + * This will be different from the _SYNC_ACCOUNT for delegated calendars. + * <P>Type: String</P> + */ + public static final String OWNER_ACCOUNT = "ownerAccount"; } public interface AttendeesColumns { @@ -448,6 +466,54 @@ public final class Calendar { * <P>Type: INTEGER (long; millis since epoch)</P> */ public static final String LAST_DATE = "lastDate"; + + /** + * Whether the event has attendee information. True if the event + * has full attendee data, false if the event has information about + * self only. + * <P>Type: INTEGER (boolean)</P> + */ + public static final String HAS_ATTENDEE_DATA = "hasAttendeeData"; + + /** + * Whether guests can modify the event. + * <P>Type: INTEGER (boolean)</P> + */ + public static final String GUESTS_CAN_MODIFY = "guestsCanModify"; + + /** + * Whether guests can invite other guests. + * <P>Type: INTEGER (boolean)</P> + */ + public static final String GUESTS_CAN_INVITE_OTHERS = "guestsCanInviteOthers"; + + /** + * Whether guests can see the list of attendees. + * <P>Type: INTEGER (boolean)</P> + */ + public static final String GUESTS_CAN_SEE_GUESTS = "guestsCanSeeGuests"; + + /** + * Email of the organizer (owner) of the event. + * <P>Type: STRING</P> + */ + public static final String ORGANIZER = "organizer"; + + /** + * Whether the user can invite others to the event. + * The GUESTS_CAN_INVITE_OTHERS is a setting that applies to an arbitrary guest, + * while CAN_INVITE_OTHERS indicates if the user can invite others (either through + * GUESTS_CAN_INVITE_OTHERS or because the user has modify access to the event). + * <P>Type: INTEGER (boolean, readonly)</P> + */ + public static final String CAN_INVITE_OTHERS = "canInviteOthers"; + + /** + * The owner account for this calendar, based on the calendar (foreign + * key into the calendars table). + * <P>Type: String</P> + */ + public static final String OWNER_ACCOUNT = "ownerAccount"; } /** @@ -694,6 +760,8 @@ public final class Calendar { * The content:// style URL for this table */ public static final Uri CONTENT_URI = Uri.parse("content://calendar/instances/when"); + public static final Uri CONTENT_BY_DAY_URI = + Uri.parse("content://calendar/instances/whenbyday"); /** * The default sort order for this table. diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index b54ad5d..7854423 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -16,16 +16,14 @@ package android.provider; +import com.android.internal.telephony.CallerInfo; +import com.android.internal.telephony.Connection; + import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.net.Uri; -import android.provider.Contacts.People; -import com.android.internal.telephony.CallerInfo; -import com.android.internal.telephony.Connection; - import android.text.TextUtils; -import android.util.Log; /** * The CallLog provider contains information about placed and received calls. @@ -179,7 +177,7 @@ public class CallLog { } if ((ci != null) && (ci.person_id > 0)) { - People.markAsContacted(resolver, ci.person_id); + ContactsContract.Contacts.markAsContacted(resolver, ci.person_id); } Uri result = resolver.insert(CONTENT_URI, values); diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java index 6b491ab..84753ee 100644 --- a/core/java/android/provider/Checkin.java +++ b/core/java/android/provider/Checkin.java @@ -59,6 +59,8 @@ public final class Checkin { /** Valid tag values. Extend as necessary for your needs. */ public enum Tag { + APANIC_CONSOLE, + APANIC_THREADS, AUTOTEST_FAILURE, AUTOTEST_SEQUENCE_BEGIN, AUTOTEST_SUITE_BEGIN, diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java index 35463cf..1a38166 100644 --- a/core/java/android/provider/Contacts.java +++ b/core/java/android/provider/Contacts.java @@ -22,11 +22,11 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; -import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; +import android.os.Build; import android.text.TextUtils; import android.util.Log; import android.widget.ImageView; @@ -36,27 +36,58 @@ import java.io.InputStream; /** * The Contacts provider stores all information about contacts. + * + * @deprecated The APIs have been superseded by {@link ContactsContract}. The newer APIs allow + * access multiple accounts and support aggregation of similar contacts. These APIs continue to + * work but will only return data for the first Google account created, which matches the original + * behavior. */ +@Deprecated public class Contacts { private static final String TAG = "Contacts"; - + + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final String AUTHORITY = "contacts"; /** * The content:// style URL for this provider + * @deprecated see {@link android.provider.ContactsContract} */ - public static final Uri CONTENT_URI = - Uri.parse("content://" + AUTHORITY); + @Deprecated + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); - /** Signifies an email address row that is stored in the ContactMethods table */ + /** + * Signifies an email address row that is stored in the ContactMethods table + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int KIND_EMAIL = 1; - /** Signifies a postal address row that is stored in the ContactMethods table */ + /** + * Signifies a postal address row that is stored in the ContactMethods table + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int KIND_POSTAL = 2; - /** Signifies an IM address row that is stored in the ContactMethods table */ + /** + * Signifies an IM address row that is stored in the ContactMethods table + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int KIND_IM = 3; - /** Signifies an Organization row that is stored in the Organizations table */ + /** + * Signifies an Organization row that is stored in the Organizations table + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int KIND_ORGANIZATION = 4; - /** Signifies an Phone row that is stored in the Phones table */ + /** + * Signifies an Phone row that is stored in the Phones table + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int KIND_PHONE = 5; /** @@ -66,30 +97,48 @@ public class Contacts { /** * Columns from the Settings table that other columns join into themselves. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface SettingsColumns { /** * The _SYNC_ACCOUNT to which this setting corresponds. This may be null. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String _SYNC_ACCOUNT = "_sync_account"; /** + * The _SYNC_ACCOUNT_TYPE to which this setting corresponds. This may be null. + * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated + public static final String _SYNC_ACCOUNT_TYPE = "_sync_account_type"; + + /** * The key of this setting. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String KEY = "key"; /** * The value of this setting. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String VALUE = "value"; } /** * The settings over all of the people + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Settings implements BaseColumns, SettingsColumns { /** * no public constructor since this is a utility class @@ -98,18 +147,24 @@ public class Contacts { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/settings"); /** * The directory twig for this sub-table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_DIRECTORY = "settings"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "key ASC"; /** @@ -120,9 +175,15 @@ public class Contacts { * <p> * This is a boolean setting. It is true if it is set and it is anything other than the * emptry string or "0". + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SYNC_EVERYTHING = "syncEverything"; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static String getSetting(ContentResolver cr, String account, String key) { // For now we only support a single account and the UI doesn't know what // the account name is, so we're using a global setting for SYNC_EVERYTHING. @@ -134,6 +195,7 @@ public class Contacts { selectString = (account == null) ? "_sync_account is null AND key=?" : "_sync_account=? AND key=?"; +// : "_sync_account=? AND _sync_account_type=? AND key=?"; selectArgs = (account == null) ? new String[]{key} : new String[]{account, key}; @@ -151,6 +213,10 @@ public class Contacts { } } + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static void setSetting(ContentResolver cr, String account, String key, String value) { ContentValues values = new ContentValues(); @@ -158,7 +224,8 @@ public class Contacts { // the account name is, so we're using a global setting for SYNC_EVERYTHING. // Some day when we add multiple accounts to the UI this should honor the account // that was asked for. - //values.put(_SYNC_ACCOUNT, account); + //values.put(_SYNC_ACCOUNT, account.mName); + //values.put(_SYNC_ACCOUNT_TYPE, account.mType); values.put(KEY, key); values.put(VALUE, value); cr.update(Settings.CONTENT_URI, values, null, null); @@ -167,12 +234,16 @@ public class Contacts { /** * Columns from the People table that other tables join into themselves. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface PeopleColumns { /** * The person's name. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String NAME = "name"; /** @@ -180,14 +251,18 @@ public class Contacts { * character set (e.g. hiragana for Japanese). * Used for pronunciation and/or collation in some languages. * <p>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PHONETIC_NAME = "phonetic_name"; - + /** * The display name. If name is not null name, else if number is not null number, * else if email is not null email. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DISPLAY_NAME = "display_name"; /** @@ -195,80 +270,105 @@ public class Contacts { * may not be human readable but phonetically sortable. * <P>Type: TEXT</p> * @hide Used only in Contacts application for now. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SORT_STRING = "sort_string"; - + /** * Notes about the person. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String NOTES = "notes"; /** * The number of times a person has been contacted * <P>Type: INTEGER</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String TIMES_CONTACTED = "times_contacted"; /** * The last time a person was contacted. * <P>Type: INTEGER</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LAST_TIME_CONTACTED = "last_time_contacted"; /** * A custom ringtone associated with a person. Not always present. * <P>Type: TEXT (URI to the ringtone)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CUSTOM_RINGTONE = "custom_ringtone"; /** * Whether the person should always be sent to voicemail. Not always * present. * <P>Type: INTEGER (0 for false, 1 for true)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; /** * Is the contact starred? * <P>Type: INTEGER (boolean)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String STARRED = "starred"; /** * The server version of the photo * <P>Type: TEXT (the version number portion of the photo URI)</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String PHOTO_VERSION = "photo_version"; + @Deprecated + public static final String PHOTO_VERSION = "photo_version"; } /** * This table contains people. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class People implements BaseColumns, SyncConstValue, PeopleColumns, PhonesColumns, PresenceColumns { /** * no public constructor since this is a utility class + * @deprecated see {@link android.provider.ContactsContract} */ private People() {} /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/people"); /** * The content:// style URL for filtering people by name. The filter * argument should be passed as an additional path segment after this URI. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_FILTER_URI = Uri.parse("content://contacts/people/filter"); /** * The content:// style URL for the table that holds the deleted * contacts. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri DELETED_CONTENT_URI = Uri.parse("content://contacts/deleted_people"); @@ -278,49 +378,63 @@ public class Contacts { * additional path segment after this URI. This matches any people with * at least one E-mail or IM {@link ContactMethods} that match the * filter. - * + * * Not exposed because we expect significant changes in the contacts * schema and do not want to have to support this. * @hide + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri WITH_EMAIL_OR_IM_FILTER_URI = Uri.parse("content://contacts/people/with_email_or_im_filter"); - + /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * person. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = People.NAME + " ASC"; /** * The ID of the persons preferred phone number. * <P>Type: INTEGER (foreign key to phones table on the _ID field)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PRIMARY_PHONE_ID = "primary_phone"; /** * The ID of the persons preferred email. * <P>Type: INTEGER (foreign key to contact_methods table on the * _ID field)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PRIMARY_EMAIL_ID = "primary_email"; /** * The ID of the persons preferred organization. * <P>Type: INTEGER (foreign key to organizations table on the * _ID field)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PRIMARY_ORGANIZATION_ID = "primary_organization"; /** @@ -328,7 +442,9 @@ public class Contacts { * * @param resolver the ContentResolver to use * @param personId the person who was contacted + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static void markAsContacted(ContentResolver resolver, long personId) { Uri uri = ContentUris.withAppendedId(CONTENT_URI, personId); uri = Uri.withAppendedPath(uri, "update_contact_time"); @@ -341,7 +457,9 @@ public class Contacts { /** * @hide Used in vCard parser code. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static long tryGetMyContactsGroupId(ContentResolver resolver) { Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION, Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null); @@ -364,25 +482,29 @@ public class Contacts { * @param personId the person to add to the group * @return the URI of the group membership row * @throws IllegalStateException if the My Contacts group can't be found + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) { long groupId = tryGetMyContactsGroupId(resolver); if (groupId == 0) { throw new IllegalStateException("Failed to find the My Contacts group"); } - + return addToGroup(resolver, personId, groupId); } /** * Adds a person to a group referred to by name. - * + * * @param resolver the resolver to use * @param personId the person to add to the group * @param groupName the name of the group to add the contact to * @return the URI of the group membership row * @throws IllegalStateException if the group can't be found + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static Uri addToGroup(ContentResolver resolver, long personId, String groupName) { long groupId = 0; Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION, @@ -400,36 +522,40 @@ public class Contacts { if (groupId == 0) { throw new IllegalStateException("Failed to find the My Contacts group"); } - + return addToGroup(resolver, personId, groupId); } /** * Adds a person to a group. - * + * * @param resolver the resolver to use * @param personId the person to add to the group * @param groupId the group to add the person to * @return the URI of the group membership row + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static Uri addToGroup(ContentResolver resolver, long personId, long groupId) { ContentValues values = new ContentValues(); values.put(GroupMembership.PERSON_ID, personId); values.put(GroupMembership.GROUP_ID, groupId); return resolver.insert(GroupMembership.CONTENT_URI, values); } - + private static final String[] GROUPS_PROJECTION = new String[] { Groups._ID, }; /** * Creates a new contacts and adds it to the "My Contacts" group. - * + * * @param resolver the ContentResolver to use * @param values the values to use when creating the contact * @return the URI of the contact, or null if the operation fails + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static Uri createPersonInMyContactsGroup(ContentResolver resolver, ContentValues values) { @@ -446,6 +572,10 @@ public class Contacts { return contactUri; } + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static Cursor queryGroups(ContentResolver resolver, long person) { return resolver.query(GroupMembership.CONTENT_URI, null, "person=?", new String[]{String.valueOf(person)}, Groups.DEFAULT_SORT_ORDER); @@ -456,24 +586,28 @@ public class Contacts { * @param cr the ContentResolver to use * @param person the Uri of the person whose photo is to be updated * @param data the byte[] that represents the photo + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static void setPhotoData(ContentResolver cr, Uri person, byte[] data) { Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY); ContentValues values = new ContentValues(); values.put(Photos.DATA, data); cr.update(photoUri, values, null, null); } - + /** * Opens an InputStream for the person's photo and returns the photo as a Bitmap. * If the person's photo isn't present returns the placeholderImageResource instead. * @param person the person whose photo should be used + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri person) { Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY); Cursor cursor = cr.query(photoUri, new String[]{Photos.DATA}, null, null, null); try { - if (!cursor.moveToNext()) { + if (cursor == null || !cursor.moveToNext()) { return null; } byte[] data = cursor.getBlob(0); @@ -482,7 +616,7 @@ public class Contacts { } return new ByteArrayInputStream(data); } finally { - cursor.close(); + if (cursor != null) cursor.close(); } } @@ -494,7 +628,9 @@ public class Contacts { * @param placeholderImageResource the image resource to use if the person doesn't * have a photo * @param options the decoding options, can be set to null + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static Bitmap loadContactPhoto(Context context, Uri person, int placeholderImageResource, BitmapFactory.Options options) { if (person == null) { @@ -520,7 +656,9 @@ public class Contacts { /** * A sub directory of a single person that contains all of their Phones. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Phones implements BaseColumns, PhonesColumns, PeopleColumns { /** @@ -530,19 +668,25 @@ public class Contacts { /** * The directory twig for this sub-table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_DIRECTORY = "phones"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "number ASC"; } /** * A subdirectory of a single person that contains all of their * ContactMethods. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class ContactMethods implements BaseColumns, ContactMethodsColumns, PeopleColumns { /** @@ -552,75 +696,100 @@ public class Contacts { /** * The directory twig for this sub-table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_DIRECTORY = "contact_methods"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "data ASC"; } /** * The extensions for a person + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static class Extensions implements BaseColumns, ExtensionsColumns { /** * no public constructor since this is a utility class + * @deprecated see {@link android.provider.ContactsContract} */ private Extensions() {} /** * The directory twig for this sub-table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_DIRECTORY = "extensions"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "name ASC"; /** * The ID of the person this phone number is assigned to. * <P>Type: INTEGER (long)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; } } /** * Columns from the groups table. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface GroupsColumns { /** * The group name. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String NAME = "name"; /** * Notes about the group. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String NOTES = "notes"; /** * Whether this group should be synced if the SYNC_EVERYTHING settings is false * for this group's account. * <P>Type: INTEGER (boolean)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SHOULD_SYNC = "should_sync"; /** * The ID of this group if it is a System Group, null otherwise. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SYSTEM_ID = "system_id"; } /** * This table contains the groups for an account. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Groups implements BaseColumns, SyncConstValue, GroupsColumns { /** @@ -630,86 +799,143 @@ public class Contacts { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/groups"); /** * The content:// style URL for the table that holds the deleted * groups. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri DELETED_CONTENT_URI = Uri.parse("content://contacts/deleted_groups"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * groups. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroup"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * group. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroup"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = NAME + " ASC"; /** - * + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String GROUP_ANDROID_STARRED = "Starred in Android"; /** * The "My Contacts" system group. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String GROUP_MY_CONTACTS = "Contacts"; } /** * Columns from the Phones table that other columns join into themselves. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface PhonesColumns { /** * The type of the the phone number. * <P>Type: INTEGER (one of the constants below)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String TYPE = "type"; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_CUSTOM = 0; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_HOME = 1; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_MOBILE = 2; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_WORK = 3; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_FAX_WORK = 4; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_FAX_HOME = 5; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_PAGER = 6; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_OTHER = 7; /** * The user provided label for the phone number, only used if TYPE is TYPE_CUSTOM. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LABEL = "label"; /** * The phone number as the user entered it. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String NUMBER = "number"; /** * The normalized phone number * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String NUMBER_KEY = "number_key"; /** * Whether this is the primary phone number * <P>Type: INTEGER (if set, non-0 means true)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String ISPRIMARY = "isprimary"; } @@ -717,7 +943,9 @@ public class Contacts { * This table stores phone numbers and a reference to the person that the * contact method belongs to. Phone numbers are stored separately from * other contact methods to make caller ID lookup more efficient. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Phones implements BaseColumns, PhonesColumns, PeopleColumns { /** @@ -725,12 +953,16 @@ public class Contacts { */ private Phones() {} + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final CharSequence getDisplayLabel(Context context, int type, CharSequence label, CharSequence[] labelArray) { CharSequence display = ""; if (type != People.Phones.TYPE_CUSTOM) { - CharSequence[] labels = labelArray != null? labelArray + CharSequence[] labels = labelArray != null? labelArray : context.getResources().getTextArray( com.android.internal.R.array.phoneTypes); try { @@ -746,47 +978,67 @@ public class Contacts { return display; } + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final CharSequence getDisplayLabel(Context context, int type, CharSequence label) { return getDisplayLabel(context, type, label, null); } - + /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/phones"); /** * The content:// style URL for filtering phone numbers + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_FILTER_URL = Uri.parse("content://contacts/phones/filter"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * phones. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * phone. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "name ASC"; /** * The ID of the person this phone number is assigned to. * <P>Type: INTEGER (long)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; } + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final class GroupMembership implements BaseColumns, GroupsColumns { /** * no public constructor since this is a utility class @@ -795,137 +1047,206 @@ public class Contacts { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/groupmembership"); /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri RAW_CONTENT_URI = Uri.parse("content://contacts/groupmembershipraw"); /** * The directory twig for this sub-table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_DIRECTORY = "groupmembership"; + /** * The MIME type of {@link #CONTENT_URI} providing a directory of all * person groups. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroupmembership"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * person group. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroupmembership"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "group_id ASC"; /** * The row id of the accounts group. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String GROUP_ID = "group_id"; /** * The sync id of the group. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String GROUP_SYNC_ID = "group_sync_id"; /** * The account of the group. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String GROUP_SYNC_ACCOUNT = "group_sync_account"; /** + * The account type of the group. + * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated + public static final String GROUP_SYNC_ACCOUNT_TYPE = "group_sync_account_type"; + + /** * The row id of the person. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; } /** * Columns from the ContactMethods table that other tables join into * themseleves. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface ContactMethodsColumns { /** * The kind of the the contact method. For example, email address, * postal address, etc. * <P>Type: INTEGER (one of the values below)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String KIND = "kind"; /** * The type of the contact method, must be one of the types below. * <P>Type: INTEGER (one of the values below)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String TYPE = "type"; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_CUSTOM = 0; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_HOME = 1; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_WORK = 2; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_OTHER = 3; /** * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final int MOBILE_EMAIL_TYPE_INDEX = 2; /** * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future. * This is not "mobile" but "CELL" since vCard uses it for identifying mobile phone. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String MOBILE_EMAIL_TYPE_NAME = "_AUTO_CELL"; /** * The user defined label for the the contact method. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LABEL = "label"; /** * The data for the contact method. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DATA = "data"; /** * Auxiliary data for the contact method. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String AUX_DATA = "aux_data"; /** * Whether this is the primary organization * <P>Type: INTEGER (if set, non-0 means true)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String ISPRIMARY = "isprimary"; } /** * This table stores all non-phone contact methods and a reference to the * person that the contact method belongs to. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class ContactMethods implements BaseColumns, ContactMethodsColumns, PeopleColumns { /** * The column with latitude data for postal locations * <P>Type: REAL</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String POSTAL_LOCATION_LATITUDE = DATA; /** * The column with longitude data for postal locations * <P>Type: REAL</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String POSTAL_LOCATION_LONGITUDE = AUX_DATA; /** @@ -935,24 +1256,66 @@ public class Contacts { * - null * - pre:<an integer, one of the protocols below> * - custom:<a string> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final int PROTOCOL_AIM = 0; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int PROTOCOL_MSN = 1; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int PROTOCOL_YAHOO = 2; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int PROTOCOL_SKYPE = 3; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int PROTOCOL_QQ = 4; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int PROTOCOL_GOOGLE_TALK = 5; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int PROTOCOL_ICQ = 6; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int PROTOCOL_JABBER = 7; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static String encodePredefinedImProtocol(int protocol) { return "pre:" + protocol; } + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static String encodeCustomImProtocol(String protocolString) { return "custom:" + protocolString; } + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static Object decodeImProtocol(String encodedString) { if (encodedString == null) { return null; @@ -969,7 +1332,7 @@ public class Contacts { throw new IllegalArgumentException( "the value is not a valid encoded protocol, " + encodedString); } - + /** * This looks up the provider name defined in * {@link android.provider.Im.ProviderNames} from the predefined IM protocol id. @@ -978,8 +1341,10 @@ public class Contacts { * @param protocol the protocol ID * @return the provider name the IM app uses for the given protocol, or null if no * provider is defined for the given protocol + * @deprecated see {@link android.provider.ContactsContract} * @hide */ + @Deprecated public static String lookupProviderNameFromId(int protocol) { switch (protocol) { case PROTOCOL_GOOGLE_TALK: @@ -1007,6 +1372,10 @@ public class Contacts { */ private ContactMethods() {} + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final CharSequence getDisplayLabel(Context context, int kind, int type, CharSequence label) { CharSequence display = ""; @@ -1022,13 +1391,7 @@ public class Contacts { } } else { if (!TextUtils.isEmpty(label)) { - if (label.toString().equals(MOBILE_EMAIL_TYPE_NAME)) { - display = - context.getString( - com.android.internal.R.string.mobileEmailTypeName); - } else { - display = label; - } + display = label; } } break; @@ -1064,7 +1427,9 @@ public class Contacts { * @param postalId the address to update * @param latitude the latitude for the address * @param longitude the longitude for the address + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public void addPostalLocation(Context context, long postalId, double latitude, double longitude) { final ContentResolver resolver = context.getContentResolver(); @@ -1083,130 +1448,166 @@ public class Contacts { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/contact_methods"); /** * The content:// style URL for sub-directory of e-mail addresses. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_EMAIL_URI = Uri.parse("content://contacts/contact_methods/email"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of + * @deprecated see {@link android.provider.ContactsContract} * phones. */ + @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact-methods"; /** - * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\ + * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of * multiple {@link Contacts#KIND_EMAIL} entries. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email"; /** - * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\ + * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of * multiple {@link Contacts#KIND_POSTAL} entries. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_POSTAL_TYPE = "vnd.android.cursor.dir/postal-address"; /** * The MIME type of a {@link #CONTENT_URI} sub-directory of a single * {@link Contacts#KIND_EMAIL} entry. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email"; /** * The MIME type of a {@link #CONTENT_URI} sub-directory of a single * {@link Contacts#KIND_POSTAL} entry. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_POSTAL_ITEM_TYPE = "vnd.android.cursor.item/postal-address"; /** * The MIME type of a {@link #CONTENT_URI} sub-directory of a single * {@link Contacts#KIND_IM} entry. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_IM_ITEM_TYPE = "vnd.android.cursor.item/jabber-im"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "name ASC"; /** * The ID of the person this contact method is assigned to. * <P>Type: INTEGER (long)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; } /** * The IM presence columns with some contacts specific columns mixed in. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface PresenceColumns extends Im.CommonPresenceColumns { /** * The IM service the presence is coming from. Formatted using either * {@link Contacts.ContactMethods#encodePredefinedImProtocol} or * {@link Contacts.ContactMethods#encodeCustomImProtocol}. * <P>Type: STRING</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String IM_PROTOCOL = "im_protocol"; /** * The IM handle the presence item is for. The handle is scoped to * the {@link #IM_PROTOCOL}. * <P>Type: STRING</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String IM_HANDLE = "im_handle"; /** * The IM account for the local user that the presence data came from. * <P>Type: STRING</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String IM_ACCOUNT = "im_account"; } /** * Contains presence information about contacts. * @hide + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Presence implements BaseColumns, PresenceColumns, PeopleColumns { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/presence"); /** * The ID of the person this presence item is assigned to. * <P>Type: INTEGER (long)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; /** * Gets the resource ID for the proper presence icon. - * + * * @param status the status to get the icon for * @return the resource ID for the proper presence icon + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final int getPresenceIconResourceId(int status) { switch (status) { case Contacts.People.AVAILABLE: return com.android.internal.R.drawable.presence_online; - + case Contacts.People.IDLE: case Contacts.People.AWAY: return com.android.internal.R.drawable.presence_away; - + case Contacts.People.DO_NOT_DISTURB: return com.android.internal.R.drawable.presence_busy; - + case Contacts.People.INVISIBLE: return com.android.internal.R.drawable.presence_invisible; - + case Contacts.People.OFFLINE: default: return com.android.internal.R.drawable.presence_offline; @@ -1218,7 +1619,9 @@ public class Contacts { * * @param icon the icon to to set * @param serverStatus that status + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final void setPresenceIcon(ImageView icon, int serverStatus) { icon.setImageResource(getPresenceIconResourceId(serverStatus)); } @@ -1226,58 +1629,90 @@ public class Contacts { /** * Columns from the Organizations table that other columns join into themselves. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface OrganizationColumns { /** * The type of the organizations. * <P>Type: INTEGER (one of the constants below)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String TYPE = "type"; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_CUSTOM = 0; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_WORK = 1; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final int TYPE_OTHER = 2; /** * The user provided label, only used if TYPE is TYPE_CUSTOM. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LABEL = "label"; /** * The name of the company for this organization. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String COMPANY = "company"; /** * The title within this organization. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String TITLE = "title"; /** * The person this organization is tied to. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; /** * Whether this is the primary organization * <P>Type: INTEGER (if set, non-0 means true)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String ISPRIMARY = "isprimary"; } /** * A sub directory of a single person that contains all of their Phones. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Organizations implements BaseColumns, OrganizationColumns { /** * no public constructor since this is a utility class */ private Organizations() {} + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public static final CharSequence getDisplayLabel(Context context, int type, CharSequence label) { CharSequence display = ""; @@ -1300,68 +1735,90 @@ public class Contacts { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/organizations"); /** * The directory twig for this sub-table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_DIRECTORY = "organizations"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "company, title, isprimary ASC"; } /** * Columns from the Photos table that other columns join into themselves. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public interface PhotosColumns { /** * The _SYNC_VERSION of the photo that was last downloaded * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LOCAL_VERSION = "local_version"; /** * The person this photo is associated with. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; /** * non-zero if a download is required and the photo isn't marked as a bad resource. * You must specify this in the columns in order to use it in the where clause. * <P>Type: INTEGER(boolean)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DOWNLOAD_REQUIRED = "download_required"; /** * non-zero if this photo is known to exist on the server * <P>Type: INTEGER(boolean)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String EXISTS_ON_SERVER = "exists_on_server"; /** * Contains the description of the upload or download error from * the previous attempt. If null then the previous attempt succeeded. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SYNC_ERROR = "sync_error"; /** * The image data, or null if there is no image. * <P>Type: BLOB</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DATA = "data"; } /** * The photos over all of the people + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Photos implements BaseColumns, PhotosColumns, SyncConstValue { /** * no public constructor since this is a utility class @@ -1370,38 +1827,53 @@ public class Contacts { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ - public static final Uri CONTENT_URI = - Uri.parse("content://contacts/photos"); + @Deprecated + public static final Uri CONTENT_URI = Uri.parse("content://contacts/photos"); /** * The directory twig for this sub-table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_DIRECTORY = "photo"; /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "person ASC"; } + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated public interface ExtensionsColumns { /** * The name of this extension. May not be null. There may be at most one row for each name. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String NAME = "name"; /** * The value of this extension. May not be null. * <P>Type: TEXT</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String VALUE = "value"; } /** * The extensions for a person + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Extensions implements BaseColumns, ExtensionsColumns { /** * no public constructor since this is a utility class @@ -1410,64 +1882,91 @@ public class Contacts { /** * The content:// style URL for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final Uri CONTENT_URI = Uri.parse("content://contacts/extensions"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * phones. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_extensions"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * phone. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_extensions"; + /** * The default sort order for this table + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String DEFAULT_SORT_ORDER = "person, name ASC"; /** * The ID of the person this phone number is assigned to. * <P>Type: INTEGER (long)</P> + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String PERSON_ID = "person"; } /** * Contains helper classes used to create or manage {@link android.content.Intent Intents} * that involve contacts. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Intents { /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated + public Intents() { + } + + /** * This is the intent that is fired when a search suggestion is clicked on. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SEARCH_SUGGESTION_CLICKED = - "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED"; + ContactsContract.Intents.SEARCH_SUGGESTION_CLICKED; /** - * This is the intent that is fired when a search suggestion for dialing a number + * This is the intent that is fired when a search suggestion for dialing a number * is clicked on. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = - "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED"; + ContactsContract.Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED; /** * This is the intent that is fired when a search suggestion for creating a contact * is clicked on. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = - "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED"; + ContactsContract.Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED; /** * Starts an Activity that lets the user pick a contact to attach an image to. * After picking the contact it launches the image cropper in face detection mode. + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String ATTACH_IMAGE = - "com.android.contacts.action.ATTACH_IMAGE"; + @Deprecated + public static final String ATTACH_IMAGE = ContactsContract.Intents.ATTACH_IMAGE; /** * Takes as input a data URI with a mailto: or tel: scheme. If a single @@ -1491,9 +1990,11 @@ public class Contacts { * <p> * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip * prompting the user when the contact doesn't exist. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String SHOW_OR_CREATE_CONTACT = - "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; + ContactsContract.Intents.SHOW_OR_CREATE_CONTACT; /** * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new @@ -1501,80 +2002,120 @@ public class Contacts { * to prompt user with dialog before creating. * <p> * Type: BOOLEAN + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String EXTRA_FORCE_CREATE = - "com.android.contacts.action.FORCE_CREATE"; - + @Deprecated + public static final String EXTRA_FORCE_CREATE = ContactsContract.Intents.EXTRA_FORCE_CREATE; + /** * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact * description to be shown when prompting user about creating a new * contact. * <p> * Type: STRING + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String EXTRA_CREATE_DESCRIPTION = - "com.android.contacts.action.CREATE_DESCRIPTION"; + ContactsContract.Intents.EXTRA_CREATE_DESCRIPTION; + + /** + * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a + * dialog location using screen coordinates. When not specified, the + * dialog will be centered. + * + * @hide pending API council review + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated + public static final String EXTRA_TARGET_RECT = ContactsContract.Intents.EXTRA_TARGET_RECT; /** * Intents related to the Contacts app UI. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class UI { /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated + public UI() { + } + + /** * The action for the default contacts list tab. + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String LIST_DEFAULT = - "com.android.contacts.action.LIST_DEFAULT"; + @Deprecated + public static final String LIST_DEFAULT = ContactsContract.Intents.UI.LIST_DEFAULT; /** * The action for the contacts list tab. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LIST_GROUP_ACTION = - "com.android.contacts.action.LIST_GROUP"; + ContactsContract.Intents.UI.LIST_GROUP_ACTION; /** * When in LIST_GROUP_ACTION mode, this is the group to display. + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP"; - + @Deprecated + public static final String GROUP_NAME_EXTRA_KEY = + ContactsContract.Intents.UI.GROUP_NAME_EXTRA_KEY; /** * The action for the all contacts list tab. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LIST_ALL_CONTACTS_ACTION = - "com.android.contacts.action.LIST_ALL_CONTACTS"; + ContactsContract.Intents.UI.LIST_ALL_CONTACTS_ACTION; /** * The action for the contacts with phone numbers list tab. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LIST_CONTACTS_WITH_PHONES_ACTION = - "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES"; + ContactsContract.Intents.UI.LIST_CONTACTS_WITH_PHONES_ACTION; /** * The action for the starred contacts list tab. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LIST_STARRED_ACTION = - "com.android.contacts.action.LIST_STARRED"; + ContactsContract.Intents.UI.LIST_STARRED_ACTION; /** * The action for the frequent contacts list tab. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LIST_FREQUENT_ACTION = - "com.android.contacts.action.LIST_FREQUENT"; + ContactsContract.Intents.UI.LIST_FREQUENT_ACTION; /** * The action for the "strequent" contacts list tab. It first lists the starred * contacts in alphabetical order and then the frequent contacts in descending * order of the number of times they have been contacted. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String LIST_STREQUENT_ACTION = - "com.android.contacts.action.LIST_STREQUENT"; + ContactsContract.Intents.UI.LIST_STREQUENT_ACTION; /** * A key for to be used as an intent extra to set the activity * title to a custom String value. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final String TITLE_EXTRA_KEY = - "com.android.contacts.extra.TITLE_EXTRA"; - + ContactsContract.Intents.UI.TITLE_EXTRA_KEY; + /** * Activity Action: Display a filtered list of contacts * <p> @@ -1582,188 +2123,267 @@ public class Contacts { * filtering * <p> * Output: Nothing. + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String FILTER_CONTACTS_ACTION = - "com.android.contacts.action.FILTER_CONTACTS"; - + @Deprecated + public static final String FILTER_CONTACTS_ACTION = + ContactsContract.Intents.UI.FILTER_CONTACTS_ACTION; + /** * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION} * intents to supply the text on which to filter. + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String FILTER_TEXT_EXTRA_KEY = - "com.android.contacts.extra.FILTER_TEXT"; + @Deprecated + public static final String FILTER_TEXT_EXTRA_KEY = + ContactsContract.Intents.UI.FILTER_TEXT_EXTRA_KEY; } /** * Convenience class that contains string constants used * to create contact {@link android.content.Intent Intents}. + * @deprecated see {@link android.provider.ContactsContract} */ + @Deprecated public static final class Insert { - /** The action code to use when adding a contact */ - public static final String ACTION = Intent.ACTION_INSERT; + /** + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated + public Insert() { + } + + /** The action code to use when adding a contact + * @deprecated see {@link android.provider.ContactsContract} + */ + @Deprecated + public static final String ACTION = ContactsContract.Intents.Insert.ACTION; /** * If present, forces a bypass of quick insert mode. + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String FULL_MODE = "full_mode"; + @Deprecated + public static final String FULL_MODE = ContactsContract.Intents.Insert.FULL_MODE; /** * The extra field for the contact name. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String NAME = "name"; + @Deprecated + public static final String NAME = ContactsContract.Intents.Insert.NAME; /** * The extra field for the contact phonetic name. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String PHONETIC_NAME = "phonetic_name"; + @Deprecated + public static final String PHONETIC_NAME = + ContactsContract.Intents.Insert.PHONETIC_NAME; /** * The extra field for the contact company. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String COMPANY = "company"; + @Deprecated + public static final String COMPANY = ContactsContract.Intents.Insert.COMPANY; /** * The extra field for the contact job title. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String JOB_TITLE = "job_title"; + @Deprecated + public static final String JOB_TITLE = ContactsContract.Intents.Insert.JOB_TITLE; /** * The extra field for the contact notes. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String NOTES = "notes"; + @Deprecated + public static final String NOTES = ContactsContract.Intents.Insert.NOTES; /** * The extra field for the contact phone number. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String PHONE = "phone"; + @Deprecated + public static final String PHONE = ContactsContract.Intents.Insert.PHONE; /** * The extra field for the contact phone number type. * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns}, * or a string specifying a custom label.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String PHONE_TYPE = "phone_type"; + @Deprecated + public static final String PHONE_TYPE = ContactsContract.Intents.Insert.PHONE_TYPE; /** * The extra field for the phone isprimary flag. * <P>Type: boolean</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String PHONE_ISPRIMARY = "phone_isprimary"; + @Deprecated + public static final String PHONE_ISPRIMARY = + ContactsContract.Intents.Insert.PHONE_ISPRIMARY; /** * The extra field for an optional second contact phone number. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String SECONDARY_PHONE = "secondary_phone"; + @Deprecated + public static final String SECONDARY_PHONE = + ContactsContract.Intents.Insert.SECONDARY_PHONE; /** * The extra field for an optional second contact phone number type. * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns}, * or a string specifying a custom label.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type"; + @Deprecated + public static final String SECONDARY_PHONE_TYPE = + ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE; /** * The extra field for an optional third contact phone number. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String TERTIARY_PHONE = "tertiary_phone"; + @Deprecated + public static final String TERTIARY_PHONE = + ContactsContract.Intents.Insert.TERTIARY_PHONE; /** * The extra field for an optional third contact phone number type. * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns}, * or a string specifying a custom label.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type"; + @Deprecated + public static final String TERTIARY_PHONE_TYPE = + ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE; /** * The extra field for the contact email address. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String EMAIL = "email"; + @Deprecated + public static final String EMAIL = ContactsContract.Intents.Insert.EMAIL; /** * The extra field for the contact email type. * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} * or a string specifying a custom label.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String EMAIL_TYPE = "email_type"; + @Deprecated + public static final String EMAIL_TYPE = ContactsContract.Intents.Insert.EMAIL_TYPE; /** * The extra field for the email isprimary flag. * <P>Type: boolean</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String EMAIL_ISPRIMARY = "email_isprimary"; + @Deprecated + public static final String EMAIL_ISPRIMARY = + ContactsContract.Intents.Insert.EMAIL_ISPRIMARY; /** * The extra field for an optional second contact email address. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String SECONDARY_EMAIL = "secondary_email"; + @Deprecated + public static final String SECONDARY_EMAIL = + ContactsContract.Intents.Insert.SECONDARY_EMAIL; /** * The extra field for an optional second contact email type. * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} * or a string specifying a custom label.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type"; + @Deprecated + public static final String SECONDARY_EMAIL_TYPE = + ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE; /** * The extra field for an optional third contact email address. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String TERTIARY_EMAIL = "tertiary_email"; + @Deprecated + public static final String TERTIARY_EMAIL = + ContactsContract.Intents.Insert.TERTIARY_EMAIL; /** * The extra field for an optional third contact email type. * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} * or a string specifying a custom label.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type"; + @Deprecated + public static final String TERTIARY_EMAIL_TYPE = + ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE; /** * The extra field for the contact postal address. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String POSTAL = "postal"; + @Deprecated + public static final String POSTAL = ContactsContract.Intents.Insert.POSTAL; /** * The extra field for the contact postal address type. * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} * or a string specifying a custom label.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String POSTAL_TYPE = "postal_type"; + @Deprecated + public static final String POSTAL_TYPE = ContactsContract.Intents.Insert.POSTAL_TYPE; /** * The extra field for the postal isprimary flag. * <P>Type: boolean</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String POSTAL_ISPRIMARY = "postal_isprimary"; + @Deprecated + public static final String POSTAL_ISPRIMARY = ContactsContract.Intents.Insert.POSTAL_ISPRIMARY; /** * The extra field for an IM handle. * <P>Type: String</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String IM_HANDLE = "im_handle"; + @Deprecated + public static final String IM_HANDLE = ContactsContract.Intents.Insert.IM_HANDLE; /** * The extra field for the IM protocol * <P>Type: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol} * or {@link Contacts.ContactMethods#encodeCustomImProtocol}.</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String IM_PROTOCOL = "im_protocol"; + @Deprecated + public static final String IM_PROTOCOL = ContactsContract.Intents.Insert.IM_PROTOCOL; /** * The extra field for the IM isprimary flag. * <P>Type: boolean</P> + * @deprecated see {@link android.provider.ContactsContract} */ - public static final String IM_ISPRIMARY = "im_isprimary"; + @Deprecated + public static final String IM_ISPRIMARY = ContactsContract.Intents.Insert.IM_ISPRIMARY; } } } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java new file mode 100644 index 0000000..7904401 --- /dev/null +++ b/core/java/android/provider/ContactsContract.java @@ -0,0 +1,2722 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.provider; + +import android.accounts.Account; +import android.content.ContentProviderClient; +import android.content.ContentProviderOperation; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.Rect; +import android.net.Uri; +import android.os.RemoteException; +import android.text.TextUtils; +import android.util.Pair; +import android.view.View; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * The contract between the contacts provider and applications. Contains definitions + * for the supported URIs and columns. These APIs supersede {@link Contacts}. + */ +@SuppressWarnings("unused") +public final class ContactsContract { + /** The authority for the contacts provider */ + public static final String AUTHORITY = "com.android.contacts"; + /** A content:// style uri to the authority for the contacts provider */ + public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); + + /** + * An optional insert, update or delete URI parameter that allows the caller + * to specify that it is a sync adapter. The default value is false. If true + * the dirty flag is not automatically set and the "syncToNetwork" parameter + * is set to false when calling + * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}. + */ + public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; + + /** + * A query parameter key used to specify the package that is requesting a query. + * This is used for restricting data based on package name. + * + * @hide + */ + public static final String REQUESTING_PACKAGE_PARAM_KEY = "requesting_package"; + + /** + * @hide should be removed when users are updated to refer to SyncState + * @deprecated use SyncState instead + */ + @Deprecated + public interface SyncStateColumns extends SyncStateContract.Columns { + } + + /** + * A table provided for sync adapters to use for storing private sync state data. + * + * @see SyncStateContract + */ + public static final class SyncState implements SyncStateContract.Columns { + /** + * This utility class cannot be instantiated + */ + private SyncState() {} + + public static final String CONTENT_DIRECTORY = + SyncStateContract.Constants.CONTENT_DIRECTORY; + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = + Uri.withAppendedPath(AUTHORITY_URI, CONTENT_DIRECTORY); + + /** + * @see android.provider.SyncStateContract.Helpers#get + */ + public static byte[] get(ContentProviderClient provider, Account account) + throws RemoteException { + return SyncStateContract.Helpers.get(provider, CONTENT_URI, account); + } + + /** + * @see android.provider.SyncStateContract.Helpers#get + */ + public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account) + throws RemoteException { + return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account); + } + + /** + * @see android.provider.SyncStateContract.Helpers#set + */ + public static void set(ContentProviderClient provider, Account account, byte[] data) + throws RemoteException { + SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data); + } + + /** + * @see android.provider.SyncStateContract.Helpers#newSetOperation + */ + public static ContentProviderOperation newSetOperation(Account account, byte[] data) { + return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data); + } + } + + /** + * Generic columns for use by sync adapters. The specific functions of + * these columns are private to the sync adapter. Other clients of the API + * should not attempt to either read or write this column. + */ + protected interface BaseSyncColumns { + + /** Generic column for use by sync adapters. */ + public static final String SYNC1 = "sync1"; + /** Generic column for use by sync adapters. */ + public static final String SYNC2 = "sync2"; + /** Generic column for use by sync adapters. */ + public static final String SYNC3 = "sync3"; + /** Generic column for use by sync adapters. */ + public static final String SYNC4 = "sync4"; + } + + /** + * Columns that appear when each row of a table belongs to a specific + * account, including sync information that an account may need. + */ + protected interface SyncColumns extends BaseSyncColumns { + /** + * The name of the account instance to which this row belongs, which when paired with + * {@link #ACCOUNT_TYPE} identifies a specific account. + * <P>Type: TEXT</P> + */ + public static final String ACCOUNT_NAME = "account_name"; + + /** + * The type of account to which this row belongs, which when paired with + * {@link #ACCOUNT_NAME} identifies a specific account. + * <P>Type: TEXT</P> + */ + public static final String ACCOUNT_TYPE = "account_type"; + + /** + * String that uniquely identifies this row to its source account. + * <P>Type: TEXT</P> + */ + public static final String SOURCE_ID = "sourceid"; + + /** + * Version number that is updated whenever this row or its related data + * changes. + * <P>Type: INTEGER</P> + */ + public static final String VERSION = "version"; + + /** + * Flag indicating that {@link #VERSION} has changed, and this row needs + * to be synchronized by its owning account. + * <P>Type: INTEGER (boolean)</P> + */ + public static final String DIRTY = "dirty"; + } + + protected interface ContactOptionsColumns { + /** + * The number of times a contact has been contacted + * <P>Type: INTEGER</P> + */ + public static final String TIMES_CONTACTED = "times_contacted"; + + /** + * The last time a contact was contacted. + * <P>Type: INTEGER</P> + */ + public static final String LAST_TIME_CONTACTED = "last_time_contacted"; + + /** + * Is the contact starred? + * <P>Type: INTEGER (boolean)</P> + */ + public static final String STARRED = "starred"; + + /** + * A custom ringtone associated with a contact. Not always present. + * <P>Type: TEXT (URI to the ringtone)</P> + */ + public static final String CUSTOM_RINGTONE = "custom_ringtone"; + + /** + * Whether the contact should always be sent to voicemail. Not always + * present. + * <P>Type: INTEGER (0 for false, 1 for true)</P> + */ + public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; + } + + protected interface ContactsColumns { + /** + * The display name for the contact. + * <P>Type: TEXT</P> + */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * Reference to the row in the data table holding the photo. + * <P>Type: INTEGER REFERENCES data(_id)</P> + */ + public static final String PHOTO_ID = "photo_id"; + + /** + * Lookup value that reflects the {@link Groups#GROUP_VISIBLE} state of + * any {@link CommonDataKinds.GroupMembership} for this contact. + */ + public static final String IN_VISIBLE_GROUP = "in_visible_group"; + + /** + * An indicator of whether this contact has at least one phone number. "1" if there is + * at least one phone number, "0" otherwise. + * <P>Type: INTEGER</P> + */ + public static final String HAS_PHONE_NUMBER = "has_phone_number"; + + /** + * An opaque value that contains hints on how to find the contact if + * its row id changed as a result of a sync or aggregation. + */ + public static final String LOOKUP_KEY = "lookup"; + } + + protected interface ContactStatusColumns { + /** + * Contact presence status. See {@link StatusUpdates} for individual status + * definitions. + * <p>Type: NUMBER</p> + */ + public static final String CONTACT_PRESENCE = "contact_presence"; + + /** + * Contact's latest status update. + * <p>Type: TEXT</p> + */ + public static final String CONTACT_STATUS = "contact_status"; + + /** + * The absolute time in milliseconds when the latest status was + * inserted/updated. + * <p>Type: NUMBER</p> + */ + public static final String CONTACT_STATUS_TIMESTAMP = "contact_status_ts"; + + /** + * The package containing resources for this status: label and icon. + * <p>Type: NUMBER</p> + */ + public static final String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package"; + + /** + * The resource ID of the label describing the source of contact + * status, e.g. "Google Talk". This resource is scoped by the + * {@link #CONTACT_STATUS_RES_PACKAGE}. + * <p>Type: NUMBER</p> + */ + public static final String CONTACT_STATUS_LABEL = "contact_status_label"; + + /** + * The resource ID of the icon for the source of contact status. This + * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}. + * <p>Type: NUMBER</p> + */ + public static final String CONTACT_STATUS_ICON = "contact_status_icon"; + } + + /** + * Constants for the contacts table, which contains a record per group + * of raw contacts representing the same person. + */ + public static class Contacts implements BaseColumns, ContactsColumns, + ContactOptionsColumns, ContactStatusColumns { + /** + * This utility class cannot be instantiated + */ + private Contacts() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts"); + + /** + * A content:// style URI for this table that should be used to create + * shortcuts or otherwise create long-term links to contacts. This URI + * should always be followed by a "/" and the contact's {@link #LOOKUP_KEY}. + * It can optionally also have a "/" and last known contact ID appended after + * that. This "complete" format is an important optimization and is highly recommended. + * <p> + * As long as the contact's row ID remains the same, this URI is + * equivalent to {@link #CONTENT_URI}. If the contact's row ID changes + * as a result of a sync or aggregation, this URI will look up the + * contact using indirect information (sync IDs or constituent raw + * contacts). + * <p> + * Lookup key should be appended unencoded - it is stored in the encoded + * form, ready for use in a URI. + */ + public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, + "lookup"); + + /** + * Base {@link Uri} for referencing a single {@link Contacts} entry, + * created by appending {@link #LOOKUP_KEY} using + * {@link Uri#withAppendedPath(Uri, String)}. Provides + * {@link OpenableColumns} columns when queried, or returns the + * referenced contact formatted as a vCard when opened through + * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}. + */ + public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI, + "as_vcard"); + + /** + * Builds a {@link #CONTENT_LOOKUP_URI} style {@link Uri} describing the + * requested {@link Contacts} entry. + * + * @param contactUri A {@link #CONTENT_URI} row, or an existing + * {@link #CONTENT_LOOKUP_URI} to attempt refreshing. + */ + public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) { + final Cursor c = resolver.query(contactUri, new String[] { + Contacts.LOOKUP_KEY, Contacts._ID + }, null, null, null); + if (c == null) { + return null; + } + + try { + if (c.moveToFirst()) { + final String lookupKey = c.getString(0); + final long contactId = c.getLong(1); + return getLookupUri(contactId, lookupKey); + } + } finally { + c.close(); + } + return null; + } + + /** + * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the + * given {@link android.provider.ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}. + */ + public static Uri getLookupUri(long contactId, String lookupKey) { + return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, + lookupKey), contactId); + } + + /** + * Computes a content URI (see {@link #CONTENT_URI}) given a lookup URI. + * <p> + * Returns null if the contact cannot be found. + */ + public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) { + if (lookupUri == null) { + return null; + } + + Cursor c = resolver.query(lookupUri, new String[]{Contacts._ID}, null, null, null); + if (c == null) { + return null; + } + + try { + if (c.moveToFirst()) { + long contactId = c.getLong(0); + return ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); + } + } finally { + c.close(); + } + return null; + } + + /** + * Mark a contact as having been contacted. + * + * @param resolver the ContentResolver to use + * @param contactId the person who was contacted + */ + public static void markAsContacted(ContentResolver resolver, long contactId) { + Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId); + ContentValues values = new ContentValues(); + // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified. + values.put(LAST_TIME_CONTACTED, System.currentTimeMillis()); + resolver.update(uri, values, null, null); + } + + /** + * The content:// style URI used for "type-to-filter" functionality on the + * {@link #CONTENT_URI} URI. The filter string will be used to match + * various parts of the contact name. The filter argument should be passed + * as an additional path segment after this URI. + */ + public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath( + CONTENT_URI, "filter"); + + /** + * The content:// style URI for this table joined with useful data from + * {@link Data}, filtered to include only starred contacts + * and the most frequently contacted contacts. + */ + public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath( + CONTENT_URI, "strequent"); + + /** + * The content:// style URI used for "type-to-filter" functionality on the + * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match + * various parts of the contact name. The filter argument should be passed + * as an additional path segment after this URI. + */ + public static final Uri CONTENT_STREQUENT_FILTER_URI = Uri.withAppendedPath( + CONTENT_STREQUENT_URI, "filter"); + + public static final Uri CONTENT_GROUP_URI = Uri.withAppendedPath( + CONTENT_URI, "group"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of + * people. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * person. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * person. + */ + public static final String CONTENT_VCARD_TYPE = "text/x-vcard"; + + /** + * A sub-directory of a single contact that contains all of the constituent raw contact + * {@link Data} rows. + */ + public static final class Data implements BaseColumns, DataColumns { + /** + * no public constructor since this is a utility class + */ + private Data() {} + + /** + * The directory twig for this sub-table + */ + public static final String CONTENT_DIRECTORY = "data"; + } + + /** + * A sub-directory of a single contact aggregate that contains all aggregation suggestions + * (other contacts). The aggregation suggestions are computed based on approximate + * data matches with this contact. + */ + public static final class AggregationSuggestions implements BaseColumns, ContactsColumns { + /** + * No public constructor since this is a utility class + */ + private AggregationSuggestions() {} + + /** + * The directory twig for this sub-table. The URI can be followed by an optional + * type-to-filter, similar to + * {@link android.provider.ContactsContract.Contacts#CONTENT_FILTER_URI}. + */ + public static final String CONTENT_DIRECTORY = "suggestions"; + } + + /** + * A sub-directory of a single contact that contains the contact's primary photo. + */ + public static final class Photo implements BaseColumns, DataColumns { + /** + * no public constructor since this is a utility class + */ + private Photo() {} + + /** + * The directory twig for this sub-table + */ + public static final String CONTENT_DIRECTORY = "photo"; + } + + /** + * Opens an InputStream for the contacts's default photo and returns the + * photo as a byte stream. If there is not photo null will be returned. + * + * @param contactUri the contact whose photo should be used + * @return an InputStream of the photo, or null if no photo is present + */ + public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { + Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY); + if (photoUri == null) { + return null; + } + Cursor cursor = cr.query(photoUri, + new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); + try { + if (cursor == null || !cursor.moveToNext()) { + return null; + } + byte[] data = cursor.getBlob(0); + if (data == null) { + return null; + } + return new ByteArrayInputStream(data); + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + } + + protected interface RawContactsColumns { + /** + * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this + * data belongs to. + * <P>Type: INTEGER</P> + */ + public static final String CONTACT_ID = "contact_id"; + + /** + * Flag indicating that this {@link RawContacts} entry and its children have + * been restricted to specific platform apps. + * <P>Type: INTEGER (boolean)</P> + * + * @hide until finalized in future platform release + */ + public static final String IS_RESTRICTED = "is_restricted"; + + /** + * The aggregation mode for this contact. + * <P>Type: INTEGER</P> + */ + public static final String AGGREGATION_MODE = "aggregation_mode"; + + /** + * The "deleted" flag: "0" by default, "1" if the row has been marked + * for deletion. When {@link android.content.ContentResolver#delete} is + * called on a raw contact, it is marked for deletion and removed from its + * aggregate contact. The sync adaptor deletes the raw contact on the server and + * then calls ContactResolver.delete once more, this time passing the + * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize + * the data removal. + * <P>Type: INTEGER</P> + */ + public static final String DELETED = "deleted"; + } + + /** + * Constants for the raw contacts table, which contains the base contact + * information per sync source. Sync adapters and contact management apps + * are the primary consumers of this API. + */ + public static final class RawContacts implements BaseColumns, RawContactsColumns, + ContactOptionsColumns, SyncColumns { + /** + * This utility class cannot be instantiated + */ + private RawContacts() { + } + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of + * people. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * person. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact"; + + /** + * Aggregation mode: aggregate asynchronously. + */ + public static final int AGGREGATION_MODE_DEFAULT = 0; + + /** + * Aggregation mode: aggregate at the time the raw contact is inserted/updated. + */ + public static final int AGGREGATION_MODE_IMMEDIATE = 1; + + /** + * If {@link #AGGREGATION_MODE} is {@link #AGGREGATION_MODE_SUSPENDED}, changes + * to the raw contact do not cause its aggregation to be revisited. Note that changing + * {@link #AGGREGATION_MODE} from {@link #AGGREGATION_MODE_SUSPENDED} to + * {@link #AGGREGATION_MODE_DEFAULT} does not trigger an aggregation pass. Any subsequent + * change to the raw contact's data will. + */ + public static final int AGGREGATION_MODE_SUSPENDED = 2; + + /** + * Aggregation mode: never aggregate this raw contact (note that the raw contact will not + * have a corresponding Aggregate and therefore will not be included in Aggregates + * query results.) + */ + public static final int AGGREGATION_MODE_DISABLED = 3; + + /** + * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} + * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} + * entry of the given {@link RawContacts} entry. + */ + public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) { + // TODO: use a lighter query by joining rawcontacts with contacts in provider + final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY); + final Cursor cursor = resolver.query(dataUri, new String[] { + RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY + }, null, null, null); + + Uri lookupUri = null; + try { + if (cursor != null && cursor.moveToFirst()) { + final long contactId = cursor.getLong(0); + final String lookupKey = cursor.getString(1); + return Contacts.getLookupUri(contactId, lookupKey); + } + } finally { + if (cursor != null) cursor.close(); + } + return lookupUri; + } + + /** + * A sub-directory of a single raw contact that contains all of their {@link Data} rows. + * To access this directory append {@link Data#CONTENT_DIRECTORY} to the contact URI. + */ + public static final class Data implements BaseColumns, DataColumns { + /** + * no public constructor since this is a utility class + */ + private Data() { + } + + /** + * The directory twig for this sub-table + */ + public static final String CONTENT_DIRECTORY = "data"; + } + + /** + * A sub-directory of a single raw contact that contains all of their {@link Data} rows. + * To access this directory append {@link Entity#CONTENT_DIRECTORY} to the contact URI. + */ + public static final class Entity implements BaseColumns, DataColumns { + /** + * no public constructor since this is a utility class + */ + private Entity() { + } + + /** + * The directory twig for this sub-table + */ + public static final String CONTENT_DIRECTORY = "entity"; + + /** + * The ID of the data column. The value will be null if this raw contact has no + * data rows. + * <P>Type: INTEGER</P> + */ + public static final String DATA_ID = "data_id"; + } + } + + protected interface StatusColumns extends Im.CommonPresenceColumns { + /** + * Contact's latest presence level. + * <P>Type: INTEGER (one of the values below)</P> + */ + public static final String PRESENCE = PRESENCE_STATUS; + + /** + * Contact latest status update. + * <p>Type: TEXT</p> + */ + public static final String STATUS = PRESENCE_CUSTOM_STATUS; + + /** + * The absolute time in milliseconds when the latest status was inserted/updated. + * <p>Type: NUMBER</p> + */ + public static final String STATUS_TIMESTAMP = "status_ts"; + + /** + * The package containing resources for this status: label and icon. + * <p>Type: NUMBER</p> + */ + public static final String STATUS_RES_PACKAGE = "status_res_package"; + + /** + * The resource ID of the label describing the source of the status update, e.g. "Google + * Talk". This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. + * <p>Type: NUMBER</p> + */ + public static final String STATUS_LABEL = "status_label"; + + /** + * The resource ID of the icon for the source of the status update. + * This resource should be scoped by the {@link #STATUS_RES_PACKAGE}. + * <p>Type: NUMBER</p> + */ + public static final String STATUS_ICON = "status_icon"; + } + + protected interface DataColumns { + /** + * The package name to use when creating {@link Resources} objects for + * this data row. This value is only designed for use when building user + * interfaces, and should not be used to infer the owner. + * + * @hide + */ + public static final String RES_PACKAGE = "res_package"; + + /** + * The MIME type of the item represented by this row. + */ + public static final String MIMETYPE = "mimetype"; + + /** + * A reference to the {@link RawContacts#_ID} + * that this data belongs to. + */ + public static final String RAW_CONTACT_ID = "raw_contact_id"; + + /** + * Whether this is the primary entry of its kind for the raw contact it belongs to + * <P>Type: INTEGER (if set, non-0 means true)</P> + */ + public static final String IS_PRIMARY = "is_primary"; + + /** + * Whether this is the primary entry of its kind for the aggregate + * contact it belongs to. Any data record that is "super primary" must + * also be "primary". + * <P>Type: INTEGER (if set, non-0 means true)</P> + */ + public static final String IS_SUPER_PRIMARY = "is_super_primary"; + + /** + * The version of this data record. This is a read-only value. The data column is + * guaranteed to not change without the version going up. This value is monotonically + * increasing. + * <P>Type: INTEGER</P> + */ + public static final String DATA_VERSION = "data_version"; + + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA1 = "data1"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA2 = "data2"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA3 = "data3"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA4 = "data4"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA5 = "data5"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA6 = "data6"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA7 = "data7"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA8 = "data8"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA9 = "data9"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA10 = "data10"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA11 = "data11"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA12 = "data12"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA13 = "data13"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA14 = "data14"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA15 = "data15"; + + /** Generic column for use by sync adapters. */ + public static final String SYNC1 = "data_sync1"; + /** Generic column for use by sync adapters. */ + public static final String SYNC2 = "data_sync2"; + /** Generic column for use by sync adapters. */ + public static final String SYNC3 = "data_sync3"; + /** Generic column for use by sync adapters. */ + public static final String SYNC4 = "data_sync4"; + } + + /** + * Combines all columns returned by {@link Data} table queries. + */ + protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns, + RawContactsColumns, ContactsColumns, ContactOptionsColumns, ContactStatusColumns { + + } + + /** + * Constants for the data table, which contains data points tied to a raw contact. + * For example, a phone number or email address. Each row in this table contains a type + * definition and some generic columns. Each data type can define the meaning for each of + * the generic columns. + */ + public final static class Data implements DataColumnsWithJoins { + /** + * This utility class cannot be instantiated + */ + private Data() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of data. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; + + /** + * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward + * Data.CONTENT_URI contains only exportable data. + * + * This flag is useful (currently) only for vCard exporter in Contacts app, which + * needs to exclude "un-exportable" data from available data to export, while + * Contacts app itself has priviledge to access all data including "un-expotable" + * ones and providers return all of them regardless of the callers' intention. + * <P>Type: INTEGER</p> + * + * @hide Maybe available only in Eclair and not really ready for public use. + * TODO: remove, or implement this feature completely. As of now (Eclair), + * we only use this flag in queryEntities(), not query(). + */ + public static final String FOR_EXPORT_ONLY = "for_export_only"; + + /** + * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} + * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} + * entry of the given {@link Data} entry. + */ + public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { + final Cursor cursor = resolver.query(dataUri, new String[] { + RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY + }, null, null, null); + + Uri lookupUri = null; + try { + if (cursor != null && cursor.moveToFirst()) { + final long contactId = cursor.getLong(0); + final String lookupKey = cursor.getString(1); + return Contacts.getLookupUri(contactId, lookupKey); + } + } finally { + if (cursor != null) cursor.close(); + } + return lookupUri; + } + } + + /** + * Constants for the raw contacts entities table, which can be though of as an outer join + * of the raw_contacts table with the data table. + */ + public final static class RawContactsEntity + implements BaseColumns, DataColumns, RawContactsColumns { + /** + * This utility class cannot be instantiated + */ + private RawContactsEntity() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = + Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of raw contact entities. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity"; + + /** + * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward + * Data.CONTENT_URI contains only exportable data. + * + * This flag is useful (currently) only for vCard exporter in Contacts app, which + * needs to exclude "un-exportable" data from available data to export, while + * Contacts app itself has priviledge to access all data including "un-expotable" + * ones and providers return all of them regardless of the callers' intention. + * <P>Type: INTEGER</p> + * + * @hide Maybe available only in Eclair and not really ready for public use. + * TODO: remove, or implement this feature completely. As of now (Eclair), + * we only use this flag in queryEntities(), not query(). + */ + public static final String FOR_EXPORT_ONLY = "for_export_only"; + + /** + * The ID of the data column. The value will be null if this raw contact has no data rows. + * <P>Type: INTEGER</P> + */ + public static final String DATA_ID = "data_id"; + } + + protected interface PhoneLookupColumns { + /** + * The phone number as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String NUMBER = "number"; + + /** + * The type of phone number, for example Home or Work. + * <P>Type: INTEGER</P> + */ + public static final String TYPE = "type"; + + /** + * The user defined label for the phone number. + * <P>Type: TEXT</P> + */ + public static final String LABEL = "label"; + } + + /** + * A table that represents the result of looking up a phone number, for + * example for caller ID. To perform a lookup you must append the number you + * want to find to {@link #CONTENT_FILTER_URI}. + */ + public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns, + ContactsColumns, ContactOptionsColumns { + /** + * This utility class cannot be instantiated + */ + private PhoneLookup() {} + + /** + * The content:// style URI for this table. Append the phone number you want to lookup + * to this URI and query it to perform a lookup. For example: + * + * {@code + * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, phoneNumber); + * } + */ + public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI, + "phone_lookup"); + } + + /** + * Additional data mixed in with {@link StatusColumns} to link + * back to specific {@link ContactsContract.Data#_ID} entries. + */ + protected interface PresenceColumns { + + /** + * Reference to the {@link Data#_ID} entry that owns this presence. + * <P>Type: INTEGER</P> + */ + public static final String DATA_ID = "presence_data_id"; + + /** + * <p>Type: NUMBER</p> + */ + public static final String PROTOCOL = "protocol"; + + /** + * Name of the custom protocol. Should be supplied along with the {@link #PROTOCOL} value + * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. Should be null or + * omitted if {@link #PROTOCOL} value is not + * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}. + * + * <p>Type: NUMBER</p> + */ + public static final String CUSTOM_PROTOCOL = "custom_protocol"; + + /** + * The IM handle the presence item is for. The handle is scoped to + * {@link #PROTOCOL}. + * <P>Type: TEXT</P> + */ + public static final String IM_HANDLE = "im_handle"; + + /** + * The IM account for the local user that the presence data came from. + * <P>Type: TEXT</P> + */ + public static final String IM_ACCOUNT = "im_account"; + } + + /** + * A status update is linked to a {@link Data} row and captures the user's latest status + * update via the corresponding source, e.g. "Having lunch" via "Google Talk". + */ + // TODO make final as soon as Presence is removed + public static /*final*/ class StatusUpdates implements StatusColumns, PresenceColumns { + + /** + * This utility class cannot be instantiated + */ + private StatusUpdates() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "status_updates"); + + /** + * Gets the resource ID for the proper presence icon. + * + * @param status the status to get the icon for + * @return the resource ID for the proper presence icon + */ + public static final int getPresenceIconResourceId(int status) { + switch (status) { + case AVAILABLE: + return android.R.drawable.presence_online; + case IDLE: + case AWAY: + return android.R.drawable.presence_away; + case DO_NOT_DISTURB: + return android.R.drawable.presence_busy; + case INVISIBLE: + return android.R.drawable.presence_invisible; + case OFFLINE: + default: + return android.R.drawable.presence_offline; + } + } + + /** + * Returns the precedence of the status code the higher number being the higher precedence. + * + * @param status The status code. + * @return An integer representing the precedence, 0 being the lowest. + */ + public static final int getPresencePrecedence(int status) { + // Keep this function here incase we want to enforce a different precedence than the + // natural order of the status constants. + return status; + } + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of + * status update details. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/status-update"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * status update detail. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update"; + } + + @Deprecated + public static final class Presence extends StatusUpdates { + + } + + /** + * Container for definitions of common data types stored in the {@link Data} table. + */ + public static final class CommonDataKinds { + /** + * This utility class cannot be instantiated + */ + private CommonDataKinds() {} + + /** + * The {@link Data#RES_PACKAGE} value for common data that should be + * shown using a default style. + * + * @hide RES_PACKAGE is hidden + */ + public static final String PACKAGE_COMMON = "common"; + + /** + * The base types that all "Typed" data kinds support. + */ + public interface BaseTypes { + /** + * A custom type. The custom label should be supplied by user. + */ + public static int TYPE_CUSTOM = 0; + } + + /** + * Columns common across the specific types. + */ + protected interface CommonColumns extends BaseTypes { + /** + * The data for the contact method. + * <P>Type: TEXT</P> + */ + public static final String DATA = DataColumns.DATA1; + + /** + * The type of data, for example Home or Work. + * <P>Type: INTEGER</P> + */ + public static final String TYPE = DataColumns.DATA2; + + /** + * The user defined label for the the contact method. + * <P>Type: TEXT</P> + */ + public static final String LABEL = DataColumns.DATA3; + } + + /** + * Parts of the name. + */ + public static final class StructuredName implements DataColumnsWithJoins { + /** + * This utility class cannot be instantiated + */ + private StructuredName() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name"; + + /** + * The name that should be used to display the contact. + * <i>Unstructured component of the name should be consistent with + * its structured representation.</i> + * <p> + * Type: TEXT + */ + public static final String DISPLAY_NAME = DATA1; + + /** + * The given name for the contact. + * <P>Type: TEXT</P> + */ + public static final String GIVEN_NAME = DATA2; + + /** + * The family name for the contact. + * <P>Type: TEXT</P> + */ + public static final String FAMILY_NAME = DATA3; + + /** + * The contact's honorific prefix, e.g. "Sir" + * <P>Type: TEXT</P> + */ + public static final String PREFIX = DATA4; + + /** + * The contact's middle name + * <P>Type: TEXT</P> + */ + public static final String MIDDLE_NAME = DATA5; + + /** + * The contact's honorific suffix, e.g. "Jr" + */ + public static final String SUFFIX = DATA6; + + /** + * The phonetic version of the given name for the contact. + * <P>Type: TEXT</P> + */ + public static final String PHONETIC_GIVEN_NAME = DATA7; + + /** + * The phonetic version of the additional name for the contact. + * <P>Type: TEXT</P> + */ + public static final String PHONETIC_MIDDLE_NAME = DATA8; + + /** + * The phonetic version of the family name for the contact. + * <P>Type: TEXT</P> + */ + public static final String PHONETIC_FAMILY_NAME = DATA9; + } + + /** + * A nickname. + */ + public static final class Nickname implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Nickname() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname"; + + public static final int TYPE_DEFAULT = 1; + public static final int TYPE_OTHER_NAME = 2; + public static final int TYPE_MAINDEN_NAME = 3; + public static final int TYPE_SHORT_NAME = 4; + public static final int TYPE_INITIALS = 5; + + /** + * The name itself + */ + public static final String NAME = DATA; + } + + /** + * Common data definition for telephone numbers. + */ + public static final class Phone implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Phone() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2"; + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of + * phones. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2"; + + /** + * The content:// style URI for all data records of the + * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the + * associated raw contact and aggregate contact data. + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, + "phones"); + + /** + * The content:// style URL for phone lookup using a filter. The filter returns + * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied + * to display names as well as phone numbers. The filter argument should be passed + * as an additional path segment after this URI. + */ + public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, + "filter"); + + public static final int TYPE_HOME = 1; + public static final int TYPE_MOBILE = 2; + public static final int TYPE_WORK = 3; + public static final int TYPE_FAX_WORK = 4; + public static final int TYPE_FAX_HOME = 5; + public static final int TYPE_PAGER = 6; + public static final int TYPE_OTHER = 7; + public static final int TYPE_CALLBACK = 8; + public static final int TYPE_CAR = 9; + public static final int TYPE_COMPANY_MAIN = 10; + public static final int TYPE_ISDN = 11; + public static final int TYPE_MAIN = 12; + public static final int TYPE_OTHER_FAX = 13; + public static final int TYPE_RADIO = 14; + public static final int TYPE_TELEX = 15; + public static final int TYPE_TTY_TDD = 16; + public static final int TYPE_WORK_MOBILE = 17; + public static final int TYPE_WORK_PAGER = 18; + public static final int TYPE_ASSISTANT = 19; + public static final int TYPE_MMS = 20; + + /** + * The phone number as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String NUMBER = DATA; + + /** + * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. + * @hide + */ + @Deprecated + public static final CharSequence getDisplayLabel(Context context, int type, + CharSequence label, CharSequence[] labelArray) { + return getTypeLabel(context.getResources(), type, label); + } + + /** + * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead. + * @hide + */ + @Deprecated + public static final CharSequence getDisplayLabel(Context context, int type, + CharSequence label) { + return getTypeLabel(context.getResources(), type, label); + } + + /** + * Return the string resource that best describes the given + * {@link #TYPE}. Will always return a valid resource. + */ + public static final int getTypeLabelResource(int type) { + switch (type) { + case TYPE_HOME: return com.android.internal.R.string.phoneTypeHome; + case TYPE_MOBILE: return com.android.internal.R.string.phoneTypeMobile; + case TYPE_WORK: return com.android.internal.R.string.phoneTypeWork; + case TYPE_FAX_WORK: return com.android.internal.R.string.phoneTypeFaxWork; + case TYPE_FAX_HOME: return com.android.internal.R.string.phoneTypeFaxHome; + case TYPE_PAGER: return com.android.internal.R.string.phoneTypePager; + case TYPE_OTHER: return com.android.internal.R.string.phoneTypeOther; + case TYPE_CALLBACK: return com.android.internal.R.string.phoneTypeCallback; + case TYPE_CAR: return com.android.internal.R.string.phoneTypeCar; + case TYPE_COMPANY_MAIN: return com.android.internal.R.string.phoneTypeCompanyMain; + case TYPE_ISDN: return com.android.internal.R.string.phoneTypeIsdn; + case TYPE_MAIN: return com.android.internal.R.string.phoneTypeMain; + case TYPE_OTHER_FAX: return com.android.internal.R.string.phoneTypeOtherFax; + case TYPE_RADIO: return com.android.internal.R.string.phoneTypeRadio; + case TYPE_TELEX: return com.android.internal.R.string.phoneTypeTelex; + case TYPE_TTY_TDD: return com.android.internal.R.string.phoneTypeTtyTdd; + case TYPE_WORK_MOBILE: return com.android.internal.R.string.phoneTypeWorkMobile; + case TYPE_WORK_PAGER: return com.android.internal.R.string.phoneTypeWorkPager; + case TYPE_ASSISTANT: return com.android.internal.R.string.phoneTypeAssistant; + case TYPE_MMS: return com.android.internal.R.string.phoneTypeMms; + default: return com.android.internal.R.string.phoneTypeCustom; + } + } + + /** + * Return a {@link CharSequence} that best describes the given type, + * possibly substituting the given {@link #LABEL} value + * for {@link #TYPE_CUSTOM}. + */ + public static final CharSequence getTypeLabel(Resources res, int type, + CharSequence label) { + if ((type == TYPE_CUSTOM || type == TYPE_ASSISTANT) && !TextUtils.isEmpty(label)) { + return label; + } else { + final int labelRes = getTypeLabelResource(type); + return res.getText(labelRes); + } + } + } + + /** + * Common data definition for email addresses. + */ + public static final class Email implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Email() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2"; + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of email addresses. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2"; + + /** + * The content:// style URI for all data records of the + * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the + * associated raw contact and aggregate contact data. + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, + "emails"); + + /** + * The content:// style URL for looking up data rows by email address. The + * lookup argument, an email address, should be passed as an additional path segment + * after this URI. + */ + public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI, + "lookup"); + + /** + * The content:// style URL for email lookup using a filter. The filter returns + * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied + * to display names as well as email addresses. The filter argument should be passed + * as an additional path segment after this URI. + */ + public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI, + "filter"); + + public static final int TYPE_HOME = 1; + public static final int TYPE_WORK = 2; + public static final int TYPE_OTHER = 3; + public static final int TYPE_MOBILE = 4; + + /** + * The display name for the email address + * <P>Type: TEXT</P> + */ + public static final String DISPLAY_NAME = DATA4; + + /** + * Return the string resource that best describes the given + * {@link #TYPE}. Will always return a valid resource. + */ + public static final int getTypeLabelResource(int type) { + switch (type) { + case TYPE_HOME: return com.android.internal.R.string.emailTypeHome; + case TYPE_WORK: return com.android.internal.R.string.emailTypeWork; + case TYPE_OTHER: return com.android.internal.R.string.emailTypeOther; + case TYPE_MOBILE: return com.android.internal.R.string.emailTypeMobile; + default: return com.android.internal.R.string.emailTypeCustom; + } + } + + /** + * Return a {@link CharSequence} that best describes the given type, + * possibly substituting the given {@link #LABEL} value + * for {@link #TYPE_CUSTOM}. + */ + public static final CharSequence getTypeLabel(Resources res, int type, + CharSequence label) { + if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { + return label; + } else { + final int labelRes = getTypeLabelResource(type); + return res.getText(labelRes); + } + } + } + + /** + * Common data definition for postal addresses. + */ + public static final class StructuredPostal implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private StructuredPostal() { + } + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = + "vnd.android.cursor.item/postal-address_v2"; + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of + * postal addresses. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2"; + + /** + * The content:// style URI for all data records of the + * {@link StructuredPostal#CONTENT_ITEM_TYPE} MIME type. + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI, + "postals"); + + public static final int TYPE_HOME = 1; + public static final int TYPE_WORK = 2; + public static final int TYPE_OTHER = 3; + + /** + * The full, unstructured postal address. <i>This field must be + * consistent with any structured data.</i> + * <p> + * Type: TEXT + */ + public static final String FORMATTED_ADDRESS = DATA; + + /** + * Can be street, avenue, road, etc. This element also includes the + * house number and room/apartment/flat/floor number. + * <p> + * Type: TEXT + */ + public static final String STREET = DATA4; + + /** + * Covers actual P.O. boxes, drawers, locked bags, etc. This is + * usually but not always mutually exclusive with street. + * <p> + * Type: TEXT + */ + public static final String POBOX = DATA5; + + /** + * This is used to disambiguate a street address when a city + * contains more than one street with the same name, or to specify a + * small place whose mail is routed through a larger postal town. In + * China it could be a county or a minor city. + * <p> + * Type: TEXT + */ + public static final String NEIGHBORHOOD = DATA6; + + /** + * Can be city, village, town, borough, etc. This is the postal town + * and not necessarily the place of residence or place of business. + * <p> + * Type: TEXT + */ + public static final String CITY = DATA7; + + /** + * A state, province, county (in Ireland), Land (in Germany), + * departement (in France), etc. + * <p> + * Type: TEXT + */ + public static final String REGION = DATA8; + + /** + * Postal code. Usually country-wide, but sometimes specific to the + * city (e.g. "2" in "Dublin 2, Ireland" addresses). + * <p> + * Type: TEXT + */ + public static final String POSTCODE = DATA9; + + /** + * The name or code of the country. + * <p> + * Type: TEXT + */ + public static final String COUNTRY = DATA10; + + /** + * Return the string resource that best describes the given + * {@link #TYPE}. Will always return a valid resource. + */ + public static final int getTypeLabelResource(int type) { + switch (type) { + case TYPE_HOME: return com.android.internal.R.string.postalTypeHome; + case TYPE_WORK: return com.android.internal.R.string.postalTypeWork; + case TYPE_OTHER: return com.android.internal.R.string.postalTypeOther; + default: return com.android.internal.R.string.postalTypeCustom; + } + } + + /** + * Return a {@link CharSequence} that best describes the given type, + * possibly substituting the given {@link #LABEL} value + * for {@link #TYPE_CUSTOM}. + */ + public static final CharSequence getTypeLabel(Resources res, int type, + CharSequence label) { + if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { + return label; + } else { + final int labelRes = getTypeLabelResource(type); + return res.getText(labelRes); + } + } + } + + /** + * Common data definition for IM addresses. + */ + public static final class Im implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Im() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im"; + + public static final int TYPE_HOME = 1; + public static final int TYPE_WORK = 2; + public static final int TYPE_OTHER = 3; + + /** + * This column should be populated with one of the defined + * constants, e.g. {@link #PROTOCOL_YAHOO}. If the value of this + * column is {@link #PROTOCOL_CUSTOM}, the {@link #CUSTOM_PROTOCOL} + * should contain the name of the custom protocol. + */ + public static final String PROTOCOL = DATA5; + + public static final String CUSTOM_PROTOCOL = DATA6; + + /* + * The predefined IM protocol types. + */ + public static final int PROTOCOL_CUSTOM = -1; + public static final int PROTOCOL_AIM = 0; + public static final int PROTOCOL_MSN = 1; + public static final int PROTOCOL_YAHOO = 2; + public static final int PROTOCOL_SKYPE = 3; + public static final int PROTOCOL_QQ = 4; + public static final int PROTOCOL_GOOGLE_TALK = 5; + public static final int PROTOCOL_ICQ = 6; + public static final int PROTOCOL_JABBER = 7; + public static final int PROTOCOL_NETMEETING = 8; + + /** + * Return the string resource that best describes the given + * {@link #TYPE}. Will always return a valid resource. + */ + public static final int getTypeLabelResource(int type) { + switch (type) { + case TYPE_HOME: return com.android.internal.R.string.imTypeHome; + case TYPE_WORK: return com.android.internal.R.string.imTypeWork; + case TYPE_OTHER: return com.android.internal.R.string.imTypeOther; + default: return com.android.internal.R.string.imTypeCustom; + } + } + + /** + * Return a {@link CharSequence} that best describes the given type, + * possibly substituting the given {@link #LABEL} value + * for {@link #TYPE_CUSTOM}. + */ + public static final CharSequence getTypeLabel(Resources res, int type, + CharSequence label) { + if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { + return label; + } else { + final int labelRes = getTypeLabelResource(type); + return res.getText(labelRes); + } + } + + /** + * Return the string resource that best describes the given + * {@link #PROTOCOL}. Will always return a valid resource. + */ + public static final int getProtocolLabelResource(int type) { + switch (type) { + case PROTOCOL_AIM: return com.android.internal.R.string.imProtocolAim; + case PROTOCOL_MSN: return com.android.internal.R.string.imProtocolMsn; + case PROTOCOL_YAHOO: return com.android.internal.R.string.imProtocolYahoo; + case PROTOCOL_SKYPE: return com.android.internal.R.string.imProtocolSkype; + case PROTOCOL_QQ: return com.android.internal.R.string.imProtocolQq; + case PROTOCOL_GOOGLE_TALK: return com.android.internal.R.string.imProtocolGoogleTalk; + case PROTOCOL_ICQ: return com.android.internal.R.string.imProtocolIcq; + case PROTOCOL_JABBER: return com.android.internal.R.string.imProtocolJabber; + case PROTOCOL_NETMEETING: return com.android.internal.R.string.imProtocolNetMeeting; + default: return com.android.internal.R.string.imProtocolCustom; + } + } + + /** + * Return a {@link CharSequence} that best describes the given + * protocol, possibly substituting the given + * {@link #CUSTOM_PROTOCOL} value for {@link #PROTOCOL_CUSTOM}. + */ + public static final CharSequence getProtocolLabel(Resources res, int type, + CharSequence label) { + if (type == PROTOCOL_CUSTOM && !TextUtils.isEmpty(label)) { + return label; + } else { + final int labelRes = getProtocolLabelResource(type); + return res.getText(labelRes); + } + } + } + + /** + * Common data definition for organizations. + */ + public static final class Organization implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Organization() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization"; + + public static final int TYPE_WORK = 1; + public static final int TYPE_OTHER = 2; + + /** + * The company as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String COMPANY = DATA; + + /** + * The position title at this company as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String TITLE = DATA4; + + /** + * The department at this company as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String DEPARTMENT = DATA5; + + /** + * The job description at this company as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String JOB_DESCRIPTION = DATA6; + + /** + * The symbol of this company as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String SYMBOL = DATA7; + + /** + * The phonetic name of this company as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String PHONETIC_NAME = DATA8; + + /** + * The office location of this organization. + * <P>Type: TEXT</P> + */ + public static final String OFFICE_LOCATION = DATA9; + + /** + * Return the string resource that best describes the given + * {@link #TYPE}. Will always return a valid resource. + */ + public static final int getTypeLabelResource(int type) { + switch (type) { + case TYPE_WORK: return com.android.internal.R.string.orgTypeWork; + case TYPE_OTHER: return com.android.internal.R.string.orgTypeOther; + default: return com.android.internal.R.string.orgTypeCustom; + } + } + + /** + * Return a {@link CharSequence} that best describes the given type, + * possibly substituting the given {@link #LABEL} value + * for {@link #TYPE_CUSTOM}. + */ + public static final CharSequence getTypeLabel(Resources res, int type, + CharSequence label) { + if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) { + return label; + } else { + final int labelRes = getTypeLabelResource(type); + return res.getText(labelRes); + } + } + } + + /** + * Common data definition for relations. + */ + public static final class Relation implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Relation() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation"; + + public static final int TYPE_ASSISTANT = 1; + public static final int TYPE_BROTHER = 2; + public static final int TYPE_CHILD = 3; + public static final int TYPE_DOMESTIC_PARTNER = 4; + public static final int TYPE_FATHER = 5; + public static final int TYPE_FRIEND = 6; + public static final int TYPE_MANAGER = 7; + public static final int TYPE_MOTHER = 8; + public static final int TYPE_PARENT = 9; + public static final int TYPE_PARTNER = 10; + public static final int TYPE_REFERRED_BY = 11; + public static final int TYPE_RELATIVE = 12; + public static final int TYPE_SISTER = 13; + public static final int TYPE_SPOUSE = 14; + + /** + * The name of the relative as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String NAME = DATA; + } + + /** + * Common data definition for events. + */ + public static final class Event implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Event() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event"; + + public static final int TYPE_ANNIVERSARY = 1; + public static final int TYPE_OTHER = 2; + public static final int TYPE_BIRTHDAY = 3; + + /** + * The event start date as the user entered it. + * <P>Type: TEXT</P> + */ + public static final String START_DATE = DATA; + + /** + * Return the string resource that best describes the given + * {@link #TYPE}. Will always return a valid resource. + */ + public static int getTypeResource(Integer type) { + if (type == null) { + return com.android.internal.R.string.eventTypeOther; + } + switch (type) { + case TYPE_ANNIVERSARY: + return com.android.internal.R.string.eventTypeAnniversary; + case TYPE_BIRTHDAY: return com.android.internal.R.string.eventTypeBirthday; + case TYPE_OTHER: return com.android.internal.R.string.eventTypeOther; + default: return com.android.internal.R.string.eventTypeOther; + } + } + } + + /** + * Photo of the contact. + */ + public static final class Photo implements DataColumnsWithJoins { + /** + * This utility class cannot be instantiated + */ + private Photo() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo"; + + /** + * Thumbnail photo of the raw contact. This is the raw bytes of an image + * that could be inflated using {@link android.graphics.BitmapFactory}. + * <p> + * Type: BLOB + */ + public static final String PHOTO = DATA15; + } + + /** + * Notes about the contact. + */ + public static final class Note implements DataColumnsWithJoins { + /** + * This utility class cannot be instantiated + */ + private Note() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note"; + + /** + * The note text. + * <P>Type: TEXT</P> + */ + public static final String NOTE = DATA1; + } + + /** + * Group Membership. + */ + public static final class GroupMembership implements DataColumnsWithJoins { + /** + * This utility class cannot be instantiated + */ + private GroupMembership() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = + "vnd.android.cursor.item/group_membership"; + + /** + * The row id of the group that this group membership refers to. Exactly one of + * this or {@link #GROUP_SOURCE_ID} must be set when inserting a row. + * <P>Type: INTEGER</P> + */ + public static final String GROUP_ROW_ID = DATA1; + + /** + * The sourceid of the group that this group membership refers to. Exactly one of + * this or {@link #GROUP_ROW_ID} must be set when inserting a row. + * <P>Type: TEXT</P> + */ + public static final String GROUP_SOURCE_ID = "group_sourceid"; + } + + /** + * Website related to the contact. + */ + public static final class Website implements DataColumnsWithJoins, CommonColumns { + /** + * This utility class cannot be instantiated + */ + private Website() {} + + /** MIME type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website"; + + public static final int TYPE_HOMEPAGE = 1; + public static final int TYPE_BLOG = 2; + public static final int TYPE_PROFILE = 3; + public static final int TYPE_HOME = 4; + public static final int TYPE_WORK = 5; + public static final int TYPE_FTP = 6; + public static final int TYPE_OTHER = 7; + + /** + * The website URL string. + * <P>Type: TEXT</P> + */ + public static final String URL = DATA; + } + } + + protected interface GroupsColumns { + /** + * The display title of this group. + * <p> + * Type: TEXT + */ + public static final String TITLE = "title"; + + /** + * The package name to use when creating {@link Resources} objects for + * this group. This value is only designed for use when building user + * interfaces, and should not be used to infer the owner. + * + * @hide + */ + public static final String RES_PACKAGE = "res_package"; + + /** + * The display title of this group to load as a resource from + * {@link #RES_PACKAGE}, which may be localized. + * <P>Type: TEXT</P> + * + * @hide + */ + public static final String TITLE_RES = "title_res"; + + /** + * Notes about the group. + * <p> + * Type: TEXT + */ + public static final String NOTES = "notes"; + + /** + * The ID of this group if it is a System Group, i.e. a group that has a special meaning + * to the sync adapter, null otherwise. + * <P>Type: TEXT</P> + */ + public static final String SYSTEM_ID = "system_id"; + + /** + * The total number of {@link Contacts} that have + * {@link CommonDataKinds.GroupMembership} in this group. Read-only value that is only + * present when querying {@link Groups#CONTENT_SUMMARY_URI}. + * <p> + * Type: INTEGER + */ + public static final String SUMMARY_COUNT = "summ_count"; + + /** + * The total number of {@link Contacts} that have both + * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers. + * Read-only value that is only present when querying + * {@link Groups#CONTENT_SUMMARY_URI}. + * <p> + * Type: INTEGER + */ + public static final String SUMMARY_WITH_PHONES = "summ_phones"; + + /** + * Flag indicating if the contacts belonging to this group should be + * visible in any user interface. + * <p> + * Type: INTEGER (boolean) + */ + public static final String GROUP_VISIBLE = "group_visible"; + + /** + * The "deleted" flag: "0" by default, "1" if the row has been marked + * for deletion. When {@link android.content.ContentResolver#delete} is + * called on a raw contact, it is marked for deletion and removed from its + * aggregate contact. The sync adaptor deletes the raw contact on the server and + * then calls ContactResolver.delete once more, this time setting the the + * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize + * the data removal. + * <P>Type: INTEGER</P> + */ + public static final String DELETED = "deleted"; + + /** + * Whether this group should be synced if the SYNC_EVERYTHING settings + * is false for this group's account. + * <p> + * Type: INTEGER (boolean) + */ + public static final String SHOULD_SYNC = "should_sync"; + } + + /** + * Constants for the groups table. + */ + public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns { + /** + * This utility class cannot be instantiated + */ + private Groups() { + } + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "groups"); + + /** + * The content:// style URI for this table joined with details data from + * {@link Data}. + */ + public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI, + "groups_summary"); + + /** + * The MIME type of a directory of groups. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/group"; + + /** + * The MIME type of a single group. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group"; + } + + /** + * Constants for the contact aggregation exceptions table, which contains + * aggregation rules overriding those used by automatic aggregation. This type only + * supports query and update. Neither insert nor delete are supported. + */ + public static final class AggregationExceptions implements BaseColumns { + /** + * This utility class cannot be instantiated + */ + private AggregationExceptions() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = + Uri.withAppendedPath(AUTHORITY_URI, "aggregation_exceptions"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of data. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of an aggregation exception + */ + public static final String CONTENT_ITEM_TYPE = + "vnd.android.cursor.item/aggregation_exception"; + + /** + * The type of exception: {@link #TYPE_KEEP_TOGETHER}, {@link #TYPE_KEEP_SEPARATE} or + * {@link #TYPE_AUTOMATIC}. + * + * <P>Type: INTEGER</P> + */ + public static final String TYPE = "type"; + + /** + * Allows the provider to automatically decide whether the specified raw contacts should + * be included in the same aggregate contact or not. + */ + public static final int TYPE_AUTOMATIC = 0; + + /** + * Makes sure that the specified raw contacts are included in the same + * aggregate contact. + */ + public static final int TYPE_KEEP_TOGETHER = 1; + + /** + * Makes sure that the specified raw contacts are NOT included in the same + * aggregate contact. + */ + public static final int TYPE_KEEP_SEPARATE = 2; + + /** + * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to. + */ + public static final String RAW_CONTACT_ID1 = "raw_contact_id1"; + + /** + * A reference to the other {@link RawContacts#_ID} of the raw contact that the rule + * applies to. + */ + public static final String RAW_CONTACT_ID2 = "raw_contact_id2"; + } + + protected interface SettingsColumns { + /** + * The name of the account instance to which this row belongs. + * <P>Type: TEXT</P> + */ + public static final String ACCOUNT_NAME = "account_name"; + + /** + * The type of account to which this row belongs, which when paired with + * {@link #ACCOUNT_NAME} identifies a specific account. + * <P>Type: TEXT</P> + */ + public static final String ACCOUNT_TYPE = "account_type"; + + /** + * Depending on the mode defined by the sync-adapter, this flag controls + * the top-level sync behavior for this data source. + * <p> + * Type: INTEGER (boolean) + */ + public static final String SHOULD_SYNC = "should_sync"; + + /** + * Flag indicating if contacts without any {@link CommonDataKinds.GroupMembership} + * entries should be visible in any user interface. + * <p> + * Type: INTEGER (boolean) + */ + public static final String UNGROUPED_VISIBLE = "ungrouped_visible"; + + /** + * Read-only flag indicating if this {@link #SHOULD_SYNC} or any + * {@link Groups#SHOULD_SYNC} under this account have been marked as + * unsynced. + */ + public static final String ANY_UNSYNCED = "any_unsynced"; + + /** + * Read-only count of {@link Contacts} from a specific source that have + * no {@link CommonDataKinds.GroupMembership} entries. + * <p> + * Type: INTEGER + */ + public static final String UNGROUPED_COUNT = "summ_count"; + + /** + * Read-only count of {@link Contacts} from a specific source that have + * no {@link CommonDataKinds.GroupMembership} entries, and also have phone numbers. + * <p> + * Type: INTEGER + */ + public static final String UNGROUPED_WITH_PHONES = "summ_phones"; + } + + /** + * Contacts-specific settings for various {@link Account}. + */ + public static final class Settings implements SettingsColumns { + /** + * This utility class cannot be instantiated + */ + private Settings() { + } + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = + Uri.withAppendedPath(AUTHORITY_URI, "settings"); + + /** + * The MIME-type of {@link #CONTENT_URI} providing a directory of + * settings. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting"; + + /** + * The MIME-type of {@link #CONTENT_URI} providing a single setting. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting"; + } + + /** + * Helper methods to display QuickContact dialogs that allow users to pivot on + * a specific {@link Contacts} entry. + */ + public static final class QuickContact { + /** + * Action used to trigger person pivot dialog. + * @hide + */ + public static final String ACTION_QUICK_CONTACT = + "com.android.contacts.action.QUICK_CONTACT"; + + /** + * Extra used to specify pivot dialog location in screen coordinates. + * @hide + */ + public static final String EXTRA_TARGET_RECT = "target_rect"; + + /** + * Extra used to specify size of pivot dialog. + * @hide + */ + public static final String EXTRA_MODE = "mode"; + + /** + * Extra used to indicate a list of specific MIME-types to exclude and + * not display. Stored as a {@link String} array. + * @hide + */ + public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes"; + + /** + * Small QuickContact mode, usually presented with minimal actions. + */ + public static final int MODE_SMALL = 1; + + /** + * Medium QuickContact mode, includes actions and light summary describing + * the {@link Contacts} entry being shown. This may include social + * status and presence details. + */ + public static final int MODE_MEDIUM = 2; + + /** + * Large QuickContact mode, includes actions and larger, card-like summary + * of the {@link Contacts} entry being shown. This may include detailed + * information, such as a photo. + */ + public static final int MODE_LARGE = 3; + + /** + * Trigger a dialog that lists the various methods of interacting with + * the requested {@link Contacts} entry. This may be based on available + * {@link Data} rows under that contact, and may also include social + * status and presence details. + * + * @param context The parent {@link Context} that may be used as the + * parent for this dialog. + * @param target Specific {@link View} from your layout that this dialog + * should be centered around. In particular, if the dialog + * has a "callout" arrow, it will be pointed and centered + * around this {@link View}. + * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style + * {@link Uri} that describes a specific contact to feature + * in this dialog. + * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or + * {@link #MODE_LARGE}, indicating the desired dialog size, + * when supported. + * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types + * to exclude when showing this dialog. For example, when + * already viewing the contact details card, this can be used + * to omit the details entry from the dialog. + */ + public static void showQuickContact(Context context, View target, Uri lookupUri, int mode, + String[] excludeMimes) { + // Find location and bounds of target view + final int[] location = new int[2]; + target.getLocationOnScreen(location); + + final Rect rect = new Rect(); + rect.left = location[0]; + rect.top = location[1]; + rect.right = rect.left + target.getWidth(); + rect.bottom = rect.top + target.getHeight(); + + // Trigger with obtained rectangle + showQuickContact(context, rect, lookupUri, mode, excludeMimes); + } + + /** + * Trigger a dialog that lists the various methods of interacting with + * the requested {@link Contacts} entry. This may be based on available + * {@link Data} rows under that contact, and may also include social + * status and presence details. + * + * @param context The parent {@link Context} that may be used as the + * parent for this dialog. + * @param target Specific {@link Rect} that this dialog should be + * centered around, in screen coordinates. In particular, if + * the dialog has a "callout" arrow, it will be pointed and + * centered around this {@link Rect}. + * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style + * {@link Uri} that describes a specific contact to feature + * in this dialog. + * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or + * {@link #MODE_LARGE}, indicating the desired dialog size, + * when supported. + * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types + * to exclude when showing this dialog. For example, when + * already viewing the contact details card, this can be used + * to omit the details entry from the dialog. + */ + public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode, + String[] excludeMimes) { + // Launch pivot dialog through intent for now + final Intent intent = new Intent(ACTION_QUICK_CONTACT); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + + intent.setData(lookupUri); + intent.putExtra(EXTRA_TARGET_RECT, target); + intent.putExtra(EXTRA_MODE, mode); + intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes); + context.startActivity(intent); + } + } + + /** + * Contains helper classes used to create or manage {@link android.content.Intent Intents} + * that involve contacts. + */ + public static final class Intents { + /** + * This is the intent that is fired when a search suggestion is clicked on. + */ + public static final String SEARCH_SUGGESTION_CLICKED = + "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED"; + + /** + * This is the intent that is fired when a search suggestion for dialing a number + * is clicked on. + */ + public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = + "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED"; + + /** + * This is the intent that is fired when a search suggestion for creating a contact + * is clicked on. + */ + public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = + "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED"; + + /** + * Starts an Activity that lets the user pick a contact to attach an image to. + * After picking the contact it launches the image cropper in face detection mode. + */ + public static final String ATTACH_IMAGE = + "com.android.contacts.action.ATTACH_IMAGE"; + + /** + * Takes as input a data URI with a mailto: or tel: scheme. If a single + * contact exists with the given data it will be shown. If no contact + * exists, a dialog will ask the user if they want to create a new + * contact with the provided details filled in. If multiple contacts + * share the data the user will be prompted to pick which contact they + * want to view. + * <p> + * For <code>mailto:</code> URIs, the scheme specific portion must be a + * raw email address, such as one built using + * {@link Uri#fromParts(String, String, String)}. + * <p> + * For <code>tel:</code> URIs, the scheme specific portion is compared + * to existing numbers using the standard caller ID lookup algorithm. + * The number must be properly encoded, for example using + * {@link Uri#fromParts(String, String, String)}. + * <p> + * Any extras from the {@link Insert} class will be passed along to the + * create activity if there are no contacts to show. + * <p> + * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip + * prompting the user when the contact doesn't exist. + */ + public static final String SHOW_OR_CREATE_CONTACT = + "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; + + /** + * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new + * contact if no matching contact found. Otherwise, default behavior is + * to prompt user with dialog before creating. + * <p> + * Type: BOOLEAN + */ + public static final String EXTRA_FORCE_CREATE = + "com.android.contacts.action.FORCE_CREATE"; + + /** + * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact + * description to be shown when prompting user about creating a new + * contact. + * <p> + * Type: STRING + */ + public static final String EXTRA_CREATE_DESCRIPTION = + "com.android.contacts.action.CREATE_DESCRIPTION"; + + /** + * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a + * dialog location using screen coordinates. When not specified, the + * dialog will be centered. + * + * @hide + */ + @Deprecated + public static final String EXTRA_TARGET_RECT = "target_rect"; + + /** + * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a + * desired dialog style, usually a variation on size. One of + * {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}. + * + * @hide + */ + @Deprecated + public static final String EXTRA_MODE = "mode"; + + /** + * Value for {@link #EXTRA_MODE} to show a small-sized dialog. + * + * @hide + */ + @Deprecated + public static final int MODE_SMALL = 1; + + /** + * Value for {@link #EXTRA_MODE} to show a medium-sized dialog. + * + * @hide + */ + @Deprecated + public static final int MODE_MEDIUM = 2; + + /** + * Value for {@link #EXTRA_MODE} to show a large-sized dialog. + * + * @hide + */ + @Deprecated + public static final int MODE_LARGE = 3; + + /** + * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to indicate + * a list of specific MIME-types to exclude and not display. Stored as a + * {@link String} array. + * + * @hide + */ + @Deprecated + public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes"; + + /** + * Intents related to the Contacts app UI. + * + * @hide + */ + public static final class UI { + /** + * The action for the default contacts list tab. + */ + public static final String LIST_DEFAULT = + "com.android.contacts.action.LIST_DEFAULT"; + + /** + * The action for the contacts list tab. + */ + public static final String LIST_GROUP_ACTION = + "com.android.contacts.action.LIST_GROUP"; + + /** + * When in LIST_GROUP_ACTION mode, this is the group to display. + */ + public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP"; + + /** + * The action for the all contacts list tab. + */ + public static final String LIST_ALL_CONTACTS_ACTION = + "com.android.contacts.action.LIST_ALL_CONTACTS"; + + /** + * The action for the contacts with phone numbers list tab. + */ + public static final String LIST_CONTACTS_WITH_PHONES_ACTION = + "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES"; + + /** + * The action for the starred contacts list tab. + */ + public static final String LIST_STARRED_ACTION = + "com.android.contacts.action.LIST_STARRED"; + + /** + * The action for the frequent contacts list tab. + */ + public static final String LIST_FREQUENT_ACTION = + "com.android.contacts.action.LIST_FREQUENT"; + + /** + * The action for the "strequent" contacts list tab. It first lists the starred + * contacts in alphabetical order and then the frequent contacts in descending + * order of the number of times they have been contacted. + */ + public static final String LIST_STREQUENT_ACTION = + "com.android.contacts.action.LIST_STREQUENT"; + + /** + * A key for to be used as an intent extra to set the activity + * title to a custom String value. + */ + public static final String TITLE_EXTRA_KEY = + "com.android.contacts.extra.TITLE_EXTRA"; + + /** + * Activity Action: Display a filtered list of contacts + * <p> + * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for + * filtering + * <p> + * Output: Nothing. + */ + public static final String FILTER_CONTACTS_ACTION = + "com.android.contacts.action.FILTER_CONTACTS"; + + /** + * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION} + * intents to supply the text on which to filter. + */ + public static final String FILTER_TEXT_EXTRA_KEY = + "com.android.contacts.extra.FILTER_TEXT"; + } + + /** + * Convenience class that contains string constants used + * to create contact {@link android.content.Intent Intents}. + */ + public static final class Insert { + /** The action code to use when adding a contact */ + public static final String ACTION = Intent.ACTION_INSERT; + + /** + * If present, forces a bypass of quick insert mode. + */ + public static final String FULL_MODE = "full_mode"; + + /** + * The extra field for the contact name. + * <P>Type: String</P> + */ + public static final String NAME = "name"; + + // TODO add structured name values here. + + /** + * The extra field for the contact phonetic name. + * <P>Type: String</P> + */ + public static final String PHONETIC_NAME = "phonetic_name"; + + /** + * The extra field for the contact company. + * <P>Type: String</P> + */ + public static final String COMPANY = "company"; + + /** + * The extra field for the contact job title. + * <P>Type: String</P> + */ + public static final String JOB_TITLE = "job_title"; + + /** + * The extra field for the contact notes. + * <P>Type: String</P> + */ + public static final String NOTES = "notes"; + + /** + * The extra field for the contact phone number. + * <P>Type: String</P> + */ + public static final String PHONE = "phone"; + + /** + * The extra field for the contact phone number type. + * <P>Type: Either an integer value from + * {@link android.provider.Contacts.PhonesColumns PhonesColumns}, + * or a string specifying a custom label.</P> + */ + public static final String PHONE_TYPE = "phone_type"; + + /** + * The extra field for the phone isprimary flag. + * <P>Type: boolean</P> + */ + public static final String PHONE_ISPRIMARY = "phone_isprimary"; + + /** + * The extra field for an optional second contact phone number. + * <P>Type: String</P> + */ + public static final String SECONDARY_PHONE = "secondary_phone"; + + /** + * The extra field for an optional second contact phone number type. + * <P>Type: Either an integer value from + * {@link android.provider.Contacts.PhonesColumns PhonesColumns}, + * or a string specifying a custom label.</P> + */ + public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type"; + + /** + * The extra field for an optional third contact phone number. + * <P>Type: String</P> + */ + public static final String TERTIARY_PHONE = "tertiary_phone"; + + /** + * The extra field for an optional third contact phone number type. + * <P>Type: Either an integer value from + * {@link android.provider.Contacts.PhonesColumns PhonesColumns}, + * or a string specifying a custom label.</P> + */ + public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type"; + + /** + * The extra field for the contact email address. + * <P>Type: String</P> + */ + public static final String EMAIL = "email"; + + /** + * The extra field for the contact email type. + * <P>Type: Either an integer value from + * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} + * or a string specifying a custom label.</P> + */ + public static final String EMAIL_TYPE = "email_type"; + + /** + * The extra field for the email isprimary flag. + * <P>Type: boolean</P> + */ + public static final String EMAIL_ISPRIMARY = "email_isprimary"; + + /** + * The extra field for an optional second contact email address. + * <P>Type: String</P> + */ + public static final String SECONDARY_EMAIL = "secondary_email"; + + /** + * The extra field for an optional second contact email type. + * <P>Type: Either an integer value from + * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} + * or a string specifying a custom label.</P> + */ + public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type"; + + /** + * The extra field for an optional third contact email address. + * <P>Type: String</P> + */ + public static final String TERTIARY_EMAIL = "tertiary_email"; + + /** + * The extra field for an optional third contact email type. + * <P>Type: Either an integer value from + * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} + * or a string specifying a custom label.</P> + */ + public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type"; + + /** + * The extra field for the contact postal address. + * <P>Type: String</P> + */ + public static final String POSTAL = "postal"; + + /** + * The extra field for the contact postal address type. + * <P>Type: Either an integer value from + * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns} + * or a string specifying a custom label.</P> + */ + public static final String POSTAL_TYPE = "postal_type"; + + /** + * The extra field for the postal isprimary flag. + * <P>Type: boolean</P> + */ + public static final String POSTAL_ISPRIMARY = "postal_isprimary"; + + /** + * The extra field for an IM handle. + * <P>Type: String</P> + */ + public static final String IM_HANDLE = "im_handle"; + + /** + * The extra field for the IM protocol + */ + public static final String IM_PROTOCOL = "im_protocol"; + + /** + * The extra field for the IM isprimary flag. + * <P>Type: boolean</P> + */ + public static final String IM_ISPRIMARY = "im_isprimary"; + } + } + +} diff --git a/core/java/android/provider/DrmStore.java b/core/java/android/provider/DrmStore.java index db71854..c438ac4 100644 --- a/core/java/android/provider/DrmStore.java +++ b/core/java/android/provider/DrmStore.java @@ -35,7 +35,7 @@ import java.io.OutputStream; /** * The DRM provider contains forward locked DRM content. - * + * * @hide */ public final class DrmStore @@ -43,13 +43,13 @@ public final class DrmStore private static final String TAG = "DrmStore"; public static final String AUTHORITY = "drm"; - + /** * This is in the Manifest class of the drm provider, but that isn't visible * in the framework. */ private static final String ACCESS_DRM_PERMISSION = "android.permission.ACCESS_DRM"; - + /** * Fields for DRM database */ @@ -82,18 +82,18 @@ public final class DrmStore } public interface Images extends Columns { - + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/images"); } - + public interface Audio extends Columns { - + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/audio"); } /** * Utility function for inserting a file into the DRM content provider. - * + * * @param cr The content resolver to use * @param file The file to insert * @param title The title for the content (or null) @@ -101,12 +101,46 @@ public final class DrmStore */ public static final Intent addDrmFile(ContentResolver cr, File file, String title) { FileInputStream fis = null; - OutputStream os = null; Intent result = null; try { fis = new FileInputStream(file); - DrmRawContent content = new DrmRawContent(fis, (int) file.length(), + if (title == null) { + title = file.getName(); + int lastDot = title.lastIndexOf('.'); + if (lastDot > 0) { + title = title.substring(0, lastDot); + } + } + result = addDrmFile(cr, fis, title); + } catch (Exception e) { + Log.e(TAG, "pushing file failed", e); + } finally { + try { + if (fis != null) + fis.close(); + } catch (IOException e) { + Log.e(TAG, "IOException in DrmStore.addDrmFile()", e); + } + } + + return result; + } + + /** + * Utility function for inserting a file stream into the DRM content provider. + * + * @param cr The content resolver to use + * @param fileStream The FileInputStream to insert + * @param title The title for the content (or null) + * @return uri to the DRM record or null + */ + public static final Intent addDrmFile(ContentResolver cr, FileInputStream fis, String title) { + OutputStream os = null; + Intent result = null; + + try { + DrmRawContent content = new DrmRawContent(fis, (int) fis.available(), DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING); String mimeType = content.getContentType(); @@ -126,14 +160,6 @@ public final class DrmStore if (contentUri != null) { ContentValues values = new ContentValues(3); - // compute title from file name, if it is not specified - if (title == null) { - title = file.getName(); - int lastDot = title.lastIndexOf('.'); - if (lastDot > 0) { - title = title.substring(0, lastDot); - } - } values.put(DrmStore.Columns.TITLE, title); values.put(DrmStore.Columns.SIZE, size); values.put(DrmStore.Columns.MIME_TYPE, mimeType); @@ -162,7 +188,7 @@ public final class DrmStore if (os != null) os.close(); } catch (IOException e) { - Log.e(TAG, "IOException in DrmTest.onCreate()", e); + Log.e(TAG, "IOException in DrmStore.addDrmFile()", e); } } @@ -172,7 +198,7 @@ public final class DrmStore /** * Utility function to enforce any permissions required to access DRM * content. - * + * * @param context A context used for checking calling permission. */ public static void enforceAccessDrmPermission(Context context) { @@ -181,5 +207,5 @@ public final class DrmStore throw new SecurityException("Requires DRM permission"); } } - + } diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java index c4b29ae..073ae6c 100644 --- a/core/java/android/provider/Gmail.java +++ b/core/java/android/provider/Gmail.java @@ -83,7 +83,7 @@ public final class Gmail { public static final String LABEL_OUTBOX = "^^out"; public static final String AUTHORITY = "gmail-ls"; - private static final String TAG = "gmail-ls"; + private static final String TAG = "Gmail"; private static final String AUTHORITY_PLUS_CONVERSATIONS = "content://" + AUTHORITY + "/conversations/"; private static final String AUTHORITY_PLUS_LABELS = @@ -1521,8 +1521,9 @@ public final class Gmail { /** * Returns the number of conversation with a given label. - * @deprecated + * @deprecated Use {@link #getLabelId} instead. */ + @Deprecated public int getNumConversations(String label) { return getNumConversations(getLabelId(label)); } @@ -1534,8 +1535,9 @@ public final class Gmail { /** * Returns the number of unread conversation with a given label. - * @deprecated + * @deprecated Use {@link #getLabelId} instead. */ + @Deprecated public int getNumUnreadConversations(String label) { return getNumUnreadConversations(getLabelId(label)); } @@ -1546,11 +1548,12 @@ public final class Gmail { getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_UNREAD_CONVERSATIONS); // There seems to be a race condition here that can get the label maps into a bad // state and lose state on a particular label. - if (unreadConversations == null) { - return 0; - } else { - return unreadConversations; + int result = 0; + if (unreadConversations != null) { + result = unreadConversations < 0 ? 0 : unreadConversations; } + + return result; } /** @@ -2040,8 +2043,9 @@ public final class Gmail { } /** - * @deprecated + * @deprecated Always returns true. */ + @Deprecated public boolean getExpanded() { return true; } diff --git a/core/java/android/provider/Im.java b/core/java/android/provider/Im.java index 19ad158..025d5c2 100644 --- a/core/java/android/provider/Im.java +++ b/core/java/android/provider/Im.java @@ -27,7 +27,7 @@ import android.os.Handler; import java.util.HashMap; /** - * The IM provider stores all information about roster contacts, chat messages, presence, etc. + * The GTalk provider stores all information about roster contacts, chat messages, presence, etc. * * @hide */ @@ -38,7 +38,7 @@ public class Im { private Im() {} /** - * The Columns for IM providers (i.e. AIM, Y!, GTalk) + * The Columns for IM providers */ public interface ProviderColumns { /** @@ -138,6 +138,7 @@ public class Im { public static final String ACTIVE_ACCOUNT_USERNAME = "account_username"; public static final String ACTIVE_ACCOUNT_PW = "account_pw"; public static final String ACTIVE_ACCOUNT_LOCKED = "account_locked"; + public static final String ACTIVE_ACCOUNT_KEEP_SIGNED_IN = "account_keepSignedIn"; public static final String ACCOUNT_PRESENCE_STATUS = "account_presenceStatus"; public static final String ACCOUNT_CONNECTION_STATUS = "account_connStatus"; @@ -145,20 +146,20 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/providers"); + Uri.parse("content://com.google.android.providers.talk/providers"); public static final Uri CONTENT_URI_WITH_ACCOUNT = - Uri.parse("content://im/providers/account"); + Uri.parse("content://com.google.android.providers.talk/providers/account"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-providers"; + "vnd.android.cursor.dir/gtalk-providers"; public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-providers"; + "vnd.android.cursor.item/gtalk-providers"; /** * The default sort order for this table @@ -252,21 +253,21 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/accounts"); + Uri.parse("content://com.google.android.providers.talk/accounts"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * account. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-accounts"; + "vnd.android.cursor.dir/gtalk-accounts"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * account. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-accounts"; + "vnd.android.cursor.item/gtalk-accounts"; /** * The default sort order for this table @@ -325,19 +326,19 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/accountStatus"); + Uri.parse("content://com.google.android.providers.talk/accountStatus"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of account status. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-account-status"; + "vnd.android.cursor.dir/gtalk-account-status"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single account status. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-account-status"; + "vnd.android.cursor.item/gtalk-account-status"; /** * The default sort order for this table @@ -521,83 +522,83 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/contacts"); + Uri.parse("content://com.google.android.providers.talk/contacts"); /** * The content:// style URL for contacts joined with presence */ public static final Uri CONTENT_URI_WITH_PRESENCE = - Uri.parse("content://im/contactsWithPresence"); + Uri.parse("content://com.google.android.providers.talk/contactsWithPresence"); /** * The content:// style URL for barebone contacts, not joined with any other table */ public static final Uri CONTENT_URI_CONTACTS_BAREBONE = - Uri.parse("content://im/contactsBarebone"); + Uri.parse("content://com.google.android.providers.talk/contactsBarebone"); /** * The content:// style URL for contacts who have an open chat session */ public static final Uri CONTENT_URI_CHAT_CONTACTS = - Uri.parse("content://im/contacts/chatting"); + Uri.parse("content://com.google.android.providers.talk/contacts_chatting"); /** * The content:// style URL for contacts who have been blocked */ public static final Uri CONTENT_URI_BLOCKED_CONTACTS = - Uri.parse("content://im/contacts/blocked"); + Uri.parse("content://com.google.android.providers.talk/contacts/blocked"); /** * The content:// style URL for contacts by provider and account */ public static final Uri CONTENT_URI_CONTACTS_BY = - Uri.parse("content://im/contacts"); + Uri.parse("content://com.google.android.providers.talk/contacts"); /** * The content:// style URL for contacts by provider and account, * and who have an open chat session */ public static final Uri CONTENT_URI_CHAT_CONTACTS_BY = - Uri.parse("content://im/contacts/chatting"); + Uri.parse("content://com.google.android.providers.talk/contacts/chatting"); /** * The content:// style URL for contacts by provider and account, * and who are online */ public static final Uri CONTENT_URI_ONLINE_CONTACTS_BY = - Uri.parse("content://im/contacts/online"); + Uri.parse("content://com.google.android.providers.talk/contacts/online"); /** * The content:// style URL for contacts by provider and account, * and who are offline */ public static final Uri CONTENT_URI_OFFLINE_CONTACTS_BY = - Uri.parse("content://im/contacts/offline"); + Uri.parse("content://com.google.android.providers.talk/contacts/offline"); /** * The content:// style URL for operations on bulk contacts */ public static final Uri BULK_CONTENT_URI = - Uri.parse("content://im/bulk_contacts"); + Uri.parse("content://com.google.android.providers.talk/bulk_contacts"); /** * The content:// style URL for the count of online contacts in each * contact list by provider and account. */ public static final Uri CONTENT_URI_ONLINE_COUNT = - Uri.parse("content://im/contacts/onlineCount"); + Uri.parse("content://com.google.android.providers.talk/contacts/onlineCount"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-contacts"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-contacts"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * person. */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im-contacts"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/gtalk-contacts"; /** * The default sort order for this table @@ -633,21 +634,21 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/contactLists"); + Uri.parse("content://com.google.android.providers.talk/contactLists"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-contactLists"; + "vnd.android.cursor.dir/gtalk-contactLists"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * person. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-contactLists"; + "vnd.android.cursor.item/gtalk-contactLists"; /** * The default sort order for this table @@ -698,21 +699,21 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/blockedList"); + Uri.parse("content://com.google.android.providers.talk/blockedList"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-blockedList"; + "vnd.android.cursor.dir/gtalk-blockedList"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * person. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-blockedList"; + "vnd.android.cursor.item/gtalk-blockedList"; /** * The default sort order for this table @@ -821,21 +822,21 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/contactsEtag"); + Uri.parse("content://com.google.android.providers.talk/contactsEtag"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-contactsEtag"; + "vnd.android.cursor.dir/gtalk-contactsEtag"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * person. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-contactsEtag"; + "vnd.android.cursor.item/gtalk-contactsEtag"; } /** @@ -871,14 +872,22 @@ public class Im { } /** - * The common columns for both one-to-one chat messages or group chat messages. + * The common columns for messages table */ - public interface BaseMessageColumns { + public interface MessageColumns { /** - * The user this message belongs to - * <P>Type: TEXT</P> + * The thread_id column stores the contact id of the contact the message belongs to. + * For groupchat messages, the thread_id stores the group id, which is the contact id + * of the temporary group contact created for the groupchat. So there should be no + * collision between groupchat message thread id and regular message thread id. */ - String CONTACT = "contact"; + String THREAD_ID = "thread_id"; + + /** + * The nickname. This is used for groupchat messages to indicate the participant's + * nickname. For non groupchat messages, this field should be left empty. + */ + String NICKNAME = "nickname"; /** * The body @@ -887,12 +896,21 @@ public class Im { String BODY = "body"; /** - * The date this message is sent or received + * The date this message is sent or received. This represents the display date for + * the message. * <P>Type: INTEGER</P> */ String DATE = "date"; /** + * The real date for this message. While 'date' can be modified by the client + * to account for server time skew, the real_date is the original timestamp set + * by the server for incoming messages. + * <P>Type: INTEGER</P> + */ + String REAL_DATE = "real_date"; + + /** * Message Type, see {@link MessageType} * <P>Type: INTEGER</P> */ @@ -917,81 +935,217 @@ public class Im { * <P>Type: STRING</P> */ String PACKET_ID = "packet_id"; - } - /** - * Columns from the Messages table. - */ - public interface MessagesColumns extends BaseMessageColumns{ /** - * The provider id - * <P> Type: INTEGER </P> + * Is groupchat message or not + * <P>Type: INTEGER</P> */ - String PROVIDER = "provider"; + String IS_GROUP_CHAT = "is_muc"; /** - * The account id - * <P> Type: INTEGER </P> + * A hint that the UI should show the sent time of this message + * <P>Type: INTEGER</P> */ - String ACCOUNT = "account"; + String DISPLAY_SENT_TIME = "show_ts"; } /** * This table contains messages. */ - public static final class Messages implements BaseColumns, MessagesColumns { + public static final class Messages implements BaseColumns, MessageColumns { /** * no public constructor since this is a utility class */ private Messages() {} /** - * Gets the Uri to query messages by contact. + * Gets the Uri to query messages by thread id. + * + * @param threadId the thread id of the message. + * @return the Uri + */ + public static final Uri getContentUriByThreadId(long threadId) { + Uri.Builder builder = CONTENT_URI_MESSAGES_BY_THREAD_ID.buildUpon(); + ContentUris.appendId(builder, threadId); + return builder.build(); + } + + /** + * @deprecated + * + * Gets the Uri to query messages by account and contact. * - * @param providerId the provider id of the contact. * @param accountId the account id of the contact. * @param username the user name of the contact. * @return the Uri */ - public static final Uri getContentUriByContact(long providerId, - long accountId, String username) { - Uri.Builder builder = CONTENT_URI_MESSAGES_BY.buildUpon(); + public static final Uri getContentUriByContact(long accountId, String username) { + Uri.Builder builder = CONTENT_URI_MESSAGES_BY_ACCOUNT_AND_CONTACT.buildUpon(); + ContentUris.appendId(builder, accountId); + builder.appendPath(username); + return builder.build(); + } + + /** + * Gets the Uri to query messages by provider. + * + * @param providerId the service provider id. + * @return the Uri + */ + public static final Uri getContentUriByProvider(long providerId) { + Uri.Builder builder = CONTENT_URI_MESSAGES_BY_PROVIDER.buildUpon(); ContentUris.appendId(builder, providerId); + return builder.build(); + } + + /** + * Gets the Uri to query off the record messages by account. + * + * @param accountId the account id. + * @return the Uri + */ + public static final Uri getContentUriByAccount(long accountId) { + Uri.Builder builder = CONTENT_URI_BY_ACCOUNT.buildUpon(); + ContentUris.appendId(builder, accountId); + return builder.build(); + } + + /** + * Gets the Uri to query off the record messages by thread id. + * + * @param threadId the thread id of the message. + * @return the Uri + */ + public static final Uri getOtrMessagesContentUriByThreadId(long threadId) { + Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID.buildUpon(); + ContentUris.appendId(builder, threadId); + return builder.build(); + } + + /** + * @deprecated + * + * Gets the Uri to query off the record messages by account and contact. + * + * @param accountId the account id of the contact. + * @param username the user name of the contact. + * @return the Uri + */ + public static final Uri getOtrMessagesContentUriByContact(long accountId, String username) { + Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT.buildUpon(); ContentUris.appendId(builder, accountId); builder.appendPath(username); return builder.build(); } /** + * Gets the Uri to query off the record messages by provider. + * + * @param providerId the service provider id. + * @return the Uri + */ + public static final Uri getOtrMessagesContentUriByProvider(long providerId) { + Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_PROVIDER.buildUpon(); + ContentUris.appendId(builder, providerId); + return builder.build(); + } + + /** + * Gets the Uri to query off the record messages by account. + * + * @param accountId the account id. + * @return the Uri + */ + public static final Uri getOtrMessagesContentUriByAccount(long accountId) { + Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT.buildUpon(); + ContentUris.appendId(builder, accountId); + return builder.build(); + } + + /** * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/messages"); + Uri.parse("content://com.google.android.providers.talk/messages"); + + /** + * The content:// style URL for messages by thread id + */ + public static final Uri CONTENT_URI_MESSAGES_BY_THREAD_ID = + Uri.parse("content://com.google.android.providers.talk/messagesByThreadId"); + + /** + * The content:// style URL for messages by account and contact + */ + public static final Uri CONTENT_URI_MESSAGES_BY_ACCOUNT_AND_CONTACT = + Uri.parse("content://com.google.android.providers.talk/messagesByAcctAndContact"); + + /** + * The content:// style URL for messages by provider + */ + public static final Uri CONTENT_URI_MESSAGES_BY_PROVIDER = + Uri.parse("content://com.google.android.providers.talk/messagesByProvider"); + + /** + * The content:// style URL for messages by account + */ + public static final Uri CONTENT_URI_BY_ACCOUNT = + Uri.parse("content://com.google.android.providers.talk/messagesByAccount"); + + /** + * The content:// style url for off the record messages + */ + public static final Uri OTR_MESSAGES_CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/otrMessages"); + + /** + * The content:// style url for off the record messages by thread id + */ + public static final Uri OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID = + Uri.parse("content://com.google.android.providers.talk/otrMessagesByThreadId"); + + /** + * The content:// style url for off the record messages by account and contact + */ + public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT = + Uri.parse("content://com.google.android.providers.talk/otrMessagesByAcctAndContact"); + + /** + * The content:// style URL for off the record messages by provider + */ + public static final Uri OTR_MESSAGES_CONTENT_URI_BY_PROVIDER = + Uri.parse("content://com.google.android.providers.talk/otrMessagesByProvider"); /** - * The content:// style URL for messages by provider and account + * The content:// style URL for off the record messages by account */ - public static final Uri CONTENT_URI_MESSAGES_BY = - Uri.parse("content://im/messagesBy"); + public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT = + Uri.parse("content://com.google.android.providers.talk/otrMessagesByAccount"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-messages"; + public static final String CONTENT_TYPE = + "vnd.android.cursor.dir/gtalk-messages"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * person. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-messages"; + "vnd.android.cursor.item/gtalk-messages"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = "date ASC"; + /** + * The "contact" column. This is not a real column in the messages table, but a + * temoprary column created when querying for messages (joined with the contacts table) + */ + public static final String CONTACT = "contact"; } /** @@ -1021,21 +1175,21 @@ public class Im { private GroupMembers(){} public static final Uri CONTENT_URI = - Uri.parse("content://im/groupMembers"); + Uri.parse("content://com.google.android.providers.talk/groupMembers"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * group members. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-groupMembers"; + "vnd.android.cursor.dir/gtalk-groupMembers"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * group member. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-groupMembers"; + "vnd.android.cursor.item/gtalk-groupMembers"; } /** @@ -1101,82 +1255,21 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/invitations"); + Uri.parse("content://com.google.android.providers.talk/invitations"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * invitations. */ public static final String CONTENT_TYPE = - "vnd.android.cursor.dir/im-invitations"; + "vnd.android.cursor.dir/gtalk-invitations"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single * invitation. */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-invitations"; - } - - /** - * Columns from the GroupMessages table - */ - public interface GroupMessageColumns extends BaseMessageColumns { - /** - * The group this message belongs to - * <p>Type: TEXT</p> - */ - String GROUP = "groupId"; - } - - /** - * This table contains group messages. - */ - public final static class GroupMessages implements BaseColumns, - GroupMessageColumns { - private GroupMessages() {} - - /** - * Gets the Uri to query group messages by group. - * - * @param groupId the group id. - * @return the Uri - */ - public static final Uri getContentUriByGroup(long groupId) { - Uri.Builder builder = CONTENT_URI_GROUP_MESSAGES_BY.buildUpon(); - ContentUris.appendId(builder, groupId); - return builder.build(); - } - - /** - * The content:// style URL for this table - */ - public static final Uri CONTENT_URI = - Uri.parse("content://im/groupMessages"); - - /** - * The content:// style URL for group messages by provider and account - */ - public static final Uri CONTENT_URI_GROUP_MESSAGES_BY = - Uri.parse("content://im/groupMessagesBy"); - - /** - * The MIME type of {@link #CONTENT_URI} providing a directory of - * group messages. - */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-groupMessages"; - - /** - * The MIME type of a {@link #CONTENT_URI} subdirectory of a single - * group message. - */ - public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-groupMessages"; - - /** - * The default sort order for this table - */ - public static final String DEFAULT_SORT_ORDER = "date ASC"; + "vnd.android.cursor.item/gtalk-invitations"; } /** @@ -1218,24 +1311,25 @@ public class Im { /** * The content:// style URL for this table */ - public static final Uri CONTENT_URI = Uri.parse("content://im/avatars"); + public static final Uri CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/avatars"); /** * The content:// style URL for avatars by provider, account and contact */ public static final Uri CONTENT_URI_AVATARS_BY = - Uri.parse("content://im/avatarsBy"); + Uri.parse("content://com.google.android.providers.talk/avatarsBy"); /** * The MIME type of {@link #CONTENT_URI} providing the avatars */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-avatars"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-avatars"; /** * The MIME type of a {@link #CONTENT_URI} */ public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/im-avatars"; + "vnd.android.cursor.item/gtalk-avatars"; /** * The default sort order for this table @@ -1313,28 +1407,31 @@ public class Im { /** * The content:// style URL for this table */ - public static final Uri CONTENT_URI = Uri.parse("content://im/presence"); + public static final Uri CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/presence"); /** - * The content URL for IM presences for an account + * The content URL for Talk presences for an account */ - public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://im/presence/account"); + public static final Uri CONTENT_URI_BY_ACCOUNT = + Uri.parse("content://com.google.android.providers.talk/presence/account"); /** * The content:// style URL for operations on bulk contacts */ - public static final Uri BULK_CONTENT_URI = Uri.parse("content://im/bulk_presence"); + public static final Uri BULK_CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/bulk_presence"); /** * The content:// style URL for seeding presences for a given account id. */ public static final Uri SEED_PRESENCE_BY_ACCOUNT_CONTENT_URI = - Uri.parse("content://im/seed_presence/account"); + Uri.parse("content://com.google.android.providers.talk/seed_presence/account"); /** * The MIME type of a {@link #CONTENT_URI} providing a directory of presence */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-presence"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-presence"; /** * The default sort order for this table @@ -1384,7 +1481,7 @@ public class Im { * <P>Type: TEXT</P> */ String UNSENT_COMPOSED_MESSAGE = "unsent_composed_message"; - + /** * A value from 0-9 indicating which quick-switch chat screen slot this * chat is occupying. If none (for instance, this is the 12th active chat) @@ -1407,22 +1504,23 @@ public class Im { * The content:// style URL for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/chats"); + Uri.parse("content://com.google.android.providers.talk/chats"); /** * The content URL for all chats that belong to the account */ - public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://im/chats/account"); + public static final Uri CONTENT_URI_BY_ACCOUNT = + Uri.parse("content://com.google.android.providers.talk/chats/account"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of chats. */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-chats"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-chats"; /** * The MIME type of a {@link #CONTENT_URI} subdirectory of a single chat. */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im-chats"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/gtalk-chats"; /** * The default sort order for this table @@ -1450,19 +1548,20 @@ public class Im { /** * The content:// style URI for this table */ - public static final Uri CONTENT_URI = Uri.parse("content://im/sessionCookies"); + public static final Uri CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/sessionCookies"); /** * The content:// style URL for session cookies by provider and account */ public static final Uri CONTENT_URI_SESSION_COOKIES_BY = - Uri.parse("content://im/sessionCookiesBy"); + Uri.parse("content://com.google.android.providers.talk/sessionCookiesBy"); /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ - public static final String CONTENT_TYPE = "vnd.android-dir/im-sessionCookies"; + public static final String CONTENT_TYPE = "vnd.android-dir/gtalk-sessionCookies"; } /** @@ -1497,12 +1596,12 @@ public class Im { * The content:// style URI for this table */ public static final Uri CONTENT_URI = - Uri.parse("content://im/providerSettings"); + Uri.parse("content://com.google.android.providers.talk/providerSettings"); /** * The MIME type of {@link #CONTENT_URI} providing provider settings */ - public static final String CONTENT_TYPE = "vnd.android-dir/im-providerSettings"; + public static final String CONTENT_TYPE = "vnd.android-dir/gtalk-providerSettings"; /** * A boolean value to indicate whether this provider should show the offline contacts @@ -1512,13 +1611,13 @@ public class Im { /** controls whether or not the GTalk service automatically connect to server. */ public static final String SETTING_AUTOMATICALLY_CONNECT_GTALK = "gtalk_auto_connect"; - /** controls whether or not the IM service will be automatically started after boot */ + /** controls whether or not the GTalk service will be automatically started after boot */ public static final String SETTING_AUTOMATICALLY_START_SERVICE = "auto_start_service"; /** controls whether or not the offline contacts will be hided */ public static final String SETTING_HIDE_OFFLINE_CONTACTS = "hide_offline_contacts"; - /** controls whether or not enable the IM notification */ + /** controls whether or not enable the GTalk notification */ public static final String SETTING_ENABLE_NOTIFICATION = "enable_notification"; /** specifies whether or not to vibrate */ @@ -1534,6 +1633,18 @@ public class Im { /** specifies whether or not to show mobile indicator to friends */ public static final String SETTING_SHOW_MOBILE_INDICATOR = "mobile_indicator"; + /** specifies whether or not to show as away when device is idle */ + public static final String SETTING_SHOW_AWAY_ON_IDLE = "show_away_on_idle"; + + /** specifies whether or not to upload heartbeat stat upon login */ + public static final String SETTING_UPLOAD_HEARTBEAT_STAT = "upload_heartbeat_stat"; + + /** specifies the last heartbeat interval received from the server */ + public static final String SETTING_HEARTBEAT_INTERVAL = "heartbeat_interval"; + + /** specifiy the JID resource used for Google Talk connection */ + public static final String SETTING_JID_RESOURCE = "jid_resource"; + /** * Used for reliable message queue (RMQ). This is for storing the last rmq id received * from the GTalk server @@ -1698,10 +1809,10 @@ public class Im { } /** - * A convenience method to set whether or not enable the IM notification. + * A convenience method to set whether or not enable the GTalk notification. * * @param contentResolver The ContentResolver to use to access the setting table. - * @param enable Whether enable the IM notification + * @param enable Whether enable the GTalk notification */ public static void setEnableNotification(ContentResolver contentResolver, long providerId, boolean enable) { @@ -1742,6 +1853,47 @@ public class Im { showMobileIndicator); } + /** + * A convenience method to set whether or not to show as away when device is idle. + * + * @param contentResolver The ContentResolver to use to access the setting table. + * @param showAway Whether or not to show as away when device is idle. + */ + public static void setShowAwayOnIdle(ContentResolver contentResolver, + long providerId, boolean showAway) { + putBooleanValue(contentResolver, providerId, SETTING_SHOW_AWAY_ON_IDLE, showAway); + } + + /** + * A convenience method to set whether or not to upload heartbeat stat. + * + * @param contentResolver The ContentResolver to use to access the setting table. + * @param uploadStat Whether or not to upload heartbeat stat. + */ + public static void setUploadHeartbeatStat(ContentResolver contentResolver, + long providerId, boolean uploadStat) { + putBooleanValue(contentResolver, providerId, SETTING_UPLOAD_HEARTBEAT_STAT, uploadStat); + } + + /** + * A convenience method to set the heartbeat interval last received from the server. + * + * @param contentResolver The ContentResolver to use to access the setting table. + * @param interval The heartbeat interval last received from the server. + */ + public static void setHeartbeatInterval(ContentResolver contentResolver, + long providerId, long interval) { + putLongValue(contentResolver, providerId, SETTING_HEARTBEAT_INTERVAL, interval); + } + + /** + * A convenience method to set the jid resource. + */ + public static void setJidResource(ContentResolver contentResolver, + long providerId, String jidResource) { + putStringValue(contentResolver, providerId, SETTING_JID_RESOURCE, jidResource); + } + public static class QueryMap extends ContentQueryMap { private ContentResolver mContentResolver; private long mProviderId; @@ -1798,18 +1950,18 @@ public class Im { } /** - * Set whether or not enable the IM notification. + * Set whether or not enable the GTalk notification. * - * @param enable Whether or not enable the IM notification. + * @param enable Whether or not enable the GTalk notification. */ public void setEnableNotification(boolean enable) { ProviderSettings.setEnableNotification(mContentResolver, mProviderId, enable); } /** - * Check if the IM notification is enabled. + * Check if the GTalk notification is enabled. * - * @return Whether or not enable the IM notification. + * @return Whether or not enable the GTalk notification. */ public boolean getEnableNotification() { return getBoolean(SETTING_ENABLE_NOTIFICATION, @@ -1817,7 +1969,7 @@ public class Im { } /** - * Set whether or not to vibrate on IM notification. + * Set whether or not to vibrate on GTalk notification. * * @param vibrate Whether or not to vibrate. */ @@ -1826,7 +1978,7 @@ public class Im { } /** - * Gets whether or not to vibrate on IM notification. + * Gets whether or not to vibrate on GTalk notification. * * @return Whether or not to vibrate. */ @@ -1872,6 +2024,79 @@ public class Im { } /** + * Set whether or not to show as away when device is idle. + * + * @param showAway whether or not to show as away when device is idle. + */ + public void setShowAwayOnIdle(boolean showAway) { + ProviderSettings.setShowAwayOnIdle(mContentResolver, mProviderId, showAway); + } + + /** + * Get whether or not to show as away when device is idle. + * + * @return Whether or not to show as away when device is idle. + */ + public boolean getShowAwayOnIdle() { + return getBoolean(SETTING_SHOW_AWAY_ON_IDLE, + true /* by default show as away on idle*/); + } + + /** + * Set whether or not to upload heartbeat stat. + * + * @param uploadStat whether or not to upload heartbeat stat. + */ + public void setUploadHeartbeatStat(boolean uploadStat) { + ProviderSettings.setUploadHeartbeatStat(mContentResolver, mProviderId, uploadStat); + } + + /** + * Get whether or not to upload heartbeat stat. + * + * @return Whether or not to upload heartbeat stat. + */ + public boolean getUploadHeartbeatStat() { + return getBoolean(SETTING_UPLOAD_HEARTBEAT_STAT, + false /* by default do not upload */); + } + + /** + * Set the last received heartbeat interval from the server. + * + * @param interval the last received heartbeat interval from the server. + */ + public void setHeartbeatInterval(long interval) { + ProviderSettings.setHeartbeatInterval(mContentResolver, mProviderId, interval); + } + + /** + * Get the last received heartbeat interval from the server. + * + * @return the last received heartbeat interval from the server. + */ + public long getHeartbeatInterval() { + return getLong(SETTING_HEARTBEAT_INTERVAL, 0L /* an invalid default interval */); + } + + /** + * Set the JID resource. + * + * @param jidResource the jid resource to be stored. + */ + public void setJidResource(String jidResource) { + ProviderSettings.setJidResource(mContentResolver, mProviderId, jidResource); + } + /** + * Get the JID resource used for the Google Talk connection + * + * @return the JID resource stored. + */ + public String getJidResource() { + return getString(SETTING_JID_RESOURCE, null); + } + + /** * Convenience function for retrieving a single settings value * as a boolean. * @@ -1909,21 +2134,78 @@ public class Im { ContentValues values = getValues(name); return values != null ? values.getAsInteger(VALUE) : def; } + + /** + * Convenience function for retrieving a single settings value + * as a Long. + * + * @param name The name of the setting to retrieve. + * @param def The value to return if the setting is not defined. + * @return The setting's current value or 'def' if it is not defined. + */ + private long getLong(String name, long def) { + ContentValues values = getValues(name); + return values != null ? values.getAsLong(VALUE) : def; + } } } + + /** + * Columns for GTalk branding resource map cache table. This table caches the result of + * loading the branding resources to speed up GTalk landing page start. + */ + public interface BrandingResourceMapCacheColumns { + /** + * The provider ID + * <P>Type: INTEGER</P> + */ + String PROVIDER_ID = "provider_id"; + /** + * The application resource ID + * <P>Type: INTEGER</P> + */ + String APP_RES_ID = "app_res_id"; + /** + * The plugin resource ID + * <P>Type: INTEGER</P> + */ + String PLUGIN_RES_ID = "plugin_res_id"; + } + + /** + * The table for caching the result of loading GTalk branding resources. + */ + public static final class BrandingResourceMapCache + implements BaseColumns, BrandingResourceMapCacheColumns { + /** + * The content:// style URL for this table. + */ + public static final Uri CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/brandingResMapCache"); + } + + + + /** + * //TODO: move these to MCS specific provider. + * The following are MCS stuff, and should really live in a separate provider specific to + * MCS code. + */ + /** * Columns from OutgoingRmq table */ public interface OutgoingRmqColumns { String RMQ_ID = "rmq_id"; - String TYPE = "type"; String TIMESTAMP = "ts"; String DATA = "data"; + String PROTOBUF_TAG = "type"; } /** + * //TODO: we should really move these to their own provider and database. * The table for storing outgoing rmq packets. */ public static final class OutgoingRmq implements BaseColumns, OutgoingRmqColumns { @@ -1963,13 +2245,14 @@ public class Im { /** * The content:// style URL for this table. */ - public static final Uri CONTENT_URI = Uri.parse("content://im/outgoingRmqMessages"); + public static final Uri CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/outgoingRmqMessages"); /** * The content:// style URL for the highest rmq id for the outgoing rmq messages */ public static final Uri CONTENT_URI_FOR_HIGHEST_RMQ_ID = - Uri.parse("content://im/outgoingHighestRmqId"); + Uri.parse("content://com.google.android.providers.talk/outgoingHighestRmqId"); /** * The default sort order for this table. @@ -1986,6 +2269,7 @@ public class Im { } /** + * //TODO: move these out into their own provider and database * The table for storing the last client rmq id sent to the server. */ public static final class LastRmqId implements BaseColumns, LastRmqIdColumns { @@ -2042,39 +2326,27 @@ public class Im { /** * The content:// style URL for this table. */ - public static final Uri CONTENT_URI = Uri.parse("content://im/lastRmqId"); + public static final Uri CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/lastRmqId"); } /** - * Columns for IM branding resource map cache table. This table caches the result of - * loading the branding resources to speed up IM landing page start. + * Columns for the s2dRmqIds table, which stores the server-to-device message + * persistent ids. These are used in the RMQ2 protocol, where in the login request, the + * client selective acks these s2d ids to the server. */ - public interface BrandingResourceMapCacheColumns { - /** - * The provider ID - * <P>Type: INTEGER</P> - */ - String PROVIDER_ID = "provider_id"; - /** - * The application resource ID - * <P>Type: INTEGER</P> - */ - String APP_RES_ID = "app_res_id"; - /** - * The plugin resource ID - * <P>Type: INTEGER</P> - */ - String PLUGIN_RES_ID = "plugin_res_id"; + public interface ServerToDeviceRmqIdsColumn { + String RMQ_ID = "rmq_id"; } - /** - * The table for caching the result of loading IM branding resources. - */ - public static final class BrandingResourceMapCache - implements BaseColumns, BrandingResourceMapCacheColumns { + public static final class ServerToDeviceRmqIds implements BaseColumns, + ServerToDeviceRmqIdsColumn { + /** * The content:// style URL for this table. */ - public static final Uri CONTENT_URI = Uri.parse("content://im/brandingResMapCache"); + public static final Uri CONTENT_URI = + Uri.parse("content://com.google.android.providers.talk/s2dids"); } + } diff --git a/core/java/android/provider/LiveFolders.java b/core/java/android/provider/LiveFolders.java index 6e95fb7..7856bab 100644 --- a/core/java/android/provider/LiveFolders.java +++ b/core/java/android/provider/LiveFolders.java @@ -40,12 +40,11 @@ import android.annotation.SdkConstant; * to retrieve the folder's content.</p> * * <h3>Setting up the live folder activity</h3> - * <p>The following code sample shows how to write an activity that creates a live fodler:</p> + * <p>The following code sample shows how to write an activity that creates a live folder:</p> * <pre> * public static class MyLiveFolder extends Activity { * public static final Uri CONTENT_URI = Uri.parse("content://my.app/live"); * - * @Override * protected void onCreate(Bundle savedInstanceState) { * super.onCreate(savedInstanceState); * diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 21e5865..062080d 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -23,11 +23,15 @@ import android.content.ContentValues; import android.content.ContentUris; import android.database.Cursor; import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; +import android.media.MiniThumbFile; +import android.media.ThumbnailUtil; import android.net.Uri; import android.os.Environment; +import android.os.ParcelFileDescriptor; import android.util.Log; import java.io.FileInputStream; @@ -42,8 +46,7 @@ import java.text.Collator; * The Media provider contains meta data for all available media on both internal * and external storage devices. */ -public final class MediaStore -{ +public final class MediaStore { private final static String TAG = "MediaStore"; public static final String AUTHORITY = "media"; @@ -164,6 +167,12 @@ public final class MediaStore public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit"; /** + * Specify the maximum allowed recording duration in seconds. + * @hide + */ + public final static String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit"; + + /** * The name of the Intent-extra used to indicate a content resolver Uri to be used to * store the requested image or video. */ @@ -173,7 +182,7 @@ public final class MediaStore * Common fields for most MediaProvider tables */ - public interface MediaColumns extends BaseColumns { + public interface MediaColumns extends BaseColumns { /** * The data stream for the file * <P>Type: DATA STREAM</P> @@ -221,10 +230,154 @@ public final class MediaStore } /** + * This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended + * to be accessed elsewhere. + */ + private static class InternalThumbnails implements BaseColumns { + private static final int MINI_KIND = 1; + private static final int FULL_SCREEN_KIND = 2; + private static final int MICRO_KIND = 3; + private static final String[] PROJECTION = new String[] {_ID, MediaColumns.DATA}; + + /** + * This method cancels the thumbnail request so clients waiting for getThumbnail will be + * interrupted and return immediately. Only the original process which made the getThumbnail + * requests can cancel their own requests. + * + * @param cr ContentResolver + * @param origId original image or video id. use -1 to cancel all requests. + * @param baseUri the base URI of requested thumbnails + */ + static void cancelThumbnailRequest(ContentResolver cr, long origId, Uri baseUri) { + Uri cancelUri = baseUri.buildUpon().appendQueryParameter("cancel", "1") + .appendQueryParameter("orig_id", String.valueOf(origId)).build(); + Cursor c = null; + try { + c = cr.query(cancelUri, PROJECTION, null, null, null); + } + finally { + if (c != null) c.close(); + } + } + /** + * This method ensure thumbnails associated with origId are generated and decode the byte + * stream from database (MICRO_KIND) or file (MINI_KIND). + * + * Special optimization has been done to avoid further IPC communication for MICRO_KIND + * thumbnails. + * + * @param cr ContentResolver + * @param origId original image or video id + * @param kind could be MINI_KIND or MICRO_KIND + * @param options this is only used for MINI_KIND when decoding the Bitmap + * @param baseUri the base URI of requested thumbnails + * @return Bitmap bitmap of specified thumbnail kind + */ + static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, + BitmapFactory.Options options, Uri baseUri, boolean isVideo) { + Bitmap bitmap = null; + String filePath = null; + // Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo); + // some optimization for MICRO_KIND: if the magic is non-zero, we don't bother + // querying MediaProvider and simply return thumbnail. + if (kind == MICRO_KIND) { + MiniThumbFile thumbFile = MiniThumbFile.instance(baseUri); + if (thumbFile.getMagic(origId) != 0) { + byte[] data = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; + if (thumbFile.getMiniThumbFromFile(origId, data) != null) { + bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); + if (bitmap == null) { + Log.w(TAG, "couldn't decode byte array."); + } + } + return bitmap; + } + } + + Cursor c = null; + try { + Uri blockingUri = baseUri.buildUpon().appendQueryParameter("blocking", "1") + .appendQueryParameter("orig_id", String.valueOf(origId)).build(); + c = cr.query(blockingUri, PROJECTION, null, null, null); + // This happens when original image/video doesn't exist. + if (c == null) return null; + + // Assuming thumbnail has been generated, at least original image exists. + if (kind == MICRO_KIND) { + MiniThumbFile thumbFile = MiniThumbFile.instance(baseUri); + byte[] data = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; + if (thumbFile.getMiniThumbFromFile(origId, data) != null) { + bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); + if (bitmap == null) { + Log.w(TAG, "couldn't decode byte array."); + } + } + } else if (kind == MINI_KIND) { + if (c.moveToFirst()) { + ParcelFileDescriptor pfdInput; + Uri thumbUri = null; + try { + long thumbId = c.getLong(0); + filePath = c.getString(1); + thumbUri = ContentUris.withAppendedId(baseUri, thumbId); + pfdInput = cr.openFileDescriptor(thumbUri, "r"); + bitmap = BitmapFactory.decodeFileDescriptor( + pfdInput.getFileDescriptor(), null, options); + pfdInput.close(); + } catch (FileNotFoundException ex) { + Log.e(TAG, "couldn't open thumbnail " + thumbUri + "; " + ex); + } catch (IOException ex) { + Log.e(TAG, "couldn't open thumbnail " + thumbUri + "; " + ex); + } catch (OutOfMemoryError ex) { + Log.e(TAG, "failed to allocate memory for thumbnail " + + thumbUri + "; " + ex); + } + } + } else { + throw new IllegalArgumentException("Unsupported kind: " + kind); + } + + // We probably run out of space, so create the thumbnail in memory. + if (bitmap == null) { + Log.v(TAG, "We probably run out of space, so create the thumbnail in memory."); + + Uri uri = Uri.parse( + baseUri.buildUpon().appendPath(String.valueOf(origId)) + .toString().replaceFirst("thumbnails", "media")); + if (filePath == null) { + if (c != null) c.close(); + c = cr.query(uri, PROJECTION, null, null, null); + if (c == null || !c.moveToFirst()) { + return null; + } + filePath = c.getString(1); + } + if (isVideo) { + bitmap = ThumbnailUtil.createVideoThumbnail(filePath); + if (kind == MICRO_KIND) { + bitmap = ThumbnailUtil.extractMiniThumb(bitmap, + ThumbnailUtil.MINI_THUMB_TARGET_SIZE, + ThumbnailUtil.MINI_THUMB_TARGET_SIZE, + ThumbnailUtil.RECYCLE_INPUT); + } + } else { + bitmap = ThumbnailUtil.createImageThumbnail(cr, filePath, uri, origId, + kind, false); + } + } + } catch (SQLiteException ex) { + Log.w(TAG, ex); + } finally { + if (c != null) c.close(); + } + return bitmap; + } + } + + /** * Contains meta data for all available images. */ - public static final class Images - { + public static final class Images { public interface ImageColumns extends MediaColumns { /** * The description of the image @@ -292,21 +445,18 @@ public final class MediaStore } public static final class Media implements ImageColumns { - public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) - { + public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) { return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER); } public static final Cursor query(ContentResolver cr, Uri uri, String[] projection, - String where, String orderBy) - { + String where, String orderBy) { return cr.query(uri, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } public static final Cursor query(ContentResolver cr, Uri uri, String[] projection, - String selection, String [] selectionArgs, String orderBy) - { + String selection, String [] selectionArgs, String orderBy) { return cr.query(uri, projection, selection, selectionArgs, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } @@ -320,8 +470,7 @@ public final class MediaStore * @throws IOException */ public static final Bitmap getBitmap(ContentResolver cr, Uri url) - throws FileNotFoundException, IOException - { + throws FileNotFoundException, IOException { InputStream input = cr.openInputStream(url); Bitmap bitmap = BitmapFactory.decodeStream(input); input.close(); @@ -338,9 +487,8 @@ public final class MediaStore * @return The URL to the newly created image * @throws FileNotFoundException */ - public static final String insertImage(ContentResolver cr, String imagePath, String name, - String description) throws FileNotFoundException - { + public static final String insertImage(ContentResolver cr, String imagePath, + String name, String description) throws FileNotFoundException { // Check if file exists with a FileInputStream FileInputStream stream = new FileInputStream(imagePath); try { @@ -409,8 +557,7 @@ public final class MediaStore * for any reason. */ public static final String insertImage(ContentResolver cr, Bitmap source, - String title, String description) - { + String title, String description) { ContentValues values = new ContentValues(); values.put(Images.Media.TITLE, title); values.put(Images.Media.DESCRIPTION, description); @@ -419,8 +566,7 @@ public final class MediaStore Uri url = null; String stringUrl = null; /* value to be returned */ - try - { + try { url = cr.insert(EXTERNAL_CONTENT_URI, values); if (source != null) { @@ -490,28 +636,60 @@ public final class MediaStore * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = ImageColumns.BUCKET_DISPLAY_NAME; - } + } - public static class Thumbnails implements BaseColumns - { - public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) - { + /** + * This class allows developers to query and get two kinds of thumbnails: + * MINI_KIND: 512 x 384 thumbnail + * MICRO_KIND: 96 x 96 thumbnail + */ + public static class Thumbnails implements BaseColumns { + public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) { return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER); } - public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind, String[] projection) - { + public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind, + String[] projection) { return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER); } - public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind, String[] projection) - { + public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind, + String[] projection) { return cr.query(EXTERNAL_CONTENT_URI, projection, IMAGE_ID + " = " + origId + " AND " + KIND + " = " + kind, null, null); } /** + * This method cancels the thumbnail request so clients waiting for getThumbnail will be + * interrupted and return immediately. Only the original process which made the getThumbnail + * requests can cancel their own requests. + * + * @param cr ContentResolver + * @param origId original image id + */ + public static void cancelThumbnailRequest(ContentResolver cr, long origId) { + InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI); + } + + /** + * This method checks if the thumbnails of the specified image (origId) has been created. + * It will be blocked until the thumbnails are generated. + * + * @param cr ContentResolver used to dispatch queries to MediaProvider. + * @param origId Original image id associated with thumbnail of interest. + * @param kind The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND. + * @param options this is only used for MINI_KIND when decoding the Bitmap + * @return A Bitmap instance. It could be null if the original image + * associated with origId doesn't exist or memory is not enough. + */ + public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, + BitmapFactory.Options options) { + return InternalThumbnails.getThumbnail(cr, origId, kind, options, + EXTERNAL_CONTENT_URI, false); + } + + /** * Get the content:// style URI for the image media table on the * given volume. * @@ -562,6 +740,11 @@ public final class MediaStore public static final int MINI_KIND = 1; public static final int FULL_SCREEN_KIND = 2; public static final int MICRO_KIND = 3; + /** + * The blob raw data of thumbnail + * <P>Type: DATA STREAM</P> + */ + public static final String THUMB_DATA = "thumb_data"; /** * The width of the thumbnal @@ -1176,7 +1359,7 @@ public final class MediaStore * <P>Type: INTEGER</P> */ public static final String FIRST_YEAR = "minyear"; - + /** * The year in which the latest songs * on this album were released. This will often @@ -1253,8 +1436,7 @@ public final class MediaStore */ public static final String DEFAULT_SORT_ORDER = MediaColumns.DISPLAY_NAME; - public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) - { + public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) { return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER); } @@ -1399,6 +1581,107 @@ public final class MediaStore */ public static final String DEFAULT_SORT_ORDER = TITLE; } + + /** + * This class allows developers to query and get two kinds of thumbnails: + * MINI_KIND: 512 x 384 thumbnail + * MICRO_KIND: 96 x 96 thumbnail + * + */ + public static class Thumbnails implements BaseColumns { + /** + * This method cancels the thumbnail request so clients waiting for getThumbnail will be + * interrupted and return immediately. Only the original process which made the getThumbnail + * requests can cancel their own requests. + * + * @param cr ContentResolver + * @param origId original video id + */ + public static void cancelThumbnailRequest(ContentResolver cr, long origId) { + InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI); + } + + /** + * This method checks if the thumbnails of the specified image (origId) has been created. + * It will be blocked until the thumbnails are generated. + * + * @param cr ContentResolver used to dispatch queries to MediaProvider. + * @param origId Original image id associated with thumbnail of interest. + * @param kind The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND + * @param options this is only used for MINI_KIND when decoding the Bitmap + * @return A Bitmap instance. It could be null if the original image associated with + * origId doesn't exist or memory is not enough. + */ + public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, + BitmapFactory.Options options) { + return InternalThumbnails.getThumbnail(cr, origId, kind, options, + EXTERNAL_CONTENT_URI, true); + } + + /** + * Get the content:// style URI for the image media table on the + * given volume. + * + * @param volumeName the name of the volume to get the URI for + * @return the URI to the image media table on the given volume + */ + public static Uri getContentUri(String volumeName) { + return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + + "/video/thumbnails"); + } + + /** + * The content:// style URI for the internal storage. + */ + public static final Uri INTERNAL_CONTENT_URI = + getContentUri("internal"); + + /** + * The content:// style URI for the "primary" external storage + * volume. + */ + public static final Uri EXTERNAL_CONTENT_URI = + getContentUri("external"); + + /** + * The default sort order for this table + */ + public static final String DEFAULT_SORT_ORDER = "video_id ASC"; + + /** + * The data stream for the thumbnail + * <P>Type: DATA STREAM</P> + */ + public static final String DATA = "_data"; + + /** + * The original image for the thumbnal + * <P>Type: INTEGER (ID from Video table)</P> + */ + public static final String VIDEO_ID = "video_id"; + + /** + * The kind of the thumbnail + * <P>Type: INTEGER (One of the values below)</P> + */ + public static final String KIND = "kind"; + + public static final int MINI_KIND = 1; + public static final int FULL_SCREEN_KIND = 2; + public static final int MICRO_KIND = 3; + + /** + * The width of the thumbnal + * <P>Type: INTEGER (long)</P> + */ + public static final String WIDTH = "width"; + + /** + * The height of the thumbnail + * <P>Type: INTEGER (long)</P> + */ + public static final String HEIGHT = "height"; + } } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 4a4d2de..cb3dc16 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -119,6 +119,20 @@ public final class Settings { "android.settings.AIRPLANE_MODE_SETTINGS"; /** + * Activity Action: Show settings for accessibility modules. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_ACCESSIBILITY_SETTINGS = + "android.settings.ACCESSIBILITY_SETTINGS"; + + /** * Activity Action: Show settings to allow configuration of security and * location privacy. * <p> @@ -134,6 +148,20 @@ public final class Settings { "android.settings.SECURITY_SETTINGS"; /** + * Activity Action: Show settings to allow configuration of privacy options. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_PRIVACY_SETTINGS = + "android.settings.PRIVACY_SETTINGS"; + + /** * Activity Action: Show settings to allow configuration of Wi-Fi. * <p> @@ -413,8 +441,6 @@ public final class Settings { private static final String TAG = "Settings"; - private static String sJidResource = null; - public static class SettingNotFoundException extends AndroidException { public SettingNotFoundException(String msg) { super(msg); @@ -438,7 +464,7 @@ public final class Settings { resolver.insert(uri, values); return true; } catch (SQLException e) { - Log.e(TAG, "Can't set key " + name + " in " + uri, e); + Log.w(TAG, "Can't set key " + name + " in " + uri, e); return false; } } @@ -475,7 +501,7 @@ public final class Settings { mValues.put(name, value); } catch (SQLException e) { // SQL error: return null, but don't cache it. - Log.e(TAG, "Can't get key " + name + " from " + mUri, e); + Log.w(TAG, "Can't get key " + name + " from " + mUri, e); } finally { if (c != null) c.close(); } @@ -879,6 +905,17 @@ public final class Settings { public static final String AIRPLANE_MODE_RADIOS = "airplane_mode_radios"; /** + * A comma separated list of radios that should to be disabled when airplane mode + * is on, but can be manually reenabled by the user. For example, if RADIO_WIFI is + * added to both AIRPLANE_MODE_RADIOS and AIRPLANE_MODE_TOGGLEABLE_RADIOS, then Wifi + * will be turned off when entering airplane mode, but the user will be able to reenable + * Wifi in the Settings app. + * + * {@hide} + */ + public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS = "airplane_mode_toggleable_radios"; + + /** * The policy for deciding when Wi-Fi should go to sleep (which will in * turn switch to using the mobile data as an Internet connection). * <p> @@ -1038,6 +1075,24 @@ public final class Settings { public static final String SCREEN_BRIGHTNESS = "screen_brightness"; /** + * Control whether to enable automatic brightness mode. + * @hide + */ + public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode"; + + /** + * SCREEN_BRIGHTNESS_MODE value for manual mode. + * @hide + */ + public static final int SCREEN_BRIGHTNESS_MODE_MANUAL = 0; + + /** + * SCREEN_BRIGHTNESS_MODE value for manual mode. + * @hide + */ + public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1; + + /** * Control whether the process CPU usage meter should be shown. */ public static final String SHOW_PROCESSES = "show_processes"; @@ -1182,6 +1237,22 @@ public final class Settings { public static final Uri DEFAULT_NOTIFICATION_URI = getUriFor(NOTIFICATION_SOUND); /** + * Persistent store for the system-wide default alarm alert. + * + * @see #RINGTONE + * @see #DEFAULT_ALARM_ALERT_URI + */ + public static final String ALARM_ALERT = "alarm_alert"; + + /** + * A {@link Uri} that will point to the current default alarm alert at + * any given time. + * + * @see #DEFAULT_ALARM_ALERT_URI + */ + public static final Uri DEFAULT_ALARM_ALERT_URI = getUriFor(ALARM_ALERT); + + /** * Setting to enable Auto Replace (AutoText) in text editors. 1 = On, 0 = Off */ public static final String TEXT_AUTO_REPLACE = "auto_replace"; @@ -1357,6 +1428,7 @@ public final class Settings { DIM_SCREEN, SCREEN_OFF_TIMEOUT, SCREEN_BRIGHTNESS, + SCREEN_BRIGHTNESS_MODE, VIBRATE_ON, NOTIFICATIONS_USE_RING_VOLUME, MODE_RINGER, @@ -1497,18 +1569,17 @@ public final class Settings { @Deprecated public static final String USE_GOOGLE_MAIL = Secure.USE_GOOGLE_MAIL; -// /** -// * @deprecated Use {@link android.provider.Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT} -// * instead -// */ + /** + * @deprecated Use + * {@link android.provider.Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT} instead + */ @Deprecated public static final String WIFI_MAX_DHCP_RETRY_COUNT = Secure.WIFI_MAX_DHCP_RETRY_COUNT; -// /** -// * @deprecated Use -// * {@link android.provider.Settings.Secure#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS} -// * instead -// */ + /** + * @deprecated Use + * {@link android.provider.Settings.Secure#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS} instead + */ @Deprecated public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = Secure.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS; @@ -1968,6 +2039,12 @@ public final class Settings { public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed"; /** + * Whether assisted GPS should be enabled or not. + * @hide + */ + public static final String ASSISTED_GPS_ENABLED = "assisted_gps_enabled"; + + /** * The Logging ID (a unique 64-bit value) as a hex string. * Used as a pseudonymous identifier for logging. * @deprecated This identifier is poorly initialized and has @@ -2201,6 +2278,32 @@ public final class Settings { public static final String BACKGROUND_DATA = "background_data"; /** + * The time in msec, when the LAST_KMSG file was send to the checkin server. + * We will only send the LAST_KMSG file if it was modified after this time. + * + * @hide + */ + public static final String CHECKIN_SEND_LAST_KMSG_TIME = "checkin_kmsg_time"; + + /** + * The time in msec, when the apanic_console file was send to the checkin server. + * We will only send the apanic_console file if it was modified after this time. + * + * @hide + */ + public static final String CHECKIN_SEND_APANIC_CONSOLE_TIME = + "checkin_apanic_console_time"; + + /** + * The time in msec, when the apanic_thread file was send to the checkin server. + * We will only send the apanic_thread file if it was modified after this time. + * + * @hide + */ + public static final String CHECKIN_SEND_APANIC_THREAD_TIME = + "checkin_apanic_thread_time"; + + /** * The CDMA roaming mode 0 = Home Networks, CDMA default * 1 = Roaming on Affiliated networks * 2 = Roaming on any networks @@ -2314,7 +2417,6 @@ public final class Settings { public static final String[] SETTINGS_TO_BACKUP = { ADB_ENABLED, ALLOW_MOCK_LOCATION, - INSTALL_NON_MARKET_APPS, PARENTAL_CONTROL_ENABLED, PARENTAL_CONTROL_REDIRECT_URL, USB_MASS_STORAGE_ENABLED, @@ -2330,12 +2432,6 @@ public final class Settings { WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, WIFI_NUM_ALLOWED_CHANNELS, WIFI_NUM_OPEN_NETWORKS_KEPT, - BACKGROUND_DATA, - PREFERRED_NETWORK_MODE, - PREFERRED_TTY_MODE, - CDMA_CELL_BROADCAST_SMS, - PREFERRED_CDMA_SUBSCRIPTION, - ENHANCED_VOICE_PRIVACY_ENABLED }; /** @@ -2687,15 +2783,30 @@ public final class Settings { /** * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be - * an integer where non-zero means true. Defaults to 1. + * an integer where non-zero means true. Defaults to 1. This flag controls Donut devices. */ public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op"; /** + * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be + * an integer where non-zero means true. Defaults to 1. This flag controls Eclair and + * future devices. + */ + public static final String GMAIL_DISCARD_ERROR_UPHILL_OP_NEW = + "gmail_discard_error_uphill_op_new"; + + /** * Controls how many attempts Gmail will try to upload an uphill operations before it * abandons the operation. Defaults to 20. */ - public static final String GMAIL_NUM_RETRY_UPHILL_OP = "gmail_discard_error_uphill_op"; + public static final String GMAIL_NUM_RETRY_UPHILL_OP = "gmail_num_retry_uphill_op"; + + /** + * How much time in seconds Gmail will try to upload an uphill operations before it + * abandons the operation. Defaults to 36400 (one day). + */ + public static final String GMAIL_WAIT_TIME_RETRY_UPHILL_OP = + "gmail_wait_time_retry_uphill_op"; /** * Controls if the protocol buffer version of the protocol will use a multipart request for @@ -2804,6 +2915,12 @@ public final class Settings { "gtalk_nosync_heartbeat_ping_interval_ms"; /** + * The maximum heartbeat interval used while on the WIFI network. + */ + public static final String GTALK_SERVICE_WIFI_MAX_HEARTBEAT_INTERVAL_MS = + "gtalk_wifi_max_heartbeat_ping_interval_ms"; + + /** * How long we wait to receive a heartbeat ping acknowledgement (or another packet) * from the GTalk server, before deeming the connection dead. */ @@ -2856,6 +2973,113 @@ public final class Settings { public static final String GTALK_USE_BARE_JID_TIMEOUT_MS = "gtalk_use_barejid_timeout_ms"; /** + * This is the threshold of retry number when there is an authentication expired failure + * for Google Talk. In some situation, e.g. when a Google Apps account is disabled chat + * service, the connection keeps failing. This threshold controls when we should stop + * the retrying. + */ + public static final String GTALK_MAX_RETRIES_FOR_AUTH_EXPIRED = + "gtalk_max_retries_for_auth_expired"; + + /** + * a boolean setting indicating whether the GTalkService should use RMQ2 protocol or not. + */ + public static final String GTALK_USE_RMQ2_PROTOCOL = + "gtalk_use_rmq2"; + + /** + * a boolean setting indicating whether the GTalkService should support both RMQ and + * RMQ2 protocols. This setting is true for the transitional period when we need to + * support both protocols. + */ + public static final String GTALK_SUPPORT_RMQ_AND_RMQ2_PROTOCOLS = + "gtalk_support_rmq_and_rmq2"; + + /** + * a boolean setting controlling whether the rmq2 protocol will include stream ids in + * the protobufs. This is used for debugging. + */ + public static final String GTALK_RMQ2_INCLUDE_STREAM_ID = + "gtalk_rmq2_include_stream_id"; + + /** + * when receiving a chat message from the server, the message could be an older message + * whose "time sent" is x seconds from now. If x is significant enough, we want to flag + * it so the UI can give it some special treatment when displaying the "time sent" for + * it. This setting is to control what x is. + */ + public static final String GTALK_OLD_CHAT_MESSAGE_THRESHOLD_IN_SEC = + "gtalk_old_chat_msg_threshold_in_sec"; + + /** + * a setting to control the max connection history record GTalkService stores. + */ + public static final String GTALK_MAX_CONNECTION_HISTORY_RECORDS = + "gtalk_max_conn_history_records"; + + /** + * This is gdata url to lookup album and picture info from picasa web. It also controls + * whether url scraping for picasa is enabled (NULL to disable). + */ + public static final String GTALK_PICASA_ALBUM_URL = + "gtalk_picasa_album_url"; + + /** + * This is the url to lookup picture info from flickr. It also controls + * whether url scraping for flickr is enabled (NULL to disable). + */ + public static final String GTALK_FLICKR_PHOTO_INFO_URL = + "gtalk_flickr_photo_info_url"; + + /** + * This is the url to lookup an actual picture from flickr. + */ + public static final String GTALK_FLICKR_PHOTO_URL = + "gtalk_flickr_photo_url"; + + /** + * This is the gdata url to lookup info on a youtube video. It also controls + * whether url scraping for youtube is enabled (NULL to disable). + */ + public static final String GTALK_YOUTUBE_VIDEO_URL = + "gtalk_youtube_video_url"; + + /** + * Enable/disable GTalk URL scraping for JPG images ("true" to enable). + */ + public static final String GTALK_URL_SCRAPING_FOR_JPG = + "gtalk_url_scraping_for_jpg"; + + /** + * Chat message lifetime (for pruning old chat messages). + */ + public static final String GTALK_CHAT_MESSAGE_LIFETIME = + "gtalk_chat_message_lifetime"; + + /** + * OTR message lifetime (for pruning old otr messages). + */ + public static final String GTALK_OTR_MESSAGE_LIFETIME = + "gtalk_otr_message_lifetime"; + + /** + * Chat expiration time, i.e., time since last message in the chat (for pruning old chats). + */ + public static final String GTALK_CHAT_EXPIRATION_TIME = + "gtalk_chat_expiration_time"; + + /** + * This is the url for getting the app token for server-to-device push messaging. + */ + public static final String PUSH_MESSAGING_REGISTRATION_URL = + "push_messaging_registration_url"; + + /** + * Use android://<it> routing infos for Google Sync Server subcriptions. + */ + public static final String GSYNC_USE_RMQ2_ROUTING_INFO = "gsync_use_rmq2_routing_info"; + + /** * Enable use of ssl session caching. * 'db' - save each session in a (per process) database * 'file' - save each session in a (per process) file @@ -2907,6 +3131,12 @@ public final class Settings { "vending_require_sim_for_purchase"; /** + * Indicates the Vending Machine backup state. It is set if the + * Vending application has been backed up at least once. + */ + public static final String VENDING_BACKUP_STATE = "vending_backup_state"; + + /** * The current version id of the Vending Machine terms of service. */ public static final String VENDING_TOS_VERSION = "vending_tos_version"; @@ -2973,6 +3203,13 @@ public final class Settings { "vending_pd_resend_frequency_ms"; /** + * Time before an asset in the 'DOWNLOADING' state is considered ready + * for an install kick on the client. + */ + public static final String VENDING_DOWNLOADING_KICK_TIMEOUT_MS = + "vending_downloading_kick_ms"; + + /** * Size of buffer in bytes for Vending to use when reading cache files. */ public static final String VENDING_DISK_INPUT_BUFFER_BYTES = @@ -2992,6 +3229,25 @@ public final class Settings { "vending_promo_refresh_freq_ms"; /** + * Frequency in milliseconds when we should refresh the provisioning information from + * the carrier backend. + */ + public static final String VENDING_CARRIER_PROVISIONING_REFRESH_FREQUENCY_MS = + "vending_carrier_ref_freq_ms"; + + /** + * Interval in milliseconds after which a failed provisioning request should be retried. + */ + public static final String VENDING_CARRIER_PROVISIONING_RETRY_MS = + "vending_carrier_prov_retry_ms"; + + /** + * Buffer in milliseconds for carrier credentials to be considered valid. + */ + public static final String VENDING_CARRIER_CREDENTIALS_BUFFER_MS = + "vending_carrier_cred_buf_ms"; + + /** * URL that points to the legal terms of service to display in Settings. * <p> * This should be a https URL. For a pretty user-friendly URL, use @@ -3225,39 +3481,6 @@ public final class Settings { "short_keylight_delay_ms"; /** - * URL that points to the voice search servers. To be factored out of this class. - */ - public static final String VOICE_SEARCH_URL = "voice_search_url"; - - /** - * Speech encoding used with voice search on 3G networks. To be factored out of this class. - */ - public static final String VOICE_SEARCH_ENCODING_THREE_G = "voice_search_encoding_three_g"; - - /** - * Speech encoding used with voice search on WIFI networks. To be factored out of this class. - */ - public static final String VOICE_SEARCH_ENCODING_WIFI = "voice_search_encoding_wifi"; - - /** - * Whether to use automatic gain control in voice search (0 = disable, 1 = enable). - * To be factored out of this class. - */ - public static final String VOICE_SEARCH_ENABLE_AGC = "voice_search_enable_agc"; - - /** - * Whether to use noise suppression in voice search (0 = disable, 1 = enable). - * To be factored out of this class. - */ - public static final String VOICE_SEARCH_ENABLE_NS = "voice_search_enable_ns"; - - /** - * Whether to use the IIR filter in voice search (0 = disable, 1 = enable). - * To be factored out of this class. - */ - public static final String VOICE_SEARCH_ENABLE_IIR = "voice_search_enable_iir"; - - /** * List of test suites (local disk filename) for the automatic instrumentation test runner. * The file format is similar to automated_suites.xml, see AutoTesterService. * If this setting is missing or empty, the automatic test runner will not start. @@ -3300,6 +3523,121 @@ public final class Settings { public static final String USE_LOCATION_FOR_SERVICES = "use_location"; /** + * The length of the calendar sync window into the future. + * This specifies the number of days into the future for the sliding window sync. + * Setting this to zero will disable sliding sync. + */ + public static final String GOOGLE_CALENDAR_SYNC_WINDOW_DAYS = + "google_calendar_sync_window_days"; + + /** + * How often to update the calendar sync window. + * The window will be advanced every n days. + */ + public static final String GOOGLE_CALENDAR_SYNC_WINDOW_UPDATE_DAYS = + "google_calendar_sync_window_update_days"; + + /** + * The number of promoted sources in GlobalSearch. + */ + public static final String SEARCH_NUM_PROMOTED_SOURCES = "search_num_promoted_sources"; + /** + * The maximum number of suggestions returned by GlobalSearch. + */ + public static final String SEARCH_MAX_RESULTS_TO_DISPLAY = "search_max_results_to_display"; + /** + * The number of suggestions GlobalSearch will ask each non-web search source for. + */ + public static final String SEARCH_MAX_RESULTS_PER_SOURCE = "search_max_results_per_source"; + /** + * The number of suggestions the GlobalSearch will ask the web search source for. + */ + public static final String SEARCH_WEB_RESULTS_OVERRIDE_LIMIT = + "search_web_results_override_limit"; + /** + * The number of milliseconds that GlobalSearch will wait for suggestions from + * promoted sources before continuing with all other sources. + */ + public static final String SEARCH_PROMOTED_SOURCE_DEADLINE_MILLIS = + "search_promoted_source_deadline_millis"; + /** + * The number of milliseconds before GlobalSearch aborts search suggesiton queries. + */ + public static final String SEARCH_SOURCE_TIMEOUT_MILLIS = "search_source_timeout_millis"; + /** + * The maximum number of milliseconds that GlobalSearch shows the previous results + * after receiving a new query. + */ + public static final String SEARCH_PREFILL_MILLIS = "search_prefill_millis"; + /** + * The maximum age of log data used for shortcuts in GlobalSearch. + */ + public static final String SEARCH_MAX_STAT_AGE_MILLIS = "search_max_stat_age_millis"; + /** + * The maximum age of log data used for source ranking in GlobalSearch. + */ + public static final String SEARCH_MAX_SOURCE_EVENT_AGE_MILLIS = + "search_max_source_event_age_millis"; + /** + * The minimum number of impressions needed to rank a source in GlobalSearch. + */ + public static final String SEARCH_MIN_IMPRESSIONS_FOR_SOURCE_RANKING = + "search_min_impressions_for_source_ranking"; + /** + * The minimum number of clicks needed to rank a source in GlobalSearch. + */ + public static final String SEARCH_MIN_CLICKS_FOR_SOURCE_RANKING = + "search_min_clicks_for_source_ranking"; + /** + * The maximum number of shortcuts shown by GlobalSearch. + */ + public static final String SEARCH_MAX_SHORTCUTS_RETURNED = "search_max_shortcuts_returned"; + /** + * The size of the core thread pool for suggestion queries in GlobalSearch. + */ + public static final String SEARCH_QUERY_THREAD_CORE_POOL_SIZE = + "search_query_thread_core_pool_size"; + /** + * The maximum size of the thread pool for suggestion queries in GlobalSearch. + */ + public static final String SEARCH_QUERY_THREAD_MAX_POOL_SIZE = + "search_query_thread_max_pool_size"; + /** + * The size of the core thread pool for shortcut refreshing in GlobalSearch. + */ + public static final String SEARCH_SHORTCUT_REFRESH_CORE_POOL_SIZE = + "search_shortcut_refresh_core_pool_size"; + /** + * The maximum size of the thread pool for shortcut refreshing in GlobalSearch. + */ + public static final String SEARCH_SHORTCUT_REFRESH_MAX_POOL_SIZE = + "search_shortcut_refresh_max_pool_size"; + /** + * The maximun time that excess threads in the GlobalSeach thread pools will + * wait before terminating. + */ + public static final String SEARCH_THREAD_KEEPALIVE_SECONDS = + "search_thread_keepalive_seconds"; + /** + * The maximum number of concurrent suggestion queries to each source. + */ + public static final String SEARCH_PER_SOURCE_CONCURRENT_QUERY_LIMIT = + "search_per_source_concurrent_query_limit"; + + /** + * Flag for allowing ActivityManagerService to send ACTION_APP_ERROR intents + * on application crashes and ANRs. If this is disabled, the crash/ANR dialog + * will never display the "Report" button. + * Type: int ( 0 = disallow, 1 = allow ) + */ + public static final String SEND_ACTION_APP_ERROR = "send_action_app_error"; + + /** + * Maximum size of /proc/last_kmsg content to upload after reboot. + */ + public static final String LAST_KMSG_KB = "last_kmsg_kb"; + + /** * @deprecated * @hide */ @@ -3425,7 +3763,7 @@ public final class Settings { // The stored URL is bad... ignore it. } catch (IllegalArgumentException e) { // Column not found - Log.e(TAG, "Intent column not found", e); + Log.w(TAG, "Intent column not found", e); } } } finally { @@ -3542,42 +3880,6 @@ public final class Settings { } /** - * Returns the GTalk JID resource associated with this device. - * - * @return String the JID resource of the device. It uses the device IMEI in the computation - * of the JID resource. If IMEI is not ready (i.e. telephony module not ready), we'll return - * an empty string. - * @hide - */ - // TODO: we shouldn't not have a permenant Jid resource, as that's an easy target for - // spams. We should change it once a while, like when we resubscribe to the subscription feeds - // server. - // (also, should this live in GTalkService?) - public static synchronized String getJidResource() { - if (sJidResource != null) { - return sJidResource; - } - - MessageDigest digest; - try { - digest = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("this should never happen"); - } - - String deviceId = TelephonyManager.getDefault().getDeviceId(); - if (TextUtils.isEmpty(deviceId)) { - return ""; - } - - byte[] hashedDeviceId = digest.digest(deviceId.getBytes()); - String id = new String(Base64.encodeBase64(hashedDeviceId), 0, 12); - id = id.replaceAll("/", "_"); - sJidResource = JID_RESOURCE_PREFIX + id; - return sJidResource; - } - - /** * Returns the device ID that we should use when connecting to the mobile gtalk server. * This is a string like "android-0x1242", where the hex string is the Android ID obtained * from the GoogleLoginService. diff --git a/core/java/android/provider/SocialContract.java b/core/java/android/provider/SocialContract.java new file mode 100644 index 0000000..ee271ba --- /dev/null +++ b/core/java/android/provider/SocialContract.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.provider; + +import android.content.res.Resources; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.Data; + +/** + * The contract between the social provider and applications. Contains + * definitions for the supported URIs and columns. + * + * @hide + */ +public class SocialContract { + /** The authority for the social provider */ + public static final String AUTHORITY = "com.android.social"; + + /** A content:// style uri to the authority for the contacts provider */ + public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); + + private interface ActivitiesColumns { + /** + * The package name to use when creating {@link Resources} objects for + * this data row. This value is only designed for use when building user + * interfaces, and should not be used to infer the owner. + * <p> + * Type: TEXT + */ + public static final String RES_PACKAGE = "res_package"; + + /** + * The mime-type of this social activity. + * <p> + * Type: TEXT + */ + public static final String MIMETYPE = "mimetype"; + + /** + * Internal raw identifier for this social activity. This field is + * analogous to the <code>atom:id</code> element defined in RFC 4287. + * <p> + * Type: TEXT + */ + public static final String RAW_ID = "raw_id"; + + /** + * Reference to another {@link Activities#RAW_ID} that this social activity + * is replying to. This field is analogous to the + * <code>thr:in-reply-to</code> element defined in RFC 4685. + * <p> + * Type: TEXT + */ + public static final String IN_REPLY_TO = "in_reply_to"; + + /** + * Reference to the {@link android.provider.ContactsContract.Contacts#_ID} that authored + * this social activity. This field is analogous to the <code>atom:author</code> + * element defined in RFC 4287. + * <p> + * Type: INTEGER + */ + public static final String AUTHOR_CONTACT_ID = "author_contact_id"; + + /** + * Optional reference to the {@link android.provider.ContactsContract.Contacts#_ID} this + * social activity is targeted towards. If more than one direct target, this field may + * be left undefined. This field is analogous to the + * <code>activity:target</code> element defined in the Atom Activity + * Extensions Internet-Draft. + * <p> + * Type: INTEGER + */ + public static final String TARGET_CONTACT_ID = "target_contact_id"; + + /** + * Timestamp when this social activity was published, in a + * {@link System#currentTimeMillis()} time base. This field is analogous + * to the <code>atom:published</code> element defined in RFC 4287. + * <p> + * Type: INTEGER + */ + public static final String PUBLISHED = "published"; + + /** + * Timestamp when the original social activity in a thread was + * published. For activities that have an in-reply-to field specified, the + * content provider will automatically populate this field with the + * timestamp of the original activity. + * <p> + * This field is useful for sorting order of activities that keeps together all + * messages in each thread. + * <p> + * Type: INTEGER + */ + public static final String THREAD_PUBLISHED = "thread_published"; + + /** + * Title of this social activity. This field is analogous to the + * <code>atom:title</code> element defined in RFC 4287. + * <p> + * Type: TEXT + */ + public static final String TITLE = "title"; + + /** + * Summary of this social activity. This field is analogous to the + * <code>atom:summary</code> element defined in RFC 4287. + * <p> + * Type: TEXT + */ + public static final String SUMMARY = "summary"; + + /** + * A URI associated this social activity. This field is analogous to the + * <code>atom:link rel="alternate"</code> element defined in RFC 4287. + * <p> + * Type: TEXT + */ + public static final String LINK = "link"; + + /** + * Optional thumbnail specific to this social activity. This is the raw + * bytes of an image that could be inflated using {@link BitmapFactory}. + * <p> + * Type: BLOB + */ + public static final String THUMBNAIL = "thumbnail"; + } + + public static final class Activities implements BaseColumns, ActivitiesColumns { + /** + * This utility class cannot be instantiated + */ + private Activities() { + } + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "activities"); + + /** + * The content:// URI for this table filtered to the set of social activities + * authored by a specific {@link android.provider.ContactsContract.Contacts#_ID}. + */ + public static final Uri CONTENT_AUTHORED_BY_URI = + Uri.withAppendedPath(CONTENT_URI, "authored_by"); + + /** + * The {@link Uri} for the latest social activity performed by any + * raw contact aggregated under the specified {@link Contacts#_ID}. Will + * also join with most-present {@link Presence} for this aggregate. + */ + public static final Uri CONTENT_CONTACT_STATUS_URI = + Uri.withAppendedPath(AUTHORITY_URI, "contact_status"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of social + * activities. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/activity"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * social activity. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/activity"; + } + +} diff --git a/core/java/android/provider/SubscribedFeeds.java b/core/java/android/provider/SubscribedFeeds.java index 4d430d5..8e9f402 100644 --- a/core/java/android/provider/SubscribedFeeds.java +++ b/core/java/android/provider/SubscribedFeeds.java @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; +import android.accounts.Account; /** * The SubscribedFeeds provider stores all information about subscribed feeds. @@ -99,7 +100,7 @@ public class SubscribedFeeds { /** * The default sort order for this table */ - public static final String DEFAULT_SORT_ORDER = "_SYNC_ACCOUNT ASC"; + public static final String DEFAULT_SORT_ORDER = "_SYNC_ACCOUNT_TYPE, _SYNC_ACCOUNT ASC"; } /** @@ -114,38 +115,36 @@ public class SubscribedFeeds { * @return the Uri of the feed that was added */ public static Uri addFeed(ContentResolver resolver, - String feed, String account, + String feed, Account account, String authority, String service) { ContentValues values = new ContentValues(); values.put(SubscribedFeeds.Feeds.FEED, feed); - values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, account); + values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, account.name); + values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE, account.type); values.put(SubscribedFeeds.Feeds.AUTHORITY, authority); values.put(SubscribedFeeds.Feeds.SERVICE, service); return resolver.insert(SubscribedFeeds.Feeds.CONTENT_URI, values); } public static int deleteFeed(ContentResolver resolver, - String feed, String account, String authority) { + String feed, Account account, String authority) { StringBuilder where = new StringBuilder(); where.append(SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=?"); + where.append(" AND " + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "=?"); where.append(" AND " + SubscribedFeeds.Feeds.FEED + "=?"); where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?"); return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI, - where.toString(), new String[] {account, feed, authority}); + where.toString(), new String[] {account.name, account.type, feed, authority}); } public static int deleteFeeds(ContentResolver resolver, - String account, String authority) { + Account account, String authority) { StringBuilder where = new StringBuilder(); where.append(SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=?"); + where.append(" AND " + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "=?"); where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?"); return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI, - where.toString(), new String[] {account, authority}); - } - - public static String gtalkServiceRoutingInfoFromAccountAndResource( - String account, String res) { - return Uri.parse("gtalk://" + account + "/" + res).toString(); + where.toString(), new String[] {account.name, account.type, authority}); } /** @@ -157,6 +156,12 @@ public class SubscribedFeeds { * <P>Type: TEXT</P> */ public static final String _SYNC_ACCOUNT = SyncConstValue._SYNC_ACCOUNT; + + /** + * The account type. + * <P>Type: TEXT</P> + */ + public static final String _SYNC_ACCOUNT_TYPE = SyncConstValue._SYNC_ACCOUNT_TYPE; } /** @@ -199,6 +204,6 @@ public class SubscribedFeeds { /** * The default sort order for this table */ - public static final String DEFAULT_SORT_ORDER = "_SYNC_ACCOUNT ASC"; + public static final String DEFAULT_SORT_ORDER = "_SYNC_ACCOUNT_TYPE, _SYNC_ACCOUNT ASC"; } } diff --git a/core/java/android/provider/SyncConstValue.java b/core/java/android/provider/SyncConstValue.java index 6eb4398..30966eb 100644 --- a/core/java/android/provider/SyncConstValue.java +++ b/core/java/android/provider/SyncConstValue.java @@ -29,6 +29,12 @@ public interface SyncConstValue public static final String _SYNC_ACCOUNT = "_sync_account"; /** + * The type of the account that was used to sync the entry to the device. + * <P>Type: TEXT</P> + */ + public static final String _SYNC_ACCOUNT_TYPE = "_sync_account_type"; + + /** * The unique ID for a row assigned by the sync source. NULL if the row has never been synced. * <P>Type: TEXT</P> */ @@ -68,4 +74,9 @@ public interface SyncConstValue * Used to indicate that this account is not synced */ public static final String NON_SYNCABLE_ACCOUNT = "non_syncable"; + + /** + * Used to indicate that this account is not synced + */ + public static final String NON_SYNCABLE_ACCOUNT_TYPE = "android.local"; } diff --git a/core/java/android/provider/SyncStateContract.java b/core/java/android/provider/SyncStateContract.java new file mode 100644 index 0000000..e8177ca --- /dev/null +++ b/core/java/android/provider/SyncStateContract.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.provider; + +import android.net.Uri; +import android.content.ContentProviderClient; +import android.content.ContentValues; +import android.content.ContentProviderOperation; +import android.content.ContentUris; +import android.accounts.Account; +import android.database.Cursor; +import android.os.RemoteException; +import android.util.Pair; + +/** + * The ContentProvider contract for associating data with ana data array account. + * This may be used by providers that want to store this data in a standard way. + */ +public class SyncStateContract { + public interface Columns extends BaseColumns { + /** + * A reference to the name of the account to which this data belongs + * <P>Type: STRING</P> + */ + public static final String ACCOUNT_NAME = "account_name"; + + /** + * A reference to the type of the account to which this data belongs + * <P>Type: STRING</P> + */ + public static final String ACCOUNT_TYPE = "account_type"; + + /** + * The sync data associated with this account. + * <P>Type: NONE</P> + */ + public static final String DATA = "data"; + } + + public static class Constants implements Columns { + public static final String CONTENT_DIRECTORY = "syncstate"; + } + + public static final class Helpers { + private static final String[] DATA_PROJECTION = new String[]{Columns.DATA, Columns._ID}; + private static final String SELECT_BY_ACCOUNT = + Columns.ACCOUNT_NAME + "=? AND " + Columns.ACCOUNT_TYPE + "=?"; + + /** + * Get the sync state that is associated with the account or null. + * @param provider the {@link ContentProviderClient} that is to be used to communicate + * with the {@link android.content.ContentProvider} that contains the sync state. + * @param uri the uri of the sync state + * @param account the {@link Account} whose sync state should be returned + * @return the sync state or null if there is no sync state associated with the account + * @throws RemoteException if there is a failure communicating with the remote + * {@link android.content.ContentProvider} + */ + public static byte[] get(ContentProviderClient provider, Uri uri, + Account account) throws RemoteException { + Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT, + new String[]{account.name, account.type}, null); + try { + if (c.moveToNext()) { + return c.getBlob(c.getColumnIndexOrThrow(Columns.DATA)); + } + } finally { + c.close(); + } + return null; + } + + /** + * Assigns the data array as the sync state for the given account. + * @param provider the {@link ContentProviderClient} that is to be used to communicate + * with the {@link android.content.ContentProvider} that contains the sync state. + * @param uri the uri of the sync state + * @param account the {@link Account} whose sync state should be set + * @param data the byte[] that contains the sync state + * @throws RemoteException if there is a failure communicating with the remote + * {@link android.content.ContentProvider} + */ + public static void set(ContentProviderClient provider, Uri uri, + Account account, byte[] data) throws RemoteException { + ContentValues values = new ContentValues(); + values.put(Columns.DATA, data); + values.put(Columns.ACCOUNT_NAME, account.name); + values.put(Columns.ACCOUNT_TYPE, account.type); + provider.insert(uri, values); + } + + public static Uri insert(ContentProviderClient provider, Uri uri, + Account account, byte[] data) throws RemoteException { + ContentValues values = new ContentValues(); + values.put(Columns.DATA, data); + values.put(Columns.ACCOUNT_NAME, account.name); + values.put(Columns.ACCOUNT_TYPE, account.type); + return provider.insert(uri, values); + } + + public static void update(ContentProviderClient provider, Uri uri, byte[] data) + throws RemoteException { + ContentValues values = new ContentValues(); + values.put(Columns.DATA, data); + provider.update(uri, values, null, null); + } + + public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Uri uri, + Account account) throws RemoteException { + Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT, + new String[]{account.name, account.type}, null); + try { + if (c.moveToNext()) { + long rowId = c.getLong(1); + byte[] blob = c.getBlob(c.getColumnIndexOrThrow(Columns.DATA)); + return Pair.create(ContentUris.withAppendedId(uri, rowId), blob); + } + } finally { + c.close(); + } + return null; + } + + /** + * Creates and returns a ContentProviderOperation that assigns the data array as the + * sync state for the given account. + * @param uri the uri of the sync state + * @param account the {@link Account} whose sync state should be set + * @param data the byte[] that contains the sync state + * @return the new ContentProviderOperation that assigns the data array as the + * account's sync state + */ + public static ContentProviderOperation newSetOperation(Uri uri, + Account account, byte[] data) { + ContentValues values = new ContentValues(); + values.put(Columns.DATA, data); + return ContentProviderOperation + .newInsert(uri) + .withValue(Columns.ACCOUNT_NAME, account.name) + .withValue(Columns.ACCOUNT_TYPE, account.type) + .withValues(values) + .build(); + } + + /** + * Creates and returns a ContentProviderOperation that assigns the data array as the + * sync state for the given account. + * @param uri the uri of the specific sync state to set + * @param data the byte[] that contains the sync state + * @return the new ContentProviderOperation that assigns the data array as the + * account's sync state + */ + public static ContentProviderOperation newUpdateOperation(Uri uri, byte[] data) { + ContentValues values = new ContentValues(); + values.put(Columns.DATA, data); + return ContentProviderOperation + .newUpdate(uri) + .withValues(values) + .build(); + } + } +} diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index c292c53..d8c5a53 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -146,7 +146,13 @@ public final class Telephony { * <P>Type: TEXT</P> */ public static final String SERVICE_CENTER = "service_center"; - } + + /** + * Has the message been locked? + * <P>Type: INTEGER (boolean)</P> + */ + public static final String LOCKED = "locked"; +} /** * Contains all text based SMS messages. @@ -484,6 +490,13 @@ public final class Telephony { public static final int RESULT_SMS_OUT_OF_MEMORY = 3; /** + * Set by BroadcastReceiver. Indicates the message, while + * possibly valid, is of a format or encoding that is not + * supported. + */ + public static final int RESULT_SMS_UNSUPPORTED = 4; + + /** * Broadcast Action: A new text based SMS message has been received * by the device. The intent will have the following extra * values:</p> @@ -552,6 +565,23 @@ public final class Telephony { "android.provider.Telephony.SIM_FULL"; /** + * Broadcast Action: An incoming SMS has been rejected by the + * telephony framework. This intent is sent in lieu of any + * of the RECEIVED_ACTION intents. The intent will have the + * following extra value:</p> + * + * <ul> + * <li><em>result</em> - An int result code, eg, + * <code>{@link #RESULT_SMS_OUT_OF_MEMORY}</code>, + * indicating the error returned to the network.</li> + * </ul> + + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String SMS_REJECTED_ACTION = + "android.provider.Telephony.SMS_REJECTED"; + + /** * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a * {@link #DATA_SMS_RECEIVED_ACTION} intent. * @@ -1008,6 +1038,12 @@ public final class Telephony { * <P>Type: INTEGER</P> */ public static final String THREAD_ID = "thread_id"; + + /** + * Has the message been locked? + * <P>Type: INTEGER (boolean)</P> + */ + public static final String LOCKED = "locked"; } /** @@ -1252,6 +1288,21 @@ public final class Telephony { } /** + * Returns true if the number is a Phone number + * + * @param number the input number to be tested + * @return true if number is a Phone number + */ + public static boolean isPhoneNumber(String number) { + if (TextUtils.isEmpty(number)) { + return false; + } + + Matcher match = Regex.PHONE_PATTERN.matcher(number); + return match.matches(); + } + + /** * Contains all MMS messages in the MMS app's inbox. */ public static final class Inbox implements BaseMmsColumns { @@ -1416,6 +1467,8 @@ public final class Telephony { */ public static final String _DATA = "_data"; + public static final String TEXT = "text"; + } public static final class Rate { @@ -1428,6 +1481,21 @@ public final class Telephony { public static final String SENT_TIME = "sent_time"; } + public static final class ScrapSpace { + /** + * The content:// style URL for this table + */ + public static final Uri CONTENT_URI = Uri.parse("content://mms/scrapSpace"); + + /** + * This is the scrap file we use to store the media attachment when the user + * chooses to capture a photo to be attached . We pass {#link@Uri} to the Camera app, + * which streams the captured image to the uri. Internally we write the media content + * to this file. It's named '.temp.jpg' so Gallery won't pick it up. + */ + public static final String SCRAP_FILE_PATH = "/sdcard/mms/scrapSpace/.temp.jpg"; + } + public static final class Intents { private Intents() { // Non-instantiatable. @@ -1493,6 +1561,17 @@ public final class Telephony { public static final Uri CONTENT_DRAFT_URI = Uri.parse( "content://mms-sms/draft"); + public static final Uri CONTENT_LOCKED_URI = Uri.parse( + "content://mms-sms/locked"); + + /*** + * Pass in a query parameter called "pattern" which is the text + * to search for. + * The sort order is fixed to be thread_id ASC,date DESC. + */ + public static final Uri SEARCH_URI = Uri.parse( + "content://mms-sms/search"); + // Constants for message protocol types. public static final int SMS_PROTO = 0; public static final int MMS_PROTO = 1; @@ -1590,6 +1669,8 @@ public final class Telephony { public static final String NUMERIC = "numeric"; + public static final String AUTH_TYPE = "authtype"; + public static final String TYPE = "type"; public static final String CURRENT = "current"; @@ -1639,7 +1720,3 @@ public final class Telephony { public static final String EXTRA_SPN = "spn"; } } - - - - |