Contacts.java revision 8ba63601ab3aa4042f8801529cb629450aea4bc3
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.provider;
18
19import com.android.internal.R;
20
21import android.content.ContentResolver;
22import android.content.ContentUris;
23import android.content.ContentValues;
24import android.content.Context;
25import android.content.Intent;
26import android.database.Cursor;
27import android.graphics.Bitmap;
28import android.graphics.BitmapFactory;
29import android.net.Uri;
30import android.text.TextUtils;
31import android.util.Log;
32import android.widget.ImageView;
33import android.accounts.Account;
34
35import java.io.ByteArrayInputStream;
36import java.io.InputStream;
37
38/**
39 * The Contacts provider stores all information about contacts.
40 */
41public class Contacts {
42    private static final String TAG = "Contacts";
43
44    public static final String AUTHORITY = "contacts";
45
46    /**
47     * The content:// style URL for this provider
48     */
49    public static final Uri CONTENT_URI =
50        Uri.parse("content://" + AUTHORITY);
51
52    /** Signifies an email address row that is stored in the ContactMethods table */
53    public static final int KIND_EMAIL = 1;
54    /** Signifies a postal address row that is stored in the ContactMethods table */
55    public static final int KIND_POSTAL = 2;
56    /** Signifies an IM address row that is stored in the ContactMethods table */
57    public static final int KIND_IM = 3;
58    /** Signifies an Organization row that is stored in the Organizations table */
59    public static final int KIND_ORGANIZATION = 4;
60    /** Signifies an Phone row that is stored in the Phones table */
61    public static final int KIND_PHONE = 5;
62
63    /**
64     * no public constructor since this is a utility class
65     */
66    private Contacts() {}
67
68    /**
69     * Columns from the Settings table that other columns join into themselves.
70     */
71    public interface SettingsColumns {
72        /**
73         * The _SYNC_ACCOUNT to which this setting corresponds. This may be null.
74         * <P>Type: TEXT</P>
75         */
76        public static final String _SYNC_ACCOUNT = "_sync_account";
77
78        /**
79         * The _SYNC_ACCOUNT_TYPE to which this setting corresponds. This may be null.
80         * <P>Type: TEXT</P>
81         */
82        public static final String _SYNC_ACCOUNT_TYPE = "_sync_account_type";
83
84        /**
85         * The key of this setting.
86         * <P>Type: TEXT</P>
87         */
88        public static final String KEY = "key";
89
90        /**
91         * The value of this setting.
92         * <P>Type: TEXT</P>
93         */
94        public static final String VALUE = "value";
95    }
96
97    /**
98     * The settings over all of the people
99     */
100    public static final class Settings implements BaseColumns, SettingsColumns {
101        /**
102         * no public constructor since this is a utility class
103         */
104        private Settings() {}
105
106        /**
107         * The content:// style URL for this table
108         */
109        public static final Uri CONTENT_URI =
110            Uri.parse("content://contacts/settings");
111
112        /**
113         * The directory twig for this sub-table
114         */
115        public static final String CONTENT_DIRECTORY = "settings";
116
117        /**
118         * The default sort order for this table
119         */
120        public static final String DEFAULT_SORT_ORDER = "key ASC";
121
122        /**
123         * A setting that is used to indicate if we should sync down all groups for the
124         * specified account. For this setting the _SYNC_ACCOUNT column must be set.
125         * If this isn't set then we will only sync the groups whose SHOULD_SYNC column
126         * is set to true.
127         * <p>
128         * This is a boolean setting. It is true if it is set and it is anything other than the
129         * emptry string or "0".
130         */
131        public static final String SYNC_EVERYTHING = "syncEverything";
132
133        public static String getSetting(ContentResolver cr, String account, String key) {
134            // For now we only support a single account and the UI doesn't know what
135            // the account name is, so we're using a global setting for SYNC_EVERYTHING.
136            // Some day when we add multiple accounts to the UI this should honor the account
137            // that was asked for.
138            String selectString;
139            String[] selectArgs;
140            if (false) {
141                selectString = (account == null)
142                        ? "_sync_account is null AND key=?"
143                        : "_sync_account=? AND key=?";
144//                : "_sync_account=? AND _sync_account_type=? AND key=?";
145                selectArgs = (account == null)
146                ? new String[]{key}
147                : new String[]{account, key};
148            } else {
149                selectString = "key=?";
150                selectArgs = new String[] {key};
151            }
152            Cursor cursor = cr.query(Settings.CONTENT_URI, new String[]{VALUE},
153                    selectString, selectArgs, null);
154            try {
155                if (!cursor.moveToNext()) return null;
156                return cursor.getString(0);
157            } finally {
158                cursor.close();
159            }
160        }
161
162        public static void setSetting(ContentResolver cr, String account, String key,
163                String value) {
164            ContentValues values = new ContentValues();
165            // For now we only support a single account and the UI doesn't know what
166            // the account name is, so we're using a global setting for SYNC_EVERYTHING.
167            // Some day when we add multiple accounts to the UI this should honor the account
168            // that was asked for.
169            //values.put(_SYNC_ACCOUNT, account.mName);
170            //values.put(_SYNC_ACCOUNT_TYPE, account.mType);
171            values.put(KEY, key);
172            values.put(VALUE, value);
173            cr.update(Settings.CONTENT_URI, values, null, null);
174        }
175    }
176
177    /**
178     * Columns from the People table that other tables join into themselves.
179     */
180    public interface PeopleColumns {
181        /**
182         * The person's name.
183         * <P>Type: TEXT</P>
184         */
185        public static final String NAME = "name";
186
187        /**
188         * Phonetic equivalent of the person's name, in a locale-dependent
189         * character set (e.g. hiragana for Japanese).
190         * Used for pronunciation and/or collation in some languages.
191         * <p>Type: TEXT</P>
192         */
193        public static final String PHONETIC_NAME = "phonetic_name";
194
195        /**
196         * The display name. If name is not null name, else if number is not null number,
197         * else if email is not null email.
198         * <P>Type: TEXT</P>
199         */
200        public static final String DISPLAY_NAME = "display_name";
201
202        /**
203         * The field for sorting list phonetically. The content of this field
204         * may not be human readable but phonetically sortable.
205         * <P>Type: TEXT</p>
206         * @hide Used only in Contacts application for now.
207         */
208        public static final String SORT_STRING = "sort_string";
209
210        /**
211         * Notes about the person.
212         * <P>Type: TEXT</P>
213         */
214        public static final String NOTES = "notes";
215
216        /**
217         * The number of times a person has been contacted
218         * <P>Type: INTEGER</P>
219         */
220        public static final String TIMES_CONTACTED = "times_contacted";
221
222        /**
223         * The last time a person was contacted.
224         * <P>Type: INTEGER</P>
225         */
226        public static final String LAST_TIME_CONTACTED = "last_time_contacted";
227
228        /**
229         * A custom ringtone associated with a person. Not always present.
230         * <P>Type: TEXT (URI to the ringtone)</P>
231         */
232        public static final String CUSTOM_RINGTONE = "custom_ringtone";
233
234        /**
235         * Whether the person should always be sent to voicemail. Not always
236         * present.
237         * <P>Type: INTEGER (0 for false, 1 for true)</P>
238         */
239        public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
240
241        /**
242         * Is the contact starred?
243         * <P>Type: INTEGER (boolean)</P>
244         */
245        public static final String STARRED = "starred";
246
247        /**
248         * The server version of the photo
249         * <P>Type: TEXT (the version number portion of the photo URI)</P>
250         */
251        public static final String PHOTO_VERSION = "photo_version";
252    }
253
254    /**
255     * This table contains people.
256     */
257    public static final class People implements BaseColumns, SyncConstValue, PeopleColumns,
258            PhonesColumns, PresenceColumns {
259        /**
260         * no public constructor since this is a utility class
261         */
262        private People() {}
263
264        /**
265         * The content:// style URL for this table
266         */
267        public static final Uri CONTENT_URI =
268            Uri.parse("content://contacts/people");
269
270        /**
271         * The content:// style URL for filtering people by name. The filter
272         * argument should be passed as an additional path segment after this URI.
273         */
274        public static final Uri CONTENT_FILTER_URI =
275            Uri.parse("content://contacts/people/filter");
276
277        /**
278         * The content:// style URL for the table that holds the deleted
279         * contacts.
280         */
281        public static final Uri DELETED_CONTENT_URI =
282            Uri.parse("content://contacts/deleted_people");
283
284        /**
285         * The content:// style URL for filtering people that have a specific
286         * E-mail or IM address. The filter argument should be passed as an
287         * additional path segment after this URI. This matches any people with
288         * at least one E-mail or IM {@link ContactMethods} that match the
289         * filter.
290         *
291         * Not exposed because we expect significant changes in the contacts
292         * schema and do not want to have to support this.
293         * @hide
294         */
295        public static final Uri WITH_EMAIL_OR_IM_FILTER_URI =
296            Uri.parse("content://contacts/people/with_email_or_im_filter");
297
298        /**
299         * The MIME type of {@link #CONTENT_URI} providing a directory of
300         * people.
301         */
302        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person";
303
304        /**
305         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
306         * person.
307         */
308        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";
309
310        /**
311         * The default sort order for this table
312         */
313        public static final String DEFAULT_SORT_ORDER = People.NAME + " ASC";
314
315        /**
316         * The ID of the persons preferred phone number.
317         * <P>Type: INTEGER (foreign key to phones table on the _ID field)</P>
318         */
319        public static final String PRIMARY_PHONE_ID = "primary_phone";
320
321        /**
322         * The ID of the persons preferred email.
323         * <P>Type: INTEGER (foreign key to contact_methods table on the
324         * _ID field)</P>
325         */
326        public static final String PRIMARY_EMAIL_ID = "primary_email";
327
328        /**
329         * The ID of the persons preferred organization.
330         * <P>Type: INTEGER (foreign key to organizations table on the
331         * _ID field)</P>
332         */
333        public static final String PRIMARY_ORGANIZATION_ID = "primary_organization";
334
335        /**
336         * Mark a person as having been contacted.
337         *
338         * @param resolver the ContentResolver to use
339         * @param personId the person who was contacted
340         */
341        public static void markAsContacted(ContentResolver resolver, long personId) {
342            Uri uri = ContentUris.withAppendedId(CONTENT_URI, personId);
343            uri = Uri.withAppendedPath(uri, "update_contact_time");
344            ContentValues values = new ContentValues();
345            // There is a trigger in place that will update TIMES_CONTACTED when
346            // LAST_TIME_CONTACTED is modified.
347            values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());
348            resolver.update(uri, values, null, null);
349        }
350
351        /**
352         * @hide Used in vCard parser code.
353         */
354        public static long tryGetMyContactsGroupId(ContentResolver resolver) {
355            Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
356                    Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null);
357            if (groupsCursor != null) {
358                try {
359                    if (groupsCursor.moveToFirst()) {
360                        return groupsCursor.getLong(0);
361                    }
362                } finally {
363                    groupsCursor.close();
364                }
365            }
366            return 0;
367        }
368
369        /**
370         * Adds a person to the My Contacts group.
371         *
372         * @param resolver the resolver to use
373         * @param personId the person to add to the group
374         * @return the URI of the group membership row
375         * @throws IllegalStateException if the My Contacts group can't be found
376         */
377        public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) {
378            long groupId = tryGetMyContactsGroupId(resolver);
379            if (groupId == 0) {
380                throw new IllegalStateException("Failed to find the My Contacts group");
381            }
382
383            return addToGroup(resolver, personId, groupId);
384        }
385
386        /**
387         * Adds a person to a group referred to by name.
388         *
389         * @param resolver the resolver to use
390         * @param personId the person to add to the group
391         * @param groupName the name of the group to add the contact to
392         * @return the URI of the group membership row
393         * @throws IllegalStateException if the group can't be found
394         */
395        public static Uri addToGroup(ContentResolver resolver, long personId, String groupName) {
396            long groupId = 0;
397            Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
398                    Groups.NAME + "=?", new String[] { groupName }, null);
399            if (groupsCursor != null) {
400                try {
401                    if (groupsCursor.moveToFirst()) {
402                        groupId = groupsCursor.getLong(0);
403                    }
404                } finally {
405                    groupsCursor.close();
406                }
407            }
408
409            if (groupId == 0) {
410                throw new IllegalStateException("Failed to find the My Contacts group");
411            }
412
413            return addToGroup(resolver, personId, groupId);
414        }
415
416        /**
417         * Adds a person to a group.
418         *
419         * @param resolver the resolver to use
420         * @param personId the person to add to the group
421         * @param groupId the group to add the person to
422         * @return the URI of the group membership row
423         */
424        public static Uri addToGroup(ContentResolver resolver, long personId, long groupId) {
425            ContentValues values = new ContentValues();
426            values.put(GroupMembership.PERSON_ID, personId);
427            values.put(GroupMembership.GROUP_ID, groupId);
428            return resolver.insert(GroupMembership.CONTENT_URI, values);
429        }
430
431        private static final String[] GROUPS_PROJECTION = new String[] {
432            Groups._ID,
433        };
434
435        /**
436         * Creates a new contacts and adds it to the "My Contacts" group.
437         *
438         * @param resolver the ContentResolver to use
439         * @param values the values to use when creating the contact
440         * @return the URI of the contact, or null if the operation fails
441         */
442        public static Uri createPersonInMyContactsGroup(ContentResolver resolver,
443                ContentValues values) {
444
445            Uri contactUri = resolver.insert(People.CONTENT_URI, values);
446            if (contactUri == null) {
447                Log.e(TAG, "Failed to create the contact");
448                return null;
449            }
450
451            if (addToMyContactsGroup(resolver, ContentUris.parseId(contactUri)) == null) {
452                resolver.delete(contactUri, null, null);
453                return null;
454            }
455            return contactUri;
456        }
457
458        public static Cursor queryGroups(ContentResolver resolver, long person) {
459            return resolver.query(GroupMembership.CONTENT_URI, null, "person=?",
460                    new String[]{String.valueOf(person)}, Groups.DEFAULT_SORT_ORDER);
461        }
462
463        /**
464         * Set the photo for this person. data may be null
465         * @param cr the ContentResolver to use
466         * @param person the Uri of the person whose photo is to be updated
467         * @param data the byte[] that represents the photo
468         */
469        public static void setPhotoData(ContentResolver cr, Uri person, byte[] data) {
470            Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);
471            ContentValues values = new ContentValues();
472            values.put(Photos.DATA, data);
473            cr.update(photoUri, values, null, null);
474        }
475
476        /**
477         * Opens an InputStream for the person's photo and returns the photo as a Bitmap.
478         * If the person's photo isn't present returns the placeholderImageResource instead.
479         * @param person the person whose photo should be used
480         */
481        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri person) {
482            Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);
483            Cursor cursor = cr.query(photoUri, new String[]{Photos.DATA}, null, null, null);
484            try {
485                if (!cursor.moveToNext()) {
486                    return null;
487                }
488                byte[] data = cursor.getBlob(0);
489                if (data == null) {
490                    return null;
491                }
492                return new ByteArrayInputStream(data);
493            } finally {
494                cursor.close();
495            }
496        }
497
498        /**
499         * Opens an InputStream for the person's photo and returns the photo as a Bitmap.
500         * If the person's photo isn't present returns the placeholderImageResource instead.
501         * @param context the Context
502         * @param person the person whose photo should be used
503         * @param placeholderImageResource the image resource to use if the person doesn't
504         *   have a photo
505         * @param options the decoding options, can be set to null
506         */
507        public static Bitmap loadContactPhoto(Context context, Uri person,
508                int placeholderImageResource, BitmapFactory.Options options) {
509            if (person == null) {
510                return loadPlaceholderPhoto(placeholderImageResource, context, options);
511            }
512
513            InputStream stream = openContactPhotoInputStream(context.getContentResolver(), person);
514            Bitmap bm = stream != null ? BitmapFactory.decodeStream(stream, null, options) : null;
515            if (bm == null) {
516                bm = loadPlaceholderPhoto(placeholderImageResource, context, options);
517            }
518            return bm;
519        }
520
521        private static Bitmap loadPlaceholderPhoto(int placeholderImageResource, Context context,
522                BitmapFactory.Options options) {
523            if (placeholderImageResource == 0) {
524                return null;
525            }
526            return BitmapFactory.decodeResource(context.getResources(),
527                    placeholderImageResource, options);
528        }
529
530        /**
531         * A sub directory of a single person that contains all of their Phones.
532         */
533        public static final class Phones implements BaseColumns, PhonesColumns,
534                PeopleColumns {
535            /**
536             * no public constructor since this is a utility class
537             */
538            private Phones() {}
539
540            /**
541             * The directory twig for this sub-table
542             */
543            public static final String CONTENT_DIRECTORY = "phones";
544
545            /**
546             * The default sort order for this table
547             */
548            public static final String DEFAULT_SORT_ORDER = "number ASC";
549        }
550
551        /**
552         * A subdirectory of a single person that contains all of their
553         * ContactMethods.
554         */
555        public static final class ContactMethods
556                implements BaseColumns, ContactMethodsColumns, PeopleColumns {
557            /**
558             * no public constructor since this is a utility class
559             */
560            private ContactMethods() {}
561
562            /**
563             * The directory twig for this sub-table
564             */
565            public static final String CONTENT_DIRECTORY = "contact_methods";
566
567            /**
568             * The default sort order for this table
569             */
570            public static final String DEFAULT_SORT_ORDER = "data ASC";
571        }
572
573        /**
574         * The extensions for a person
575         */
576        public static class Extensions implements BaseColumns, ExtensionsColumns {
577            /**
578             * no public constructor since this is a utility class
579             */
580            private Extensions() {}
581
582            /**
583             * The directory twig for this sub-table
584             */
585            public static final String CONTENT_DIRECTORY = "extensions";
586
587            /**
588             * The default sort order for this table
589             */
590            public static final String DEFAULT_SORT_ORDER = "name ASC";
591
592            /**
593             * The ID of the person this phone number is assigned to.
594             * <P>Type: INTEGER (long)</P>
595             */
596            public static final String PERSON_ID = "person";
597        }
598    }
599
600    /**
601     * Columns from the groups table.
602     */
603    public interface GroupsColumns {
604        /**
605         * The group name.
606         * <P>Type: TEXT</P>
607         */
608        public static final String NAME = "name";
609
610        /**
611         * Notes about the group.
612         * <P>Type: TEXT</P>
613         */
614        public static final String NOTES = "notes";
615
616        /**
617         * Whether this group should be synced if the SYNC_EVERYTHING settings is false
618         * for this group's account.
619         * <P>Type: INTEGER (boolean)</P>
620         */
621        public static final String SHOULD_SYNC = "should_sync";
622
623        /**
624         * The ID of this group if it is a System Group, null otherwise.
625         * <P>Type: TEXT</P>
626         */
627        public static final String SYSTEM_ID = "system_id";
628    }
629
630    /**
631     * This table contains the groups for an account.
632     */
633    public static final class Groups
634            implements BaseColumns, SyncConstValue, GroupsColumns {
635        /**
636         * no public constructor since this is a utility class
637         */
638        private Groups() {}
639
640        /**
641         * The content:// style URL for this table
642         */
643        public static final Uri CONTENT_URI =
644            Uri.parse("content://contacts/groups");
645
646        /**
647         * The content:// style URL for the table that holds the deleted
648         * groups.
649         */
650        public static final Uri DELETED_CONTENT_URI =
651            Uri.parse("content://contacts/deleted_groups");
652
653        /**
654         * The MIME type of {@link #CONTENT_URI} providing a directory of
655         * groups.
656         */
657        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroup";
658
659        /**
660         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
661         * group.
662         */
663        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroup";
664
665        /**
666         * The default sort order for this table
667         */
668        public static final String DEFAULT_SORT_ORDER = NAME + " ASC";
669
670        /**
671         *
672         */
673        public static final String GROUP_ANDROID_STARRED = "Starred in Android";
674
675        /**
676         * The "My Contacts" system group.
677         */
678        public static final String GROUP_MY_CONTACTS = "Contacts";
679    }
680
681    /**
682     * Columns from the Phones table that other columns join into themselves.
683     */
684    public interface PhonesColumns {
685        /**
686         * The type of the the phone number.
687         * <P>Type: INTEGER (one of the constants below)</P>
688         */
689        public static final String TYPE = "type";
690
691        public static final int TYPE_CUSTOM = 0;
692        public static final int TYPE_HOME = 1;
693        public static final int TYPE_MOBILE = 2;
694        public static final int TYPE_WORK = 3;
695        public static final int TYPE_FAX_WORK = 4;
696        public static final int TYPE_FAX_HOME = 5;
697        public static final int TYPE_PAGER = 6;
698        public static final int TYPE_OTHER = 7;
699
700        /**
701         * The user provided label for the phone number, only used if TYPE is TYPE_CUSTOM.
702         * <P>Type: TEXT</P>
703         */
704        public static final String LABEL = "label";
705
706        /**
707         * The phone number as the user entered it.
708         * <P>Type: TEXT</P>
709         */
710        public static final String NUMBER = "number";
711
712        /**
713         * The normalized phone number
714         * <P>Type: TEXT</P>
715         */
716        public static final String NUMBER_KEY = "number_key";
717
718        /**
719         * Whether this is the primary phone number
720         * <P>Type: INTEGER (if set, non-0 means true)</P>
721         */
722        public static final String ISPRIMARY = "isprimary";
723    }
724
725    /**
726     * This table stores phone numbers and a reference to the person that the
727     * contact method belongs to. Phone numbers are stored separately from
728     * other contact methods to make caller ID lookup more efficient.
729     */
730    public static final class Phones
731            implements BaseColumns, PhonesColumns, PeopleColumns {
732        /**
733         * no public constructor since this is a utility class
734         */
735        private Phones() {}
736
737        public static final CharSequence getDisplayLabel(Context context, int type,
738                CharSequence label, CharSequence[] labelArray) {
739            CharSequence display = "";
740
741            if (type != People.Phones.TYPE_CUSTOM) {
742                CharSequence[] labels = labelArray != null? labelArray
743                        : context.getResources().getTextArray(
744                                com.android.internal.R.array.phoneTypes);
745                try {
746                    display = labels[type - 1];
747                } catch (ArrayIndexOutOfBoundsException e) {
748                    display = labels[People.Phones.TYPE_HOME - 1];
749                }
750            } else {
751                if (!TextUtils.isEmpty(label)) {
752                    display = label;
753                }
754            }
755            return display;
756        }
757
758        public static final CharSequence getDisplayLabel(Context context, int type,
759                CharSequence label) {
760            return getDisplayLabel(context, type, label, null);
761        }
762
763        /**
764         * The content:// style URL for this table
765         */
766        public static final Uri CONTENT_URI =
767            Uri.parse("content://contacts/phones");
768
769        /**
770         * The content:// style URL for filtering phone numbers
771         */
772        public static final Uri CONTENT_FILTER_URL =
773            Uri.parse("content://contacts/phones/filter");
774
775        /**
776         * The MIME type of {@link #CONTENT_URI} providing a directory of
777         * phones.
778         */
779        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone";
780
781        /**
782         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
783         * phone.
784         */
785        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";
786
787        /**
788         * The default sort order for this table
789         */
790        public static final String DEFAULT_SORT_ORDER = "name ASC";
791
792        /**
793         * The ID of the person this phone number is assigned to.
794         * <P>Type: INTEGER (long)</P>
795         */
796        public static final String PERSON_ID = "person";
797    }
798
799    public static final class GroupMembership implements BaseColumns, GroupsColumns {
800        /**
801         * no public constructor since this is a utility class
802         */
803        private GroupMembership() {}
804
805        /**
806         * The content:// style URL for this table
807         */
808        public static final Uri CONTENT_URI =
809            Uri.parse("content://contacts/groupmembership");
810
811        /**
812         * The content:// style URL for this table
813         */
814        public static final Uri RAW_CONTENT_URI =
815            Uri.parse("content://contacts/groupmembershipraw");
816
817        /**
818         * The directory twig for this sub-table
819         */
820        public static final String CONTENT_DIRECTORY = "groupmembership";
821        /**
822         * The MIME type of {@link #CONTENT_URI} providing a directory of all
823         * person groups.
824         */
825        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroupmembership";
826
827        /**
828         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
829         * person group.
830         */
831        public static final String CONTENT_ITEM_TYPE =
832                "vnd.android.cursor.item/contactsgroupmembership";
833
834        /**
835         * The default sort order for this table
836         */
837        public static final String DEFAULT_SORT_ORDER = "group_id ASC";
838
839        /**
840         * The row id of the accounts group.
841         * <P>Type: TEXT</P>
842         */
843        public static final String GROUP_ID = "group_id";
844
845        /**
846         * The sync id of the group.
847         * <P>Type: TEXT</P>
848         */
849        public static final String GROUP_SYNC_ID = "group_sync_id";
850
851        /**
852         * The account of the group.
853         * <P>Type: TEXT</P>
854         */
855        public static final String GROUP_SYNC_ACCOUNT = "group_sync_account";
856
857        /**
858         * The account type of the group.
859         * <P>Type: TEXT</P>
860         */
861        public static final String GROUP_SYNC_ACCOUNT_TYPE = "group_sync_account_type";
862
863        /**
864         * The row id of the person.
865         * <P>Type: TEXT</P>
866         */
867        public static final String PERSON_ID = "person";
868    }
869
870    /**
871     * Columns from the ContactMethods table that other tables join into
872     * themseleves.
873     */
874    public interface ContactMethodsColumns {
875        /**
876         * The kind of the the contact method. For example, email address,
877         * postal address, etc.
878         * <P>Type: INTEGER (one of the values below)</P>
879         */
880        public static final String KIND = "kind";
881
882        /**
883         * The type of the contact method, must be one of the types below.
884         * <P>Type: INTEGER (one of the values below)</P>
885         */
886        public static final String TYPE = "type";
887        public static final int TYPE_CUSTOM = 0;
888        public static final int TYPE_HOME = 1;
889        public static final int TYPE_WORK = 2;
890        public static final int TYPE_OTHER = 3;
891
892        /**
893         * The user defined label for the the contact method.
894         * <P>Type: TEXT</P>
895         */
896        public static final String LABEL = "label";
897
898        /**
899         * The data for the contact method.
900         * <P>Type: TEXT</P>
901         */
902        public static final String DATA = "data";
903
904        /**
905         * Auxiliary data for the contact method.
906         * <P>Type: TEXT</P>
907         */
908        public static final String AUX_DATA = "aux_data";
909
910        /**
911         * Whether this is the primary organization
912         * <P>Type: INTEGER (if set, non-0 means true)</P>
913         */
914        public static final String ISPRIMARY = "isprimary";
915    }
916
917    /**
918     * This table stores all non-phone contact methods and a reference to the
919     * person that the contact method belongs to.
920     */
921    public static final class ContactMethods
922            implements BaseColumns, ContactMethodsColumns, PeopleColumns {
923        /**
924         * The column with latitude data for postal locations
925         * <P>Type: REAL</P>
926         */
927        public static final String POSTAL_LOCATION_LATITUDE = DATA;
928
929        /**
930         * The column with longitude data for postal locations
931         * <P>Type: REAL</P>
932         */
933        public static final String POSTAL_LOCATION_LONGITUDE = AUX_DATA;
934
935        /**
936         * The predefined IM protocol types. The protocol can either be non-present, one
937         * of these types, or a free-form string. These cases are encoded in the AUX_DATA
938         * column as:
939         *  - null
940         *  - pre:<an integer, one of the protocols below>
941         *  - custom:<a string>
942         */
943        public static final int PROTOCOL_AIM = 0;
944        public static final int PROTOCOL_MSN = 1;
945        public static final int PROTOCOL_YAHOO = 2;
946        public static final int PROTOCOL_SKYPE = 3;
947        public static final int PROTOCOL_QQ = 4;
948        public static final int PROTOCOL_GOOGLE_TALK = 5;
949        public static final int PROTOCOL_ICQ = 6;
950        public static final int PROTOCOL_JABBER = 7;
951
952        public static String encodePredefinedImProtocol(int protocol) {
953            return "pre:" + protocol;
954        }
955
956        public static String encodeCustomImProtocol(String protocolString) {
957            return "custom:" + protocolString;
958        }
959
960        public static Object decodeImProtocol(String encodedString) {
961            if (encodedString == null) {
962                return null;
963            }
964
965            if (encodedString.startsWith("pre:")) {
966                return Integer.parseInt(encodedString.substring(4));
967            }
968
969            if (encodedString.startsWith("custom:")) {
970                return encodedString.substring(7);
971            }
972
973            throw new IllegalArgumentException(
974                    "the value is not a valid encoded protocol, " + encodedString);
975        }
976
977        /**
978         * This looks up the provider name defined in
979         * {@link android.provider.Im.ProviderNames} from the predefined IM protocol id.
980         * This is used for interacting with the IM application.
981         *
982         * @param protocol the protocol ID
983         * @return the provider name the IM app uses for the given protocol, or null if no
984         * provider is defined for the given protocol
985         * @hide
986         */
987        public static String lookupProviderNameFromId(int protocol) {
988            switch (protocol) {
989                case PROTOCOL_GOOGLE_TALK:
990                    return Im.ProviderNames.GTALK;
991                case PROTOCOL_AIM:
992                    return Im.ProviderNames.AIM;
993                case PROTOCOL_MSN:
994                    return Im.ProviderNames.MSN;
995                case PROTOCOL_YAHOO:
996                    return Im.ProviderNames.YAHOO;
997                case PROTOCOL_ICQ:
998                    return Im.ProviderNames.ICQ;
999                case PROTOCOL_JABBER:
1000                    return Im.ProviderNames.JABBER;
1001                case PROTOCOL_SKYPE:
1002                    return Im.ProviderNames.SKYPE;
1003                case PROTOCOL_QQ:
1004                    return Im.ProviderNames.QQ;
1005            }
1006            return null;
1007        }
1008
1009        /**
1010         * no public constructor since this is a utility class
1011         */
1012        private ContactMethods() {}
1013
1014        public static final CharSequence getDisplayLabel(Context context, int kind,
1015                int type, CharSequence label) {
1016            CharSequence display = "";
1017            switch (kind) {
1018                case KIND_EMAIL: {
1019                    if (type != People.ContactMethods.TYPE_CUSTOM) {
1020                        CharSequence[] labels = context.getResources().getTextArray(
1021                                com.android.internal.R.array.emailAddressTypes);
1022                        try {
1023                            display = labels[type - 1];
1024                        } catch (ArrayIndexOutOfBoundsException e) {
1025                            display = labels[ContactMethods.TYPE_HOME - 1];
1026                        }
1027                    } else {
1028                        if (!TextUtils.isEmpty(label)) {
1029                            display = label;
1030                        }
1031                    }
1032                    break;
1033                }
1034
1035                case KIND_POSTAL: {
1036                    if (type != People.ContactMethods.TYPE_CUSTOM) {
1037                        CharSequence[] labels = context.getResources().getTextArray(
1038                                com.android.internal.R.array.postalAddressTypes);
1039                        try {
1040                            display = labels[type - 1];
1041                        } catch (ArrayIndexOutOfBoundsException e) {
1042                            display = labels[ContactMethods.TYPE_HOME - 1];
1043                        }
1044                    } else {
1045                        if (!TextUtils.isEmpty(label)) {
1046                            display = label;
1047                        }
1048                    }
1049                    break;
1050                }
1051
1052                default:
1053                    display = context.getString(R.string.untitled);
1054            }
1055            return display;
1056        }
1057
1058        /**
1059         * Add a longitude and latitude location to a postal address.
1060         *
1061         * @param context the context to use when updating the database
1062         * @param postalId the address to update
1063         * @param latitude the latitude for the address
1064         * @param longitude the longitude for the address
1065         */
1066        public void addPostalLocation(Context context, long postalId,
1067                double latitude, double longitude) {
1068            final ContentResolver resolver = context.getContentResolver();
1069            // Insert the location
1070            ContentValues values = new ContentValues(2);
1071            values.put(POSTAL_LOCATION_LATITUDE, latitude);
1072            values.put(POSTAL_LOCATION_LONGITUDE, longitude);
1073            Uri loc = resolver.insert(CONTENT_URI, values);
1074            long locId = ContentUris.parseId(loc);
1075
1076            // Update the postal address
1077            values.clear();
1078            values.put(AUX_DATA, locId);
1079            resolver.update(ContentUris.withAppendedId(CONTENT_URI, postalId), values, null, null);
1080        }
1081
1082        /**
1083         * The content:// style URL for this table
1084         */
1085        public static final Uri CONTENT_URI =
1086            Uri.parse("content://contacts/contact_methods");
1087
1088        /**
1089         * The content:// style URL for sub-directory of e-mail addresses.
1090         */
1091        public static final Uri CONTENT_EMAIL_URI =
1092            Uri.parse("content://contacts/contact_methods/email");
1093
1094        /**
1095         * The MIME type of {@link #CONTENT_URI} providing a directory of
1096         * phones.
1097         */
1098        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact-methods";
1099
1100        /**
1101         * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\
1102         * multiple {@link Contacts#KIND_EMAIL} entries.
1103         */
1104        public static final String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email";
1105
1106        /**
1107         * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\
1108         * multiple {@link Contacts#KIND_POSTAL} entries.
1109         */
1110        public static final String CONTENT_POSTAL_TYPE = "vnd.android.cursor.dir/postal-address";
1111
1112        /**
1113         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
1114         * {@link Contacts#KIND_EMAIL} entry.
1115         */
1116        public static final String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email";
1117
1118        /**
1119         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
1120         * {@link Contacts#KIND_POSTAL} entry.
1121         */
1122        public static final String CONTENT_POSTAL_ITEM_TYPE
1123                = "vnd.android.cursor.item/postal-address";
1124
1125        /**
1126         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
1127         * {@link Contacts#KIND_IM} entry.
1128         */
1129        public static final String CONTENT_IM_ITEM_TYPE = "vnd.android.cursor.item/jabber-im";
1130
1131        /**
1132         * The default sort order for this table
1133         */
1134        public static final String DEFAULT_SORT_ORDER = "name ASC";
1135
1136        /**
1137         * The ID of the person this contact method is assigned to.
1138         * <P>Type: INTEGER (long)</P>
1139         */
1140        public static final String PERSON_ID = "person";
1141    }
1142
1143    /**
1144     * The IM presence columns with some contacts specific columns mixed in.
1145     */
1146    public interface PresenceColumns extends Im.CommonPresenceColumns {
1147        /**
1148         * The IM service the presence is coming from. Formatted using either
1149         * {@link Contacts.ContactMethods#encodePredefinedImProtocol} or
1150         * {@link Contacts.ContactMethods#encodeCustomImProtocol}.
1151         * <P>Type: STRING</P>
1152         */
1153        public static final String IM_PROTOCOL = "im_protocol";
1154
1155        /**
1156         * The IM handle the presence item is for. The handle is scoped to
1157         * the {@link #IM_PROTOCOL}.
1158         * <P>Type: STRING</P>
1159         */
1160        public static final String IM_HANDLE = "im_handle";
1161
1162        /**
1163         * The IM account for the local user that the presence data came from.
1164         * <P>Type: STRING</P>
1165         */
1166        public static final String IM_ACCOUNT = "im_account";
1167    }
1168
1169    /**
1170     * Contains presence information about contacts.
1171     * @hide
1172     */
1173    public static final class Presence
1174            implements BaseColumns, PresenceColumns, PeopleColumns {
1175        /**
1176         * The content:// style URL for this table
1177         */
1178        public static final Uri CONTENT_URI =
1179            Uri.parse("content://contacts/presence");
1180
1181        /**
1182         * The ID of the person this presence item is assigned to.
1183         * <P>Type: INTEGER (long)</P>
1184         */
1185        public static final String PERSON_ID = "person";
1186
1187        /**
1188         * Gets the resource ID for the proper presence icon.
1189         *
1190         * @param status the status to get the icon for
1191         * @return the resource ID for the proper presence icon
1192         */
1193        public static final int getPresenceIconResourceId(int status) {
1194            switch (status) {
1195                case Contacts.People.AVAILABLE:
1196                    return com.android.internal.R.drawable.presence_online;
1197
1198                case Contacts.People.IDLE:
1199                case Contacts.People.AWAY:
1200                    return com.android.internal.R.drawable.presence_away;
1201
1202                case Contacts.People.DO_NOT_DISTURB:
1203                    return com.android.internal.R.drawable.presence_busy;
1204
1205                case Contacts.People.INVISIBLE:
1206                    return com.android.internal.R.drawable.presence_invisible;
1207
1208                case Contacts.People.OFFLINE:
1209                default:
1210                    return com.android.internal.R.drawable.presence_offline;
1211            }
1212        }
1213
1214        /**
1215         * Sets a presence icon to the proper graphic
1216         *
1217         * @param icon the icon to to set
1218         * @param serverStatus that status
1219         */
1220        public static final void setPresenceIcon(ImageView icon, int serverStatus) {
1221            icon.setImageResource(getPresenceIconResourceId(serverStatus));
1222        }
1223    }
1224
1225    /**
1226     * Columns from the Organizations table that other columns join into themselves.
1227     */
1228    public interface OrganizationColumns {
1229        /**
1230         * The type of the organizations.
1231         * <P>Type: INTEGER (one of the constants below)</P>
1232         */
1233        public static final String TYPE = "type";
1234
1235        public static final int TYPE_CUSTOM = 0;
1236        public static final int TYPE_WORK = 1;
1237        public static final int TYPE_OTHER = 2;
1238
1239        /**
1240         * The user provided label, only used if TYPE is TYPE_CUSTOM.
1241         * <P>Type: TEXT</P>
1242         */
1243        public static final String LABEL = "label";
1244
1245        /**
1246         * The name of the company for this organization.
1247         * <P>Type: TEXT</P>
1248         */
1249        public static final String COMPANY = "company";
1250
1251        /**
1252         * The title within this organization.
1253         * <P>Type: TEXT</P>
1254         */
1255        public static final String TITLE = "title";
1256
1257        /**
1258         * The person this organization is tied to.
1259         * <P>Type: TEXT</P>
1260         */
1261        public static final String PERSON_ID = "person";
1262
1263        /**
1264         * Whether this is the primary organization
1265         * <P>Type: INTEGER (if set, non-0 means true)</P>
1266         */
1267        public static final String ISPRIMARY = "isprimary";
1268    }
1269
1270    /**
1271     * A sub directory of a single person that contains all of their Phones.
1272     */
1273    public static final class Organizations implements BaseColumns, OrganizationColumns {
1274        /**
1275         * no public constructor since this is a utility class
1276         */
1277        private Organizations() {}
1278
1279        public static final CharSequence getDisplayLabel(Context context, int type,
1280                CharSequence label) {
1281            CharSequence display = "";
1282
1283            if (type != TYPE_CUSTOM) {
1284                CharSequence[] labels = context.getResources().getTextArray(
1285                        com.android.internal.R.array.organizationTypes);
1286                try {
1287                    display = labels[type - 1];
1288                } catch (ArrayIndexOutOfBoundsException e) {
1289                    display = labels[Organizations.TYPE_WORK - 1];
1290                }
1291            } else {
1292                if (!TextUtils.isEmpty(label)) {
1293                    display = label;
1294                }
1295            }
1296            return display;
1297        }
1298
1299        /**
1300         * The content:// style URL for this table
1301         */
1302        public static final Uri CONTENT_URI =
1303            Uri.parse("content://contacts/organizations");
1304
1305        /**
1306         * The directory twig for this sub-table
1307         */
1308        public static final String CONTENT_DIRECTORY = "organizations";
1309
1310        /**
1311         * The default sort order for this table
1312         */
1313        public static final String DEFAULT_SORT_ORDER = "company, title, isprimary ASC";
1314    }
1315
1316    /**
1317     * Columns from the Photos table that other columns join into themselves.
1318     */
1319    public interface PhotosColumns {
1320        /**
1321         * The _SYNC_VERSION of the photo that was last downloaded
1322         * <P>Type: TEXT</P>
1323         */
1324        public static final String LOCAL_VERSION = "local_version";
1325
1326        /**
1327         * The person this photo is associated with.
1328         * <P>Type: TEXT</P>
1329         */
1330        public static final String PERSON_ID = "person";
1331
1332        /**
1333         * non-zero if a download is required and the photo isn't marked as a bad resource.
1334         * You must specify this in the columns in order to use it in the where clause.
1335         * <P>Type: INTEGER(boolean)</P>
1336         */
1337        public static final String DOWNLOAD_REQUIRED = "download_required";
1338
1339        /**
1340         * non-zero if this photo is known to exist on the server
1341         * <P>Type: INTEGER(boolean)</P>
1342         */
1343        public static final String EXISTS_ON_SERVER = "exists_on_server";
1344
1345        /**
1346         * Contains the description of the upload or download error from
1347         * the previous attempt. If null then the previous attempt succeeded.
1348         * <P>Type: TEXT</P>
1349         */
1350        public static final String SYNC_ERROR = "sync_error";
1351
1352        /**
1353         * The image data, or null if there is no image.
1354         * <P>Type: BLOB</P>
1355         */
1356        public static final String DATA = "data";
1357
1358    }
1359
1360    /**
1361     * The photos over all of the people
1362     */
1363    public static final class Photos implements BaseColumns, PhotosColumns, SyncConstValue {
1364        /**
1365         * no public constructor since this is a utility class
1366         */
1367        private Photos() {}
1368
1369        /**
1370         * The content:// style URL for this table
1371         */
1372        public static final Uri CONTENT_URI =
1373            Uri.parse("content://contacts/photos");
1374
1375        /**
1376         * The directory twig for this sub-table
1377         */
1378        public static final String CONTENT_DIRECTORY = "photo";
1379
1380        /**
1381         * The default sort order for this table
1382         */
1383        public static final String DEFAULT_SORT_ORDER = "person ASC";
1384    }
1385
1386    public interface ExtensionsColumns {
1387        /**
1388         * The name of this extension. May not be null. There may be at most one row for each name.
1389         * <P>Type: TEXT</P>
1390         */
1391        public static final String NAME = "name";
1392
1393        /**
1394         * The value of this extension. May not be null.
1395         * <P>Type: TEXT</P>
1396         */
1397        public static final String VALUE = "value";
1398    }
1399
1400    /**
1401     * The extensions for a person
1402     */
1403    public static final class Extensions implements BaseColumns, ExtensionsColumns {
1404        /**
1405         * no public constructor since this is a utility class
1406         */
1407        private Extensions() {}
1408
1409        /**
1410         * The content:// style URL for this table
1411         */
1412        public static final Uri CONTENT_URI =
1413            Uri.parse("content://contacts/extensions");
1414
1415        /**
1416         * The MIME type of {@link #CONTENT_URI} providing a directory of
1417         * phones.
1418         */
1419        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_extensions";
1420
1421        /**
1422         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
1423         * phone.
1424         */
1425        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_extensions";
1426        /**
1427         * The default sort order for this table
1428         */
1429        public static final String DEFAULT_SORT_ORDER = "person, name ASC";
1430
1431        /**
1432         * The ID of the person this phone number is assigned to.
1433         * <P>Type: INTEGER (long)</P>
1434         */
1435        public static final String PERSON_ID = "person";
1436    }
1437
1438    /**
1439     * Contains helper classes used to create or manage {@link android.content.Intent Intents}
1440     * that involve contacts.
1441     */
1442    public static final class Intents {
1443        /**
1444         * This is the intent that is fired when a search suggestion is clicked on.
1445         */
1446        public static final String SEARCH_SUGGESTION_CLICKED =
1447                "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
1448
1449        /**
1450         * This is the intent that is fired when a search suggestion for dialing a number
1451         * is clicked on.
1452         */
1453        public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED =
1454                "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
1455
1456        /**
1457         * This is the intent that is fired when a search suggestion for creating a contact
1458         * is clicked on.
1459         */
1460        public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED =
1461                "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
1462
1463        /**
1464         * Starts an Activity that lets the user pick a contact to attach an image to.
1465         * After picking the contact it launches the image cropper in face detection mode.
1466         */
1467        public static final String ATTACH_IMAGE =
1468                "com.android.contacts.action.ATTACH_IMAGE";
1469
1470        /**
1471         * Takes as input a data URI with a mailto: or tel: scheme. If a single
1472         * contact exists with the given data it will be shown. If no contact
1473         * exists, a dialog will ask the user if they want to create a new
1474         * contact with the provided details filled in. If multiple contacts
1475         * share the data the user will be prompted to pick which contact they
1476         * want to view.
1477         * <p>
1478         * For <code>mailto:</code> URIs, the scheme specific portion must be a
1479         * raw email address, such as one built using
1480         * {@link Uri#fromParts(String, String, String)}.
1481         * <p>
1482         * For <code>tel:</code> URIs, the scheme specific portion is compared
1483         * to existing numbers using the standard caller ID lookup algorithm.
1484         * The number must be properly encoded, for example using
1485         * {@link Uri#fromParts(String, String, String)}.
1486         * <p>
1487         * Any extras from the {@link Insert} class will be passed along to the
1488         * create activity if there are no contacts to show.
1489         * <p>
1490         * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip
1491         * prompting the user when the contact doesn't exist.
1492         */
1493        public static final String SHOW_OR_CREATE_CONTACT =
1494                "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";
1495
1496        /**
1497         * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new
1498         * contact if no matching contact found. Otherwise, default behavior is
1499         * to prompt user with dialog before creating.
1500         * <p>
1501         * Type: BOOLEAN
1502         */
1503        public static final String EXTRA_FORCE_CREATE =
1504                "com.android.contacts.action.FORCE_CREATE";
1505
1506        /**
1507         * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact
1508         * description to be shown when prompting user about creating a new
1509         * contact.
1510         * <p>
1511         * Type: STRING
1512         */
1513        public static final String EXTRA_CREATE_DESCRIPTION =
1514            "com.android.contacts.action.CREATE_DESCRIPTION";
1515
1516        /**
1517         * Intents related to the Contacts app UI.
1518         */
1519        public static final class UI {
1520            /**
1521             * The action for the default contacts list tab.
1522             */
1523            public static final String LIST_DEFAULT =
1524                    "com.android.contacts.action.LIST_DEFAULT";
1525
1526            /**
1527             * The action for the contacts list tab.
1528             */
1529            public static final String LIST_GROUP_ACTION =
1530                    "com.android.contacts.action.LIST_GROUP";
1531
1532            /**
1533             * When in LIST_GROUP_ACTION mode, this is the group to display.
1534             */
1535            public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
1536
1537            /**
1538             * The action for the all contacts list tab.
1539             */
1540            public static final String LIST_ALL_CONTACTS_ACTION =
1541                    "com.android.contacts.action.LIST_ALL_CONTACTS";
1542
1543            /**
1544             * The action for the contacts with phone numbers list tab.
1545             */
1546            public static final String LIST_CONTACTS_WITH_PHONES_ACTION =
1547                    "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";
1548
1549            /**
1550             * The action for the starred contacts list tab.
1551             */
1552            public static final String LIST_STARRED_ACTION =
1553                    "com.android.contacts.action.LIST_STARRED";
1554
1555            /**
1556             * The action for the frequent contacts list tab.
1557             */
1558            public static final String LIST_FREQUENT_ACTION =
1559                    "com.android.contacts.action.LIST_FREQUENT";
1560
1561            /**
1562             * The action for the "strequent" contacts list tab. It first lists the starred
1563             * contacts in alphabetical order and then the frequent contacts in descending
1564             * order of the number of times they have been contacted.
1565             */
1566            public static final String LIST_STREQUENT_ACTION =
1567                    "com.android.contacts.action.LIST_STREQUENT";
1568
1569            /**
1570             * A key for to be used as an intent extra to set the activity
1571             * title to a custom String value.
1572             */
1573            public static final String TITLE_EXTRA_KEY =
1574                "com.android.contacts.extra.TITLE_EXTRA";
1575
1576            /**
1577             * Activity Action: Display a filtered list of contacts
1578             * <p>
1579             * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for
1580             * filtering
1581             * <p>
1582             * Output: Nothing.
1583             */
1584            public static final String FILTER_CONTACTS_ACTION =
1585                "com.android.contacts.action.FILTER_CONTACTS";
1586
1587            /**
1588             * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION}
1589             * intents to supply the text on which to filter.
1590             */
1591            public static final String FILTER_TEXT_EXTRA_KEY =
1592                "com.android.contacts.extra.FILTER_TEXT";
1593        }
1594
1595        /**
1596         * Convenience class that contains string constants used
1597         * to create contact {@link android.content.Intent Intents}.
1598         */
1599        public static final class Insert {
1600            /** The action code to use when adding a contact */
1601            public static final String ACTION = Intent.ACTION_INSERT;
1602
1603            /**
1604             * If present, forces a bypass of quick insert mode.
1605             */
1606            public static final String FULL_MODE = "full_mode";
1607
1608            /**
1609             * The extra field for the contact name.
1610             * <P>Type: String</P>
1611             */
1612            public static final String NAME = "name";
1613
1614            /**
1615             * The extra field for the contact phonetic name.
1616             * <P>Type: String</P>
1617             */
1618            public static final String PHONETIC_NAME = "phonetic_name";
1619
1620            /**
1621             * The extra field for the contact company.
1622             * <P>Type: String</P>
1623             */
1624            public static final String COMPANY = "company";
1625
1626            /**
1627             * The extra field for the contact job title.
1628             * <P>Type: String</P>
1629             */
1630            public static final String JOB_TITLE = "job_title";
1631
1632            /**
1633             * The extra field for the contact notes.
1634             * <P>Type: String</P>
1635             */
1636            public static final String NOTES = "notes";
1637
1638            /**
1639             * The extra field for the contact phone number.
1640             * <P>Type: String</P>
1641             */
1642            public static final String PHONE = "phone";
1643
1644            /**
1645             * The extra field for the contact phone number type.
1646             * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},
1647             *  or a string specifying a custom label.</P>
1648             */
1649            public static final String PHONE_TYPE = "phone_type";
1650
1651            /**
1652             * The extra field for the phone isprimary flag.
1653             * <P>Type: boolean</P>
1654             */
1655            public static final String PHONE_ISPRIMARY = "phone_isprimary";
1656
1657            /**
1658             * The extra field for an optional second contact phone number.
1659             * <P>Type: String</P>
1660             */
1661            public static final String SECONDARY_PHONE = "secondary_phone";
1662
1663            /**
1664             * The extra field for an optional second contact phone number type.
1665             * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},
1666             *  or a string specifying a custom label.</P>
1667             */
1668            public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";
1669
1670            /**
1671             * The extra field for an optional third contact phone number.
1672             * <P>Type: String</P>
1673             */
1674            public static final String TERTIARY_PHONE = "tertiary_phone";
1675
1676            /**
1677             * The extra field for an optional third contact phone number type.
1678             * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},
1679             *  or a string specifying a custom label.</P>
1680             */
1681            public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
1682
1683            /**
1684             * The extra field for the contact email address.
1685             * <P>Type: String</P>
1686             */
1687            public static final String EMAIL = "email";
1688
1689            /**
1690             * The extra field for the contact email type.
1691             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
1692             *  or a string specifying a custom label.</P>
1693             */
1694            public static final String EMAIL_TYPE = "email_type";
1695
1696            /**
1697             * The extra field for the email isprimary flag.
1698             * <P>Type: boolean</P>
1699             */
1700            public static final String EMAIL_ISPRIMARY = "email_isprimary";
1701
1702            /**
1703             * The extra field for an optional second contact email address.
1704             * <P>Type: String</P>
1705             */
1706            public static final String SECONDARY_EMAIL = "secondary_email";
1707
1708            /**
1709             * The extra field for an optional second contact email type.
1710             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
1711             *  or a string specifying a custom label.</P>
1712             */
1713            public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";
1714
1715            /**
1716             * The extra field for an optional third contact email address.
1717             * <P>Type: String</P>
1718             */
1719            public static final String TERTIARY_EMAIL = "tertiary_email";
1720
1721            /**
1722             * The extra field for an optional third contact email type.
1723             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
1724             *  or a string specifying a custom label.</P>
1725             */
1726            public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
1727
1728            /**
1729             * The extra field for the contact postal address.
1730             * <P>Type: String</P>
1731             */
1732            public static final String POSTAL = "postal";
1733
1734            /**
1735             * The extra field for the contact postal address type.
1736             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
1737             *  or a string specifying a custom label.</P>
1738             */
1739            public static final String POSTAL_TYPE = "postal_type";
1740
1741            /**
1742             * The extra field for the postal isprimary flag.
1743             * <P>Type: boolean</P>
1744             */
1745            public static final String POSTAL_ISPRIMARY = "postal_isprimary";
1746
1747            /**
1748             * The extra field for an IM handle.
1749             * <P>Type: String</P>
1750             */
1751            public static final String IM_HANDLE = "im_handle";
1752
1753            /**
1754             * The extra field for the IM protocol
1755             * <P>Type: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol}
1756             * or {@link Contacts.ContactMethods#encodeCustomImProtocol}.</P>
1757             */
1758            public static final String IM_PROTOCOL = "im_protocol";
1759
1760            /**
1761             * The extra field for the IM isprimary flag.
1762             * <P>Type: boolean</P>
1763             */
1764            public static final String IM_ISPRIMARY = "im_isprimary";
1765        }
1766    }
1767}
1768