blob: 7611026c5ab27a3f3616a193e94c89f0884ae008 [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 Millar11d628c2009-09-02 08:55:01 -070020import com.android.contacts.model.ContactsSource;
Jeff Sharkey802b2052009-08-04 14:21:06 -070021import com.android.contacts.ui.FastTrackWindow;
22
Evan Millar45e0ed32009-06-01 16:44:38 -070023import java.io.ByteArrayInputStream;
Jeff Sharkey39261272009-06-03 19:15:09 -070024import android.provider.ContactsContract.Data;
Evan Millar8a79cee2009-08-19 17:20:49 -070025import android.provider.ContactsContract.RawContacts;
26
Evan Millar45e0ed32009-06-01 16:44:38 -070027import java.io.InputStream;
28
29import android.net.Uri;
30import android.content.ContentResolver;
Evan Millar2c1cc832009-07-13 11:08:06 -070031import android.content.ContentUris;
Evan Millar7e4accf2009-06-08 10:43:26 -070032import android.content.ContentValues;
Evan Millar45e0ed32009-06-01 16:44:38 -070033import android.content.Context;
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -070034import android.content.Intent;
Evan Millar11d628c2009-09-02 08:55:01 -070035import android.content.pm.PackageManager;
Evan Millar45e0ed32009-06-01 16:44:38 -070036import android.database.Cursor;
37import android.graphics.Bitmap;
38import android.graphics.BitmapFactory;
Evan Millar11d628c2009-09-02 08:55:01 -070039import android.graphics.drawable.Drawable;
Evan Millar45e0ed32009-06-01 16:44:38 -070040import android.provider.Contacts;
41import android.provider.Contacts.Photos;
Evan Millar66388be2009-05-28 15:41:07 -070042import android.provider.ContactsContract.CommonDataKinds.Email;
43import android.provider.ContactsContract.CommonDataKinds.Im;
44import android.provider.ContactsContract.CommonDataKinds.Organization;
45import android.provider.ContactsContract.CommonDataKinds.Phone;
Evan Millar2c1cc832009-07-13 11:08:06 -070046import android.provider.ContactsContract.CommonDataKinds.Photo;
Jeff Sharkeyc6ad3ab2009-07-21 19:30:15 -070047import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
Evan Millar66388be2009-05-28 15:41:07 -070048import android.provider.Im.ProviderNames;
Jeff Sharkey39261272009-06-03 19:15:09 -070049import android.database.Cursor;
Evan Millar66388be2009-05-28 15:41:07 -070050import android.text.TextUtils;
Jeff Sharkey39261272009-06-03 19:15:09 -070051import android.util.Log;
Evan Millar11d628c2009-09-02 08:55:01 -070052import android.view.LayoutInflater;
53import android.view.View;
54import android.view.ViewGroup;
55import android.widget.ImageView;
56import android.widget.TextView;
Evan Millar66388be2009-05-28 15:41:07 -070057
58public class ContactsUtils {
Evan Millar45e0ed32009-06-01 16:44:38 -070059
Evan Millar11d628c2009-09-02 08:55:01 -070060 private static final String TAG = "ContactsUtils";
Jeff Sharkey39261272009-06-03 19:15:09 -070061 /**
62 * Build the display title for the {@link Data#CONTENT_URI} entry in the
63 * provided cursor, assuming the given mimeType.
64 */
65 public static final CharSequence getDisplayLabel(Context context,
66 String mimeType, Cursor cursor) {
67 // Try finding the type and label for this mimetype
68 int colType;
69 int colLabel;
70
71 // TODO: move the SMS mime-type to a central location
72 if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)
73 || FastTrackWindow.MIME_SMS_ADDRESS.equals(mimeType)) {
74 // Reset to phone mimetype so we generate a label for SMS case
75 mimeType = Phone.CONTENT_ITEM_TYPE;
76 colType = cursor.getColumnIndex(Phone.TYPE);
77 colLabel = cursor.getColumnIndex(Phone.LABEL);
78 } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
79 colType = cursor.getColumnIndex(Email.TYPE);
80 colLabel = cursor.getColumnIndex(Email.LABEL);
Jeff Sharkeyc6ad3ab2009-07-21 19:30:15 -070081 } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
82 colType = cursor.getColumnIndex(StructuredPostal.TYPE);
83 colLabel = cursor.getColumnIndex(StructuredPostal.LABEL);
Jeff Sharkey39261272009-06-03 19:15:09 -070084 } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
85 colType = cursor.getColumnIndex(Organization.TYPE);
86 colLabel = cursor.getColumnIndex(Organization.LABEL);
87 } else {
88 return null;
89 }
90
91 final int type = cursor.getInt(colType);
92 final CharSequence label = cursor.getString(colLabel);
93
94 return getDisplayLabel(context, mimeType, type, label);
95 }
96
Evan Millar66388be2009-05-28 15:41:07 -070097 public static final CharSequence getDisplayLabel(Context context, String mimetype, int type,
98 CharSequence label) {
99 CharSequence display = "";
100 final int customType;
101 final int defaultType;
102 final int arrayResId;
103
104 if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
105 defaultType = Phone.TYPE_HOME;
106 customType = Phone.TYPE_CUSTOM;
107 arrayResId = com.android.internal.R.array.phoneTypes;
108 } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) {
109 defaultType = Email.TYPE_HOME;
110 customType = Email.TYPE_CUSTOM;
111 arrayResId = com.android.internal.R.array.emailAddressTypes;
Jeff Sharkeyc6ad3ab2009-07-21 19:30:15 -0700112 } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimetype)) {
113 defaultType = StructuredPostal.TYPE_HOME;
114 customType = StructuredPostal.TYPE_CUSTOM;
Evan Millar66388be2009-05-28 15:41:07 -0700115 arrayResId = com.android.internal.R.array.postalAddressTypes;
116 } else if (Organization.CONTENT_ITEM_TYPE.equals(mimetype)) {
Dmitri Plotnikov48cf72b2009-07-17 11:00:26 -0700117 defaultType = Organization.TYPE_WORK;
Evan Millar66388be2009-05-28 15:41:07 -0700118 customType = Organization.TYPE_CUSTOM;
119 arrayResId = com.android.internal.R.array.organizationTypes;
120 } else {
121 // Can't return display label for given mimetype.
122 return display;
123 }
Evan Millar45e0ed32009-06-01 16:44:38 -0700124
Evan Millar66388be2009-05-28 15:41:07 -0700125 if (type != customType) {
126 CharSequence[] labels = context.getResources().getTextArray(arrayResId);
127 try {
128 display = labels[type - 1];
129 } catch (ArrayIndexOutOfBoundsException e) {
130 display = labels[defaultType - 1];
131 }
132 } else {
133 if (!TextUtils.isEmpty(label)) {
134 display = label;
135 }
136 }
137 return display;
138 }
Evan Millar45e0ed32009-06-01 16:44:38 -0700139
Evan Millar45e0ed32009-06-01 16:44:38 -0700140 /**
141 * Opens an InputStream for the person's photo and returns the photo as a Bitmap.
142 * If the person's photo isn't present returns null.
143 *
144 * @param aggCursor the Cursor pointing to the data record containing the photo.
145 * @param bitmapColumnIndex the column index where the photo Uri is stored.
146 * @param options the decoding options, can be set to null
147 * @return the photo Bitmap
148 */
Evan Millar0a40ffa2009-06-18 16:49:08 -0700149 public static Bitmap loadContactPhoto(Cursor cursor, int bitmapColumnIndex,
Evan Millar45e0ed32009-06-01 16:44:38 -0700150 BitmapFactory.Options options) {
Evan Millar0a40ffa2009-06-18 16:49:08 -0700151 if (cursor == null) {
Evan Millar45e0ed32009-06-01 16:44:38 -0700152 return null;
153 }
154
Evan Millar7911ff52009-07-21 15:55:18 -0700155 byte[] data = cursor.getBlob(bitmapColumnIndex);
Evan Millar45e0ed32009-06-01 16:44:38 -0700156 return BitmapFactory.decodeByteArray(data, 0, data.length, options);
157 }
158
159 /**
160 * Loads a placeholder photo.
161 *
162 * @param placeholderImageResource the resource to use for the placeholder image
163 * @param context the Context
164 * @param options the decoding options, can be set to null
165 * @return the placeholder Bitmap.
166 */
167 public static Bitmap loadPlaceholderPhoto(int placeholderImageResource, Context context,
168 BitmapFactory.Options options) {
169 if (placeholderImageResource == 0) {
170 return null;
171 }
172 return BitmapFactory.decodeResource(context.getResources(),
173 placeholderImageResource, options);
174 }
175
Evan Millar7911ff52009-07-21 15:55:18 -0700176 public static Bitmap loadContactPhoto(Context context, long photoId,
Evan Millar2c1cc832009-07-13 11:08:06 -0700177 BitmapFactory.Options options) {
178 Cursor photoCursor = null;
179 Bitmap photoBm = null;
180
181 try {
182 photoCursor = context.getContentResolver().query(
183 ContentUris.withAppendedId(Data.CONTENT_URI, photoId),
184 new String[] { Photo.PHOTO },
185 null, null, null);
186
187 if (photoCursor.moveToFirst() && !photoCursor.isNull(0)) {
188 byte[] photoData = photoCursor.getBlob(0);
189 photoBm = BitmapFactory.decodeByteArray(photoData, 0,
190 photoData.length, options);
191 }
192 } finally {
193 if (photoCursor != null) {
194 photoCursor.close();
195 }
196 }
197
198 return photoBm;
199 }
200
Evan Millar66388be2009-05-28 15:41:07 -0700201 /**
202 * This looks up the provider name defined in
203 * {@link android.provider.Im.ProviderNames} from the predefined IM protocol id.
204 * This is used for interacting with the IM application.
205 *
206 * @param protocol the protocol ID
207 * @return the provider name the IM app uses for the given protocol, or null if no
208 * provider is defined for the given protocol
209 * @hide
210 */
211 public static String lookupProviderNameFromId(int protocol) {
212 switch (protocol) {
213 case Im.PROTOCOL_GOOGLE_TALK:
214 return ProviderNames.GTALK;
215 case Im.PROTOCOL_AIM:
216 return ProviderNames.AIM;
217 case Im.PROTOCOL_MSN:
218 return ProviderNames.MSN;
219 case Im.PROTOCOL_YAHOO:
220 return ProviderNames.YAHOO;
221 case Im.PROTOCOL_ICQ:
222 return ProviderNames.ICQ;
223 case Im.PROTOCOL_JABBER:
224 return ProviderNames.JABBER;
225 case Im.PROTOCOL_SKYPE:
226 return ProviderNames.SKYPE;
227 case Im.PROTOCOL_QQ:
228 return ProviderNames.QQ;
229 }
230 return null;
231 }
232
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -0700233 public static Intent getPhotoPickIntent() {
234 Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
235 intent.setType("image/*");
236 intent.putExtra("crop", "true");
237 intent.putExtra("aspectX", 1);
238 intent.putExtra("aspectY", 1);
239 intent.putExtra("outputX", 96);
240 intent.putExtra("outputY", 96);
241 intent.putExtra("return-data", true);
242 return intent;
243 }
Evan Millar8a79cee2009-08-19 17:20:49 -0700244
245 public static long queryForContactId(ContentResolver cr, long rawContactId) {
246 Cursor contactIdCursor = null;
247 long contactId = -1;
248 try {
249 contactIdCursor = cr.query(RawContacts.CONTENT_URI,
250 new String[] {RawContacts.CONTACT_ID},
251 RawContacts._ID + "=" + rawContactId, null, null);
252 if (contactIdCursor != null && contactIdCursor.moveToFirst()) {
253 contactId = contactIdCursor.getLong(0);
254 }
255 } finally {
256 if (contactIdCursor != null) {
257 contactIdCursor.close();
258 }
259 }
260 return contactId;
261 }
Evan Millar11d628c2009-09-02 08:55:01 -0700262
263
264 /**
265 * Utility for creating a standard tab indicator view.
266 *
267 * @param parent The parent ViewGroup to attach the new view to.
268 * @param label The label to display in the tab indicator. If null, not label will be displayed.
269 * @param icon The icon to display. If null, no icon will be displayed.
270 * @return The tab indicator View.
271 */
272 public static View createTabIndicatorView(ViewGroup parent, CharSequence label, Drawable icon) {
273 final LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(
274 Context.LAYOUT_INFLATER_SERVICE);
275 final View tabIndicator = inflater.inflate(R.layout.tab_indicator, parent, false);
276 tabIndicator.getBackground().setDither(true);
277
278 final TextView tv = (TextView) tabIndicator.findViewById(R.id.tab_title);
279 tv.setText(label);
280
281 final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.tab_icon);
282 iconView.setImageDrawable(icon);
283
284 return tabIndicator;
285 }
286
287 /**
288 * Utility for creating a standard tab indicator view.
289 *
290 * @param context The label to display in the tab indicator. If null, not label will be displayed.
291 * @param parent The parent ViewGroup to attach the new view to.
292 * @param source The {@link ContactsSource} to build the tab view from.
293 * @return The tab indicator View.
294 */
295 public static View createTabIndicatorView(ViewGroup parent, ContactsSource source) {
296 Drawable icon = null;
297 if (source != null) {
298 final String packageName = source.resPackageName;
299 if (source.iconRes > 0) {
300 try {
301 final Context authContext = parent.getContext().
302 createPackageContext(packageName, 0);
303 icon = authContext.getResources().getDrawable(source.iconRes);
304
305 } catch (PackageManager.NameNotFoundException e) {
306 Log.d(TAG, "error getting the Package Context for " + packageName, e);
307 }
308 }
309 }
310 return createTabIndicatorView(parent, null, icon);
311 }
Evan Millar66388be2009-05-28 15:41:07 -0700312}