blob: 2a3c22d2f72211707748b60ac2addbfa97f0b038 [file] [log] [blame]
Evan Millar45e0ed32009-06-01 16:44:38 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Evan Millar66388be2009-05-28 15:41:07 -070017package com.android.contacts;
18
19
Evan Millar45e0ed32009-06-01 16:44:38 -070020import android.content.ContentResolver;
Evan Millar2c1cc832009-07-13 11:08:06 -070021import android.content.ContentUris;
Evan Millar45e0ed32009-06-01 16:44:38 -070022import android.content.Context;
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -070023import android.content.Intent;
Evan Millar45e0ed32009-06-01 16:44:38 -070024import android.database.Cursor;
25import android.graphics.Bitmap;
26import android.graphics.BitmapFactory;
Evan Millarf19104c2009-09-02 17:53:25 -070027import android.graphics.drawable.Drawable;
Neel Parekh2ad90a32009-09-20 19:08:50 -070028import android.net.Uri;
29import android.provider.ContactsContract.Contacts;
30import android.provider.ContactsContract.Data;
31import android.provider.ContactsContract.RawContacts;
Evan Millar66388be2009-05-28 15:41:07 -070032import android.provider.ContactsContract.CommonDataKinds.Email;
33import android.provider.ContactsContract.CommonDataKinds.Im;
34import android.provider.ContactsContract.CommonDataKinds.Organization;
35import android.provider.ContactsContract.CommonDataKinds.Phone;
Evan Millar2c1cc832009-07-13 11:08:06 -070036import android.provider.ContactsContract.CommonDataKinds.Photo;
Jeff Sharkeyc6ad3ab2009-07-21 19:30:15 -070037import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
Evan Millar66388be2009-05-28 15:41:07 -070038import android.provider.Im.ProviderNames;
Evan Millar66388be2009-05-28 15:41:07 -070039import android.text.TextUtils;
Evan Millar11d628c2009-09-02 08:55:01 -070040import android.view.LayoutInflater;
41import android.view.View;
42import android.view.ViewGroup;
43import android.widget.ImageView;
44import android.widget.TextView;
Evan Millar66388be2009-05-28 15:41:07 -070045
Neel Parekh2ad90a32009-09-20 19:08:50 -070046import com.android.contacts.model.ContactsSource;
47import com.android.contacts.util.Constants;
48
49import java.util.ArrayList;
50
Evan Millar66388be2009-05-28 15:41:07 -070051public class ContactsUtils {
Evan Millar45e0ed32009-06-01 16:44:38 -070052
Evan Millar11d628c2009-09-02 08:55:01 -070053 private static final String TAG = "ContactsUtils";
Jeff Sharkey39261272009-06-03 19:15:09 -070054 /**
55 * Build the display title for the {@link Data#CONTENT_URI} entry in the
56 * provided cursor, assuming the given mimeType.
57 */
58 public static final CharSequence getDisplayLabel(Context context,
59 String mimeType, Cursor cursor) {
60 // Try finding the type and label for this mimetype
61 int colType;
62 int colLabel;
63
Jeff Sharkey39261272009-06-03 19:15:09 -070064 if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)
Jeff Sharkey49d17b32009-09-07 02:14:21 -070065 || Constants.MIME_SMS_ADDRESS.equals(mimeType)) {
Jeff Sharkey39261272009-06-03 19:15:09 -070066 // Reset to phone mimetype so we generate a label for SMS case
67 mimeType = Phone.CONTENT_ITEM_TYPE;
68 colType = cursor.getColumnIndex(Phone.TYPE);
69 colLabel = cursor.getColumnIndex(Phone.LABEL);
70 } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
71 colType = cursor.getColumnIndex(Email.TYPE);
72 colLabel = cursor.getColumnIndex(Email.LABEL);
Jeff Sharkeyc6ad3ab2009-07-21 19:30:15 -070073 } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
74 colType = cursor.getColumnIndex(StructuredPostal.TYPE);
75 colLabel = cursor.getColumnIndex(StructuredPostal.LABEL);
Jeff Sharkey39261272009-06-03 19:15:09 -070076 } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
77 colType = cursor.getColumnIndex(Organization.TYPE);
78 colLabel = cursor.getColumnIndex(Organization.LABEL);
79 } else {
80 return null;
81 }
82
83 final int type = cursor.getInt(colType);
84 final CharSequence label = cursor.getString(colLabel);
85
86 return getDisplayLabel(context, mimeType, type, label);
87 }
88
Evan Millar66388be2009-05-28 15:41:07 -070089 public static final CharSequence getDisplayLabel(Context context, String mimetype, int type,
90 CharSequence label) {
91 CharSequence display = "";
92 final int customType;
93 final int defaultType;
94 final int arrayResId;
95
96 if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
97 defaultType = Phone.TYPE_HOME;
98 customType = Phone.TYPE_CUSTOM;
99 arrayResId = com.android.internal.R.array.phoneTypes;
100 } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) {
101 defaultType = Email.TYPE_HOME;
102 customType = Email.TYPE_CUSTOM;
103 arrayResId = com.android.internal.R.array.emailAddressTypes;
Jeff Sharkeyc6ad3ab2009-07-21 19:30:15 -0700104 } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimetype)) {
105 defaultType = StructuredPostal.TYPE_HOME;
106 customType = StructuredPostal.TYPE_CUSTOM;
Evan Millar66388be2009-05-28 15:41:07 -0700107 arrayResId = com.android.internal.R.array.postalAddressTypes;
108 } else if (Organization.CONTENT_ITEM_TYPE.equals(mimetype)) {
Dmitri Plotnikov48cf72b2009-07-17 11:00:26 -0700109 defaultType = Organization.TYPE_WORK;
Evan Millar66388be2009-05-28 15:41:07 -0700110 customType = Organization.TYPE_CUSTOM;
111 arrayResId = com.android.internal.R.array.organizationTypes;
112 } else {
113 // Can't return display label for given mimetype.
114 return display;
115 }
Evan Millar45e0ed32009-06-01 16:44:38 -0700116
Evan Millar66388be2009-05-28 15:41:07 -0700117 if (type != customType) {
118 CharSequence[] labels = context.getResources().getTextArray(arrayResId);
119 try {
120 display = labels[type - 1];
121 } catch (ArrayIndexOutOfBoundsException e) {
122 display = labels[defaultType - 1];
123 }
124 } else {
125 if (!TextUtils.isEmpty(label)) {
126 display = label;
127 }
128 }
129 return display;
130 }
Evan Millar45e0ed32009-06-01 16:44:38 -0700131
Evan Millar45e0ed32009-06-01 16:44:38 -0700132 /**
133 * Opens an InputStream for the person's photo and returns the photo as a Bitmap.
134 * If the person's photo isn't present returns null.
135 *
136 * @param aggCursor the Cursor pointing to the data record containing the photo.
137 * @param bitmapColumnIndex the column index where the photo Uri is stored.
138 * @param options the decoding options, can be set to null
139 * @return the photo Bitmap
140 */
Evan Millar0a40ffa2009-06-18 16:49:08 -0700141 public static Bitmap loadContactPhoto(Cursor cursor, int bitmapColumnIndex,
Evan Millar45e0ed32009-06-01 16:44:38 -0700142 BitmapFactory.Options options) {
Evan Millar0a40ffa2009-06-18 16:49:08 -0700143 if (cursor == null) {
Evan Millar45e0ed32009-06-01 16:44:38 -0700144 return null;
145 }
146
Evan Millar7911ff52009-07-21 15:55:18 -0700147 byte[] data = cursor.getBlob(bitmapColumnIndex);
Evan Millar45e0ed32009-06-01 16:44:38 -0700148 return BitmapFactory.decodeByteArray(data, 0, data.length, options);
149 }
150
151 /**
152 * Loads a placeholder photo.
153 *
154 * @param placeholderImageResource the resource to use for the placeholder image
155 * @param context the Context
156 * @param options the decoding options, can be set to null
157 * @return the placeholder Bitmap.
158 */
159 public static Bitmap loadPlaceholderPhoto(int placeholderImageResource, Context context,
160 BitmapFactory.Options options) {
161 if (placeholderImageResource == 0) {
162 return null;
163 }
164 return BitmapFactory.decodeResource(context.getResources(),
165 placeholderImageResource, options);
166 }
167
Evan Millar7911ff52009-07-21 15:55:18 -0700168 public static Bitmap loadContactPhoto(Context context, long photoId,
Evan Millar2c1cc832009-07-13 11:08:06 -0700169 BitmapFactory.Options options) {
170 Cursor photoCursor = null;
171 Bitmap photoBm = null;
172
173 try {
174 photoCursor = context.getContentResolver().query(
175 ContentUris.withAppendedId(Data.CONTENT_URI, photoId),
176 new String[] { Photo.PHOTO },
177 null, null, null);
178
179 if (photoCursor.moveToFirst() && !photoCursor.isNull(0)) {
180 byte[] photoData = photoCursor.getBlob(0);
181 photoBm = BitmapFactory.decodeByteArray(photoData, 0,
182 photoData.length, options);
183 }
184 } finally {
185 if (photoCursor != null) {
186 photoCursor.close();
187 }
188 }
189
190 return photoBm;
191 }
192
Evan Millar66388be2009-05-28 15:41:07 -0700193 /**
194 * This looks up the provider name defined in
195 * {@link android.provider.Im.ProviderNames} from the predefined IM protocol id.
196 * This is used for interacting with the IM application.
197 *
198 * @param protocol the protocol ID
199 * @return the provider name the IM app uses for the given protocol, or null if no
200 * provider is defined for the given protocol
201 * @hide
202 */
203 public static String lookupProviderNameFromId(int protocol) {
204 switch (protocol) {
205 case Im.PROTOCOL_GOOGLE_TALK:
206 return ProviderNames.GTALK;
207 case Im.PROTOCOL_AIM:
208 return ProviderNames.AIM;
209 case Im.PROTOCOL_MSN:
210 return ProviderNames.MSN;
211 case Im.PROTOCOL_YAHOO:
212 return ProviderNames.YAHOO;
213 case Im.PROTOCOL_ICQ:
214 return ProviderNames.ICQ;
215 case Im.PROTOCOL_JABBER:
216 return ProviderNames.JABBER;
217 case Im.PROTOCOL_SKYPE:
218 return ProviderNames.SKYPE;
219 case Im.PROTOCOL_QQ:
220 return ProviderNames.QQ;
221 }
222 return null;
223 }
224
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -0700225 public static Intent getPhotoPickIntent() {
226 Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
227 intent.setType("image/*");
228 intent.putExtra("crop", "true");
229 intent.putExtra("aspectX", 1);
230 intent.putExtra("aspectY", 1);
231 intent.putExtra("outputX", 96);
232 intent.putExtra("outputY", 96);
233 intent.putExtra("return-data", true);
234 return intent;
235 }
Evan Millar8a79cee2009-08-19 17:20:49 -0700236
237 public static long queryForContactId(ContentResolver cr, long rawContactId) {
238 Cursor contactIdCursor = null;
239 long contactId = -1;
240 try {
241 contactIdCursor = cr.query(RawContacts.CONTENT_URI,
242 new String[] {RawContacts.CONTACT_ID},
243 RawContacts._ID + "=" + rawContactId, null, null);
244 if (contactIdCursor != null && contactIdCursor.moveToFirst()) {
245 contactId = contactIdCursor.getLong(0);
246 }
247 } finally {
248 if (contactIdCursor != null) {
249 contactIdCursor.close();
250 }
251 }
252 return contactId;
253 }
Evan Millar11d628c2009-09-02 08:55:01 -0700254
Evan Millar2cd51002009-09-02 14:33:38 -0700255 public static String querySuperPrimaryPhone(ContentResolver cr, long contactId) {
256 Cursor c = null;
257 String phone = null;
258 try {
259 Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Jeff Sharkey49d17b32009-09-07 02:14:21 -0700260 Uri dataUri = Uri.withAppendedPath(baseUri, Contacts.Data.CONTENT_DIRECTORY);
Evan Millar2cd51002009-09-02 14:33:38 -0700261
262 c = cr.query(dataUri,
263 new String[] {Phone.NUMBER},
264 Data.MIMETYPE + "=" + Phone.MIMETYPE +
265 " AND " + Data.IS_SUPER_PRIMARY + "=1",
266 null, null);
267 if (c != null && c.moveToFirst()) {
268 // Just return the first one.
269 phone = c.getString(0);
270 }
271 } finally {
272 if (c != null) {
273 c.close();
274 }
275 }
276 return phone;
277 }
278
279 public static long queryForRawContactId(ContentResolver cr, long contactId) {
280 Cursor rawContactIdCursor = null;
281 long rawContactId = -1;
282 try {
283 rawContactIdCursor = cr.query(RawContacts.CONTENT_URI,
284 new String[] {RawContacts._ID},
285 RawContacts.CONTACT_ID + "=" + contactId, null, null);
286 if (rawContactIdCursor != null && rawContactIdCursor.moveToFirst()) {
287 // Just return the first one.
288 rawContactId = rawContactIdCursor.getLong(0);
289 }
290 } finally {
291 if (rawContactIdCursor != null) {
292 rawContactIdCursor.close();
293 }
294 }
295 return rawContactId;
296 }
297
Neel Parekh2ad90a32009-09-20 19:08:50 -0700298 public static ArrayList<Long> queryForAllRawContactIds(ContentResolver cr, long contactId) {
299 Cursor rawContactIdCursor = null;
300 ArrayList<Long> rawContactIds = new ArrayList<Long>();
301 try {
302 rawContactIdCursor = cr.query(RawContacts.CONTENT_URI,
303 new String[] {RawContacts._ID},
304 RawContacts.CONTACT_ID + "=" + contactId, null, null);
305 if (rawContactIdCursor != null) {
306 while (rawContactIdCursor.moveToNext()) {
307 rawContactIds.add(rawContactIdCursor.getLong(0));
308 }
309 }
310 } finally {
311 if (rawContactIdCursor != null) {
312 rawContactIdCursor.close();
313 }
314 }
315 return rawContactIds;
316 }
317
Evan Millar11d628c2009-09-02 08:55:01 -0700318
319 /**
320 * Utility for creating a standard tab indicator view.
321 *
322 * @param parent The parent ViewGroup to attach the new view to.
323 * @param label The label to display in the tab indicator. If null, not label will be displayed.
324 * @param icon The icon to display. If null, no icon will be displayed.
325 * @return The tab indicator View.
326 */
327 public static View createTabIndicatorView(ViewGroup parent, CharSequence label, Drawable icon) {
328 final LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(
329 Context.LAYOUT_INFLATER_SERVICE);
330 final View tabIndicator = inflater.inflate(R.layout.tab_indicator, parent, false);
331 tabIndicator.getBackground().setDither(true);
332
333 final TextView tv = (TextView) tabIndicator.findViewById(R.id.tab_title);
334 tv.setText(label);
335
336 final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.tab_icon);
337 iconView.setImageDrawable(icon);
338
339 return tabIndicator;
340 }
341
342 /**
343 * Utility for creating a standard tab indicator view.
344 *
345 * @param context The label to display in the tab indicator. If null, not label will be displayed.
346 * @param parent The parent ViewGroup to attach the new view to.
347 * @param source The {@link ContactsSource} to build the tab view from.
348 * @return The tab indicator View.
349 */
350 public static View createTabIndicatorView(ViewGroup parent, ContactsSource source) {
351 Drawable icon = null;
352 if (source != null) {
Jeff Sharkeyab066932009-09-21 09:55:30 -0700353 icon = source.getDisplayIcon(parent.getContext());
Evan Millar11d628c2009-09-02 08:55:01 -0700354 }
355 return createTabIndicatorView(parent, null, icon);
356 }
Evan Millar14fecb62009-09-09 09:23:12 -0700357
358 /**
359 * Kick off an intent to initiate a call.
360 */
361 public static void initiateCall(Context context, CharSequence phoneNumber) {
362 Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
363 Uri.fromParts("tel", phoneNumber.toString(), null));
364 context.startActivity(intent);
365 }
366
367 /**
368 * Kick off an intent to initiate an Sms/Mms message.
369 */
370 public static void initiateSms(Context context, CharSequence phoneNumber) {
371 Intent intent = new Intent(Intent.ACTION_SENDTO,
372 Uri.fromParts("sms", phoneNumber.toString(), null));
373 context.startActivity(intent);
374 }
Evan Millar66388be2009-05-28 15:41:07 -0700375}