18a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov/* 28a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project 38a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * 48a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 58a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * you may not use this file except in compliance with the License. 68a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * You may obtain a copy of the License at 78a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * 88a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 98a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * 108a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 118a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 128a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * See the License for the specific language governing permissions and 148a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * limitations under the License. 158a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov */ 168a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovpackage com.android.contacts.list; 178a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 188a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport com.android.contacts.R; 1902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikovimport com.android.contacts.util.Constants; 208a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 21dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Rootimport android.app.ActivityManager; 228a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.content.ContentResolver; 238a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.content.Context; 248a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.content.Intent; 258a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.content.res.Resources; 268a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.database.Cursor; 278a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.graphics.Bitmap; 288a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.graphics.BitmapFactory; 298a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.graphics.Canvas; 308a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.graphics.Paint; 311a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huangimport android.graphics.Paint.FontMetricsInt; 328a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.graphics.Rect; 3302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikovimport android.graphics.drawable.BitmapDrawable; 3459d8c63ee500a4852b307cfb47bfd21d58ee148eDmitri Plotnikovimport android.graphics.drawable.Drawable; 358a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.net.Uri; 368a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.os.AsyncTask; 378a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovimport android.provider.ContactsContract; 3802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 3902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 4092d3e42302e6b42fe967f81fc8ffde43f86d6c59Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 4192d3e42302e6b42fe967f81fc8ffde43f86d6c59Dmitri Plotnikovimport android.provider.ContactsContract.Data; 421a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huangimport android.text.TextPaint; 431a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huangimport android.text.TextUtils; 441a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huangimport android.text.TextUtils.TruncateAt; 458a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 468a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov/** 478a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * Constructs shortcut intents. 488a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov */ 498a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikovpublic class ShortcutIntentBuilder { 508a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 518a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private static final String[] CONTACT_COLUMNS = { 528a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Contacts.DISPLAY_NAME, 538a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Contacts.PHOTO_ID, 548a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov }; 558a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 568a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private static final int CONTACT_DISPLAY_NAME_COLUMN_INDEX = 0; 578a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private static final int CONTACT_PHOTO_ID_COLUMN_INDEX = 1; 588a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 5902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private static final String[] PHONE_COLUMNS = { 6002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Phone.DISPLAY_NAME, 6102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Phone.PHOTO_ID, 6202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Phone.NUMBER, 6302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Phone.TYPE, 641a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang Phone.LABEL 6502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov }; 6602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 6702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private static final int PHONE_DISPLAY_NAME_COLUMN_INDEX = 0; 6802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private static final int PHONE_PHOTO_ID_COLUMN_INDEX = 1; 6902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private static final int PHONE_NUMBER_COLUMN_INDEX = 2; 7002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private static final int PHONE_TYPE_COLUMN_INDEX = 3; 711a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private static final int PHONE_LABEL_COLUMN_INDEX = 4; 7202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 738a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private static final String[] PHOTO_COLUMNS = { 748a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Photo.PHOTO, 758a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov }; 768a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 778a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private static final int PHOTO_PHOTO_COLUMN_INDEX = 0; 788a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 798a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private static final String PHOTO_SELECTION = Photo._ID + "=?"; 808a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 818a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private final OnShortcutIntentCreatedListener mListener; 828a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov private final Context mContext; 83c49deffc83b18da1a1ec5c28bf1a322ce0ca2470Dmitri Plotnikov private int mIconSize; 84dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root private final int mIconDensity; 851a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private final int mBorderWidth; 861a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private final int mBorderColor; 878a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 888a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov /** 898a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * Listener interface. 908a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov */ 918a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov public interface OnShortcutIntentCreatedListener { 928a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 938a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov /** 948a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * Callback for shortcut intent creation. 958a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * 968a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * @param uri the original URI for which the shortcut intent has been 978a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * created. 988a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov * @param shortcutIntent resulting shortcut intent. 998a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov */ 1008a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov void onShortcutIntentCreated(Uri uri, Intent shortcutIntent); 1018a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 1028a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 1038a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov public ShortcutIntentBuilder(Context context, OnShortcutIntentCreatedListener listener) { 1048a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov mContext = context; 1058a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov mListener = listener; 1068a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 1071a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final Resources r = context.getResources(); 108dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root final ActivityManager am = (ActivityManager) context 109dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root .getSystemService(Context.ACTIVITY_SERVICE); 1101a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang mIconSize = r.getDimensionPixelSize(R.dimen.shortcut_icon_size); 111c49deffc83b18da1a1ec5c28bf1a322ce0ca2470Dmitri Plotnikov if (mIconSize == 0) { 112c49deffc83b18da1a1ec5c28bf1a322ce0ca2470Dmitri Plotnikov mIconSize = am.getLauncherLargeIconSize(); 113c49deffc83b18da1a1ec5c28bf1a322ce0ca2470Dmitri Plotnikov } 114dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root mIconDensity = am.getLauncherLargeIconDensity(); 1151a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang mBorderWidth = r.getDimensionPixelOffset( 1161a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang R.dimen.shortcut_icon_border_width); 1171a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang mBorderColor = r.getColor(R.color.shortcut_overlay_text_background); 1188a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 1198a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 1208a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov public void createContactShortcutIntent(Uri contactUri) { 12102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov new ContactLoadingAsyncTask(contactUri).execute(); 12202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 12302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 12402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov public void createPhoneNumberShortcutIntent(Uri dataUri, String shortcutAction) { 12502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov new PhoneNumberLoadingAsyncTask(dataUri, shortcutAction).execute(); 1268a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 1278a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 1288a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov /** 12902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov * An asynchronous task that loads name, photo and other data from the database. 1308a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov */ 13102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private abstract class LoadingAsyncTask extends AsyncTask<Void, Void, Void> { 13202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected Uri mUri; 13302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected String mDisplayName; 13402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected byte[] mBitmapData; 13502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected long mPhotoId; 13602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 13702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov public LoadingAsyncTask(Uri uri) { 13802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mUri = uri; 13902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 1408a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 1418a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov @Override 14202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected Void doInBackground(Void... params) { 14302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov loadData(); 14402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov loadPhoto(); 14502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov return null; 14602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 14702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 14802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected abstract void loadData(); 14902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 15002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private void loadPhoto() { 15102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov if (mPhotoId == 0) { 15202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov return; 15302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 1548a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 1558a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov ContentResolver resolver = mContext.getContentResolver(); 15602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Cursor cursor = resolver.query(Data.CONTENT_URI, PHOTO_COLUMNS, PHOTO_SELECTION, 15702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov new String[] { String.valueOf(mPhotoId) }, null); 15802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov if (cursor != null) { 15902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov try { 16002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov if (cursor.moveToFirst()) { 16102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mBitmapData = cursor.getBlob(PHOTO_PHOTO_COLUMN_INDEX); 16202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 16302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } finally { 16402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov cursor.close(); 16502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 16602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 16702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 16802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 1698a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 17002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private final class ContactLoadingAsyncTask extends LoadingAsyncTask { 17102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov public ContactLoadingAsyncTask(Uri uri) { 17202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov super(uri); 17302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 1748a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 17502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov @Override 17602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected void loadData() { 17702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov ContentResolver resolver = mContext.getContentResolver(); 1788a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Cursor cursor = resolver.query(mUri, CONTACT_COLUMNS, null, null, null); 1798a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov if (cursor != null) { 1808a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov try { 1818a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov if (cursor.moveToFirst()) { 1828a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov mDisplayName = cursor.getString(CONTACT_DISPLAY_NAME_COLUMN_INDEX); 18302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mPhotoId = cursor.getLong(CONTACT_PHOTO_ID_COLUMN_INDEX); 1848a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 1858a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } finally { 1868a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov cursor.close(); 1878a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 1888a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 18902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 19002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov @Override 19102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected void onPostExecute(Void result) { 19202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov createContactShortcutIntent(mUri, mDisplayName, mBitmapData); 19302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 19402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 19502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 19602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private final class PhoneNumberLoadingAsyncTask extends LoadingAsyncTask { 19702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private final String mShortcutAction; 19802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private String mPhoneNumber; 19902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private int mPhoneType; 2001a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private String mPhoneLabel; 2018a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 20202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov public PhoneNumberLoadingAsyncTask(Uri uri, String shortcutAction) { 20302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov super(uri); 20402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mShortcutAction = shortcutAction; 20502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 20602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 20702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov @Override 20802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov protected void loadData() { 20902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov ContentResolver resolver = mContext.getContentResolver(); 21002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Cursor cursor = resolver.query(mUri, PHONE_COLUMNS, null, null, null); 21102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov if (cursor != null) { 21202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov try { 21302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov if (cursor.moveToFirst()) { 21402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mDisplayName = cursor.getString(PHONE_DISPLAY_NAME_COLUMN_INDEX); 21502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mPhotoId = cursor.getLong(PHONE_PHOTO_ID_COLUMN_INDEX); 21602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mPhoneNumber = cursor.getString(PHONE_NUMBER_COLUMN_INDEX); 21702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mPhoneType = cursor.getInt(PHONE_TYPE_COLUMN_INDEX); 2181a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang mPhoneLabel = cursor.getString(PHONE_LABEL_COLUMN_INDEX); 2198a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 22002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } finally { 22102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov cursor.close(); 2228a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 2238a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 2248a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 2258a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 2268a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov @Override 2278a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov protected void onPostExecute(Void result) { 22802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov createPhoneNumberShortcutIntent(mUri, mDisplayName, mBitmapData, mPhoneNumber, 2291a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang mPhoneType, mPhoneLabel, mShortcutAction); 2308a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 2318a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 2328a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 2331a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private Bitmap getPhotoBitmap(byte[] bitmapData) { 2348a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Bitmap bitmap; 2358a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov if (bitmapData != null) { 2368a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length, null); 2378a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } else { 238dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root bitmap = ((BitmapDrawable) mContext.getResources().getDrawableForDensity( 239ecfc26c3f9495f1a4efed69a1582ff2b0deb2c71Daniel Lehmann R.drawable.ic_contact_picture_holo_light, mIconDensity)).getBitmap(); 2408a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 2411a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang return bitmap; 2421a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang } 2431a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang 2441a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private void createContactShortcutIntent(Uri contactUri, String displayName, 2451a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang byte[] bitmapData) { 2461a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang Bitmap bitmap = getPhotoBitmap(bitmapData); 2478a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 2488a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Intent shortcutIntent; 2498a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov // This is a simple shortcut to view a contact. 2508a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov shortcutIntent = new Intent(ContactsContract.QuickContact.ACTION_QUICK_CONTACT); 2518a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 2528a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 2538a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 2548a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov shortcutIntent.setData(contactUri); 2558a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_MODE, 2568a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov ContactsContract.QuickContact.MODE_LARGE); 2578a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_EXCLUDE_MIMES, 2588a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov (String[]) null); 2598a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 2608a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 26159d8c63ee500a4852b307cfb47bfd21d58ee148eDmitri Plotnikov final Bitmap icon = generateQuickContactIcon(bitmap); 2628a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 26302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Intent intent = new Intent(); 26402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon); 2658a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); 2668a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName); 2678a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 2688a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov mListener.onShortcutIntentCreated(contactUri, intent); 2698a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 2708a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 27102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov private void createPhoneNumberShortcutIntent(Uri uri, String displayName, byte[] bitmapData, 2721a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang String phoneNumber, int phoneType, String phoneLabel, String shortcutAction) { 2731a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang Bitmap bitmap = getPhotoBitmap(bitmapData); 27402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 27502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Uri phoneUri; 27602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov if (Intent.ACTION_CALL.equals(shortcutAction)) { 27702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov // Make the URI a direct tel: URI so that it will always continue to work 27802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov phoneUri = Uri.fromParts(Constants.SCHEME_TEL, phoneNumber, null); 2791a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang bitmap = generatePhoneNumberIcon(bitmap, phoneType, phoneLabel, 2801a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang R.drawable.badge_action_call); 28102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } else { 28202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov phoneUri = Uri.fromParts(Constants.SCHEME_SMSTO, phoneNumber, null); 2831a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang bitmap = generatePhoneNumberIcon(bitmap, phoneType, phoneLabel, 2841a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang R.drawable.badge_action_sms); 28502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 28602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 28702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Intent shortcutIntent = new Intent(shortcutAction, phoneUri); 28802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 28902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 29002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Intent intent = new Intent(); 29102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap); 29202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); 29302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName); 29402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 29502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov mListener.onShortcutIntentCreated(uri, intent); 29602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 29702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 2981a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private void drawBorder(Canvas canvas, Rect dst) { 2991a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang // Darken the border 3001a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final Paint workPaint = new Paint(); 3011a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang workPaint.setColor(mBorderColor); 3021a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang workPaint.setStyle(Paint.Style.STROKE); 3031a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang // The stroke is drawn centered on the rect bounds, and since half will be drawn outside the 3041a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang // bounds, we need to double the width for it to appear as intended. 3051a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang workPaint.setStrokeWidth(mBorderWidth * 2); 3061a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang canvas.drawRect(dst, workPaint); 3071a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang } 3081a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang 30959d8c63ee500a4852b307cfb47bfd21d58ee148eDmitri Plotnikov private Bitmap generateQuickContactIcon(Bitmap photo) { 3108a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 3118a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov // Setup the drawing classes 3128a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Bitmap icon = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888); 3138a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Canvas canvas = new Canvas(icon); 3148a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 3158a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov // Copy in the photo 3168a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Paint photoPaint = new Paint(); 3178a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov photoPaint.setDither(true); 3188a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov photoPaint.setFilterBitmap(true); 3198a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Rect src = new Rect(0,0, photo.getWidth(),photo.getHeight()); 3208a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov Rect dst = new Rect(0,0, mIconSize, mIconSize); 3218a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov canvas.drawBitmap(photo, src, dst, photoPaint); 3228a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov 3231a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang drawBorder(canvas, dst); 3241a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang 325dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root Drawable overlay = mContext.getResources().getDrawableForDensity( 326dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root com.android.internal.R.drawable.quickcontact_badge_overlay_dark, mIconDensity); 32759d8c63ee500a4852b307cfb47bfd21d58ee148eDmitri Plotnikov 32859d8c63ee500a4852b307cfb47bfd21d58ee148eDmitri Plotnikov overlay.setBounds(dst); 32959d8c63ee500a4852b307cfb47bfd21d58ee148eDmitri Plotnikov overlay.draw(canvas); 33035168ccd8beda015ae5fd6ca25972fc21e422865Dianne Hackborn canvas.setBitmap(null); 33159d8c63ee500a4852b307cfb47bfd21d58ee148eDmitri Plotnikov 3328a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov return icon; 3338a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov } 33402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 33502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov /** 33602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov * Generates a phone number shortcut icon. Adds an overlay describing the type of the phone 33702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov * number, and if there is a photo also adds the call action icon. 33802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov */ 3391a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang private Bitmap generatePhoneNumberIcon(Bitmap photo, int phoneType, String phoneLabel, 3401a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang int actionResId) { 34102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov final Resources r = mContext.getResources(); 3421a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final float density = r.getDisplayMetrics().density; 34302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 344dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root Bitmap phoneIcon = ((BitmapDrawable) r.getDrawableForDensity(actionResId, mIconDensity)) 345dc4c0e07a79dd1e7d6e062e789aa78266825d540Kenny Root .getBitmap(); 34602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 34702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov // Setup the drawing classes 34802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Bitmap icon = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888); 34902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Canvas canvas = new Canvas(icon); 35002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 35102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov // Copy in the photo 35202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Paint photoPaint = new Paint(); 35302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov photoPaint.setDither(true); 35402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov photoPaint.setFilterBitmap(true); 35502935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Rect src = new Rect(0, 0, photo.getWidth(), photo.getHeight()); 35602935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov Rect dst = new Rect(0, 0, mIconSize, mIconSize); 35702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov canvas.drawBitmap(photo, src, dst, photoPaint); 35802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 3591a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang drawBorder(canvas, dst); 3601a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang 36102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov // Create an overlay for the phone number type 3621a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang CharSequence overlay = Phone.getTypeLabel(r, phoneType, phoneLabel); 36302935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 36402935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov if (overlay != null) { 3651a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); 3661a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang textPaint.setTextSize(r.getDimension(R.dimen.shortcut_overlay_text_size)); 36702935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov textPaint.setColor(r.getColor(R.color.textColorIconOverlay)); 3681a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang textPaint.setShadowLayer(4f, 0, 2f, r.getColor(R.color.textColorIconOverlayShadow)); 3691a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang 3701a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final FontMetricsInt fmi = textPaint.getFontMetricsInt(); 3711a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang 3721a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang // First fill in a darker background around the text to be drawn 3731a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final Paint workPaint = new Paint(); 3741a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang workPaint.setColor(mBorderColor); 3751a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang workPaint.setStyle(Paint.Style.FILL); 3761a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final int textPadding = r 3771a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang .getDimensionPixelOffset(R.dimen.shortcut_overlay_text_background_padding); 3781a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final int textBandHeight = (fmi.descent - fmi.ascent) + textPadding * 2; 3791a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang dst.set(0 + mBorderWidth, mIconSize - textBandHeight, mIconSize - mBorderWidth, 3801a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang mIconSize - mBorderWidth); 3811a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang canvas.drawRect(dst, workPaint); 3821a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang 3831a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final float sidePadding = mBorderWidth; 3841a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang overlay = TextUtils.ellipsize(overlay, textPaint, mIconSize - 2 * sidePadding, 3851a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang TruncateAt.END_SMALL); 3861a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang final float textWidth = textPaint.measureText(overlay, 0, overlay.length()); 3871a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang canvas.drawText(overlay, 0, overlay.length(), (mIconSize - textWidth) / 2, mIconSize 3881a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang - fmi.descent - textPadding, textPaint); 38902935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 39002935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 39102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov // Draw the phone action icon as an overlay 3921a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang src.set(0, 0, phoneIcon.getWidth(), phoneIcon.getHeight()); 3931a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang int iconWidth = icon.getWidth(); 3941a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang dst.set(iconWidth - ((int) (20 * density)), -1, 3951a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang iconWidth, ((int) (19 * density))); 3961a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang dst.offset(-mBorderWidth, mBorderWidth); 3971a817f04a3fff3d578f5290ea8d82faba7d44b02Andy Huang canvas.drawBitmap(phoneIcon, src, dst, photoPaint); 39802935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov 39935168ccd8beda015ae5fd6ca25972fc21e422865Dianne Hackborn canvas.setBitmap(null); 40035168ccd8beda015ae5fd6ca25972fc21e422865Dianne Hackborn 40102935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov return icon; 40202935722ce2fcc3bd839e3571a08b8b79d70b8adDmitri Plotnikov } 4038a7831944232fd01740492b39bc67d746213b82bDmitri Plotnikov} 404