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