Making call/sms shortcuts work with Loaders and Fragments.
Change-Id: Ie88fb17e0e533e8868c68f8e74d609df17310e35
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index a8554b3..512b182 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -37,7 +37,6 @@
import com.android.contacts.ui.ContactsPreferencesActivity;
import com.android.contacts.ui.ContactsPreferencesActivity.Prefs;
import com.android.contacts.util.AccountSelectionUtil;
-import com.android.contacts.util.Constants;
import com.android.contacts.widget.ContextMenuAdapter;
import android.accounts.Account;
@@ -59,14 +58,6 @@
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.MatrixCursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -86,7 +77,6 @@
import android.provider.ContactsContract.SearchSnippetColumns;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.Intents.Insert;
import android.telephony.TelephonyManager;
@@ -101,7 +91,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
-import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
@@ -112,7 +101,6 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
-import java.util.Random;
/**
* Displays a list of contacts. Usually is embedded into the ContactsActivity.
@@ -701,6 +689,7 @@
fragment.setLegacyCompatibility(true);
}
fragment.setSectionHeaderDisplayEnabled(false);
+ fragment.setShortcutAction(mShortcutAction);
fragment.setOnPhoneNumberPickerActionListener(
new OnPhoneNumberPickerActionListener() {
@@ -713,6 +702,11 @@
public void onSearchAllContactsAction(String string) {
doSearch();
}
+
+ public void onShortcutIntentCreated(Intent intent) {
+ setResult(RESULT_OK, intent);
+ finish();
+ }
});
mListFragment = fragment;
break;
@@ -1495,221 +1489,8 @@
}
}
- private void hideSoftKeyboard() {
- // Hide soft keyboard, if visible
- InputMethodManager inputMethodManager = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodManager.hideSoftInputFromWindow(mListView.getWindowToken(), 0);
- }
-
- /**
- * @param selectedUri In most cases, this should be a lookup {@link Uri}, possibly
- * generated through {@link Contacts#getLookupUri(long, String)}.
- */
- protected void returnPickerResult(Cursor c, String name, Uri selectedUri) {
- final Intent intent = new Intent();
-
- if (mShortcutAction != null) {
- Intent shortcutIntent;
- if (Intent.ACTION_VIEW.equals(mShortcutAction)) {
- // This is a simple shortcut to view a contact.
- shortcutIntent = new Intent(ContactsContract.QuickContact.ACTION_QUICK_CONTACT);
- shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
- shortcutIntent.setData(selectedUri);
- shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_MODE,
- ContactsContract.QuickContact.MODE_LARGE);
- shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_EXCLUDE_MIMES,
- (String[]) null);
-
- final Bitmap icon = framePhoto(loadContactPhoto(selectedUri, null));
- if (icon != null) {
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaleToAppIconSize(icon));
- } else {
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
- Intent.ShortcutIconResource.fromContext(this,
- R.drawable.ic_launcher_shortcut_contact));
- }
- } else {
- // This is a direct dial or sms shortcut.
- String number = c.getString(PHONE_NUMBER_COLUMN_INDEX);
- int type = c.getInt(PHONE_TYPE_COLUMN_INDEX);
- String scheme;
- int resid;
- if (Intent.ACTION_CALL.equals(mShortcutAction)) {
- scheme = Constants.SCHEME_TEL;
- resid = R.drawable.badge_action_call;
- } else {
- scheme = Constants.SCHEME_SMSTO;
- resid = R.drawable.badge_action_sms;
- }
-
- // Make the URI a direct tel: URI so that it will always continue to work
- Uri phoneUri = Uri.fromParts(scheme, number, null);
- shortcutIntent = new Intent(mShortcutAction, phoneUri);
-
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON,
- generatePhoneNumberIcon(selectedUri, type, resid));
- }
- shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
- intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
- setResult(RESULT_OK, intent);
- } else {
- intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
- setResult(RESULT_OK, intent.setData(selectedUri));
- }
- finish();
- }
-
- private Bitmap framePhoto(Bitmap photo) {
- final Resources r = getResources();
- final Drawable frame = r.getDrawable(com.android.internal.R.drawable.quickcontact_badge);
-
- final int width = r.getDimensionPixelSize(R.dimen.contact_shortcut_frame_width);
- final int height = r.getDimensionPixelSize(R.dimen.contact_shortcut_frame_height);
-
- frame.setBounds(0, 0, width, height);
-
- final Rect padding = new Rect();
- frame.getPadding(padding);
-
- final Rect source = new Rect(0, 0, photo.getWidth(), photo.getHeight());
- final Rect destination = new Rect(padding.left, padding.top,
- width - padding.right, height - padding.bottom);
-
- final int d = Math.max(width, height);
- final Bitmap b = Bitmap.createBitmap(d, d, Bitmap.Config.ARGB_8888);
- final Canvas c = new Canvas(b);
-
- c.translate((d - width) / 2.0f, (d - height) / 2.0f);
- frame.draw(c);
- c.drawBitmap(photo, source, destination, new Paint(Paint.FILTER_BITMAP_FLAG));
-
- return b;
- }
-
- /**
- * Generates a phone number shortcut icon. Adds an overlay describing the type of the phone
- * number, and if there is a photo also adds the call action icon.
- *
- * @param lookupUri The person the phone number belongs to
- * @param type The type of the phone number
- * @param actionResId The ID for the action resource
- * @return The bitmap for the icon
- */
- private Bitmap generatePhoneNumberIcon(Uri lookupUri, int type, int actionResId) {
- final Resources r = getResources();
- boolean drawPhoneOverlay = true;
- final float scaleDensity = getResources().getDisplayMetrics().scaledDensity;
-
- Bitmap photo = loadContactPhoto(lookupUri, null);
- if (photo == null) {
- // If there isn't a photo use the generic phone action icon instead
- Bitmap phoneIcon = getPhoneActionIcon(r, actionResId);
- if (phoneIcon != null) {
- photo = phoneIcon;
- drawPhoneOverlay = false;
- } else {
- return null;
- }
- }
-
- // Setup the drawing classes
- Bitmap icon = createShortcutBitmap();
- Canvas canvas = new Canvas(icon);
-
- // Copy in the photo
- Paint photoPaint = new Paint();
- photoPaint.setDither(true);
- photoPaint.setFilterBitmap(true);
- Rect src = new Rect(0,0, photo.getWidth(),photo.getHeight());
- Rect dst = new Rect(0,0, mIconSize, mIconSize);
- canvas.drawBitmap(photo, src, dst, photoPaint);
-
- // Create an overlay for the phone number type
- String overlay = null;
- switch (type) {
- case Phone.TYPE_HOME:
- overlay = getString(R.string.type_short_home);
- break;
-
- case Phone.TYPE_MOBILE:
- overlay = getString(R.string.type_short_mobile);
- break;
-
- case Phone.TYPE_WORK:
- overlay = getString(R.string.type_short_work);
- break;
-
- case Phone.TYPE_PAGER:
- overlay = getString(R.string.type_short_pager);
- break;
-
- case Phone.TYPE_OTHER:
- overlay = getString(R.string.type_short_other);
- break;
- }
- if (overlay != null) {
- Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
- textPaint.setTextSize(20.0f * scaleDensity);
- textPaint.setTypeface(Typeface.DEFAULT_BOLD);
- textPaint.setColor(r.getColor(R.color.textColorIconOverlay));
- textPaint.setShadowLayer(3f, 1, 1, r.getColor(R.color.textColorIconOverlayShadow));
- canvas.drawText(overlay, 2 * scaleDensity, 16 * scaleDensity, textPaint);
- }
-
- // Draw the phone action icon as an overlay
- if (ENABLE_ACTION_ICON_OVERLAYS && drawPhoneOverlay) {
- Bitmap phoneIcon = getPhoneActionIcon(r, actionResId);
- if (phoneIcon != null) {
- src.set(0, 0, phoneIcon.getWidth(), phoneIcon.getHeight());
- int iconWidth = icon.getWidth();
- dst.set(iconWidth - ((int) (20 * scaleDensity)), -1,
- iconWidth, ((int) (19 * scaleDensity)));
- canvas.drawBitmap(phoneIcon, src, dst, photoPaint);
- }
- }
-
- return icon;
- }
-
- private Bitmap scaleToAppIconSize(Bitmap photo) {
- // Setup the drawing classes
- Bitmap icon = createShortcutBitmap();
- Canvas canvas = new Canvas(icon);
-
- // Copy in the photo
- Paint photoPaint = new Paint();
- photoPaint.setDither(true);
- photoPaint.setFilterBitmap(true);
- Rect src = new Rect(0,0, photo.getWidth(),photo.getHeight());
- Rect dst = new Rect(0,0, mIconSize, mIconSize);
- canvas.drawBitmap(photo, src, dst, photoPaint);
-
- return icon;
- }
-
- private Bitmap createShortcutBitmap() {
- return Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
- }
-
- /**
- * Returns the icon for the phone call action.
- *
- * @param r The resources to load the icon from
- * @param resId The resource ID to load
- * @return the icon for the phone call action
- */
- private Bitmap getPhoneActionIcon(Resources r, int resId) {
- Drawable phoneIcon = r.getDrawable(resId);
- if (phoneIcon instanceof BitmapDrawable) {
- BitmapDrawable bd = (BitmapDrawable) phoneIcon;
- return bd.getBitmap();
- } else {
- return null;
- }
+ @Deprecated
+ private void returnPickerResult(Cursor c, String string, Uri uri) {
}
protected Uri getUriToQuery() {
@@ -1889,54 +1670,6 @@
return CONTACTS_SUMMARY_PROJECTION;
}
- private Bitmap loadContactPhoto(Uri selectedUri, BitmapFactory.Options options) {
- Uri contactUri = null;
- if (Contacts.CONTENT_ITEM_TYPE.equals(getContentResolver().getType(selectedUri))) {
- // TODO we should have a "photo" directory under the lookup URI itself
- contactUri = Contacts.lookupContact(getContentResolver(), selectedUri);
- } else {
-
- Cursor cursor = getContentResolver().query(selectedUri,
- new String[] { Data.CONTACT_ID }, null, null, null);
- try {
- if (cursor != null && cursor.moveToFirst()) {
- final long contactId = cursor.getLong(0);
- contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
- }
- } finally {
- if (cursor != null) cursor.close();
- }
- }
-
- Cursor cursor = null;
- Bitmap bm = null;
-
- try {
- Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
- cursor = getContentResolver().query(photoUri, new String[] {Photo.PHOTO},
- null, null, null);
- if (cursor != null && cursor.moveToFirst()) {
- bm = ContactsUtils.loadContactPhoto(cursor, 0, options);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- if (bm == null) {
- final int[] fallbacks = {
- R.drawable.ic_contact_picture,
- R.drawable.ic_contact_picture_2,
- R.drawable.ic_contact_picture_3
- };
- bm = BitmapFactory.decodeResource(getResources(),
- fallbacks[new Random().nextInt(fallbacks.length)]);
- }
-
- return bm;
- }
-
/**
* Return the selection arguments for a default query based on the
* {@link #mDisplayOnlyPhones} flag.
diff --git a/src/com/android/contacts/JoinContactActivity.java b/src/com/android/contacts/JoinContactActivity.java
index 21f5929..9024e0b 100644
--- a/src/com/android/contacts/JoinContactActivity.java
+++ b/src/com/android/contacts/JoinContactActivity.java
@@ -19,6 +19,7 @@
import com.android.contacts.list.JoinContactListAdapter;
import com.android.contacts.list.JoinContactListFragment;
+import com.android.internal.telephony.gsm.stk.ResultCode;
import android.content.ContentUris;
import android.content.Intent;
@@ -110,7 +111,8 @@
startQuery();
} else {
final Uri uri = getSelectedUri(position);
- returnPickerResult(null, null, uri);
+ setResult(RESULT_OK, new Intent(null, uri));
+ finish();
}
}
diff --git a/src/com/android/contacts/list/OnPhoneNumberPickerActionListener.java b/src/com/android/contacts/list/OnPhoneNumberPickerActionListener.java
index f30c223..701cc78 100644
--- a/src/com/android/contacts/list/OnPhoneNumberPickerActionListener.java
+++ b/src/com/android/contacts/list/OnPhoneNumberPickerActionListener.java
@@ -15,6 +15,7 @@
*/
package com.android.contacts.list;
+import android.content.Intent;
import android.net.Uri;
/**
@@ -28,6 +29,11 @@
void onPickPhoneNumberAction(Uri dataUri);
/**
+ * Returns the selected number as a shortcut intent.
+ */
+ void onShortcutIntentCreated(Intent intent);
+
+ /**
* Searches all contacts for the specified string an show results for browsing.
*/
void onSearchAllContactsAction(String string);
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index 588f4ac..f155637 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -16,7 +16,9 @@
package com.android.contacts.list;
import com.android.contacts.R;
+import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
@@ -26,8 +28,10 @@
* Fragment containing a contact list used for browsing (as compared to
* picking a contact with one of the PICK intents).
*/
-public class PhoneNumberPickerFragment extends ContactEntryListFragment<PhoneNumberListAdapter> {
+public class PhoneNumberPickerFragment extends ContactEntryListFragment<PhoneNumberListAdapter>
+ implements OnShortcutIntentCreatedListener {
private OnPhoneNumberPickerActionListener mListener;
+ private String mShortcutAction;
public PhoneNumberPickerFragment() {
setPhotoLoaderEnabled(true);
@@ -38,6 +42,14 @@
this.mListener = listener;
}
+ /**
+ * @param shortcutAction either {@link Intent#ACTION_CALL} or
+ * {@link Intent#ACTION_SENDTO} or null.
+ */
+ public void setShortcutAction(String shortcutAction) {
+ this.mShortcutAction = shortcutAction;
+ }
+
@Override
protected void onItemClick(int position, long id) {
PhoneNumberListAdapter adapter = getAdapter();
@@ -78,6 +90,15 @@
}
public void pickPhoneNumber(Uri uri) {
- mListener.onPickPhoneNumberAction(uri);
+ if (mShortcutAction == null) {
+ mListener.onPickPhoneNumberAction(uri);
+ } else {
+ ShortcutIntentBuilder builder = new ShortcutIntentBuilder(getActivity(), this);
+ builder.createPhoneNumberShortcutIntent(getAdapter().getDataUri(), mShortcutAction);
+ }
+ }
+
+ public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) {
+ mListener.onShortcutIntentCreated(shortcutIntent);
}
}
diff --git a/src/com/android/contacts/list/ShortcutIntentBuilder.java b/src/com/android/contacts/list/ShortcutIntentBuilder.java
index 6452c05..7a4f9de 100644
--- a/src/com/android/contacts/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/list/ShortcutIntentBuilder.java
@@ -15,11 +15,10 @@
*/
package com.android.contacts.list;
-import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
+import com.android.contacts.util.Constants;
import android.content.ContentResolver;
-import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -29,13 +28,16 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
import java.util.Random;
@@ -52,6 +54,18 @@
private static final int CONTACT_DISPLAY_NAME_COLUMN_INDEX = 0;
private static final int CONTACT_PHOTO_ID_COLUMN_INDEX = 1;
+ private static final String[] PHONE_COLUMNS = {
+ Phone.DISPLAY_NAME,
+ Phone.PHOTO_ID,
+ Phone.NUMBER,
+ Phone.TYPE,
+ };
+
+ private static final int PHONE_DISPLAY_NAME_COLUMN_INDEX = 0;
+ private static final int PHONE_PHOTO_ID_COLUMN_INDEX = 1;
+ private static final int PHONE_NUMBER_COLUMN_INDEX = 2;
+ private static final int PHONE_TYPE_COLUMN_INDEX = 3;
+
private static final String[] PHOTO_COLUMNS = {
Photo.PHOTO,
};
@@ -87,64 +101,119 @@
}
public void createContactShortcutIntent(Uri contactUri) {
- new ContactLoadingAsyncTask().execute(contactUri);
+ new ContactLoadingAsyncTask(contactUri).execute();
+ }
+
+ public void createPhoneNumberShortcutIntent(Uri dataUri, String shortcutAction) {
+ new PhoneNumberLoadingAsyncTask(dataUri, shortcutAction).execute();
}
/**
- * An asynchronous task that loads the photo from the database.
+ * An asynchronous task that loads name, photo and other data from the database.
*/
- private final class ContactLoadingAsyncTask extends AsyncTask<Uri, Void, Void> {
- private Uri mUri;
- private String mDisplayName;
- private byte[] mBitmapData;
+ private abstract class LoadingAsyncTask extends AsyncTask<Void, Void, Void> {
+ protected Uri mUri;
+ protected String mDisplayName;
+ protected byte[] mBitmapData;
+ protected long mPhotoId;
+
+ public LoadingAsyncTask(Uri uri) {
+ mUri = uri;
+ }
@Override
- protected Void doInBackground(Uri... uris) {
- mUri = uris[0];
+ protected Void doInBackground(Void... params) {
+ loadData();
+ loadPhoto();
+ return null;
+ }
+
+ protected abstract void loadData();
+
+ private void loadPhoto() {
+ if (mPhotoId == 0) {
+ return;
+ }
ContentResolver resolver = mContext.getContentResolver();
-
- long photoId = 0;
-
- Cursor cursor = resolver.query(mUri, CONTACT_COLUMNS, null, null, null);
+ Cursor cursor = resolver.query(Data.CONTENT_URI, PHOTO_COLUMNS, PHOTO_SELECTION,
+ new String[] { String.valueOf(mPhotoId) }, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
- mDisplayName = cursor.getString(CONTACT_DISPLAY_NAME_COLUMN_INDEX);
- photoId = cursor.getLong(CONTACT_PHOTO_ID_COLUMN_INDEX);
+ mBitmapData = cursor.getBlob(PHOTO_PHOTO_COLUMN_INDEX);
}
} finally {
cursor.close();
}
}
+ }
+ }
- if (photoId != 0) {
- cursor = resolver.query(Data.CONTENT_URI, PHOTO_COLUMNS, PHOTO_SELECTION,
- new String[] { String.valueOf(photoId) }, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- mBitmapData = cursor.getBlob(PHOTO_PHOTO_COLUMN_INDEX);
- }
- } finally {
- cursor.close();
- }
- }
- }
-
- return null;
+ private final class ContactLoadingAsyncTask extends LoadingAsyncTask {
+ public ContactLoadingAsyncTask(Uri uri) {
+ super(uri);
}
@Override
+ protected void loadData() {
+ ContentResolver resolver = mContext.getContentResolver();
+ Cursor cursor = resolver.query(mUri, CONTACT_COLUMNS, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ mDisplayName = cursor.getString(CONTACT_DISPLAY_NAME_COLUMN_INDEX);
+ mPhotoId = cursor.getLong(CONTACT_PHOTO_ID_COLUMN_INDEX);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ @Override
protected void onPostExecute(Void result) {
createContactShortcutIntent(mUri, mDisplayName, mBitmapData);
}
}
- public void createContactShortcutIntent(Uri contactUri, String displayName, byte[] bitmapData) {
+ private final class PhoneNumberLoadingAsyncTask extends LoadingAsyncTask {
+ private final String mShortcutAction;
+ private String mPhoneNumber;
+ private int mPhoneType;
+ public PhoneNumberLoadingAsyncTask(Uri uri, String shortcutAction) {
+ super(uri);
+ mShortcutAction = shortcutAction;
+ }
+
+ @Override
+ protected void loadData() {
+ ContentResolver resolver = mContext.getContentResolver();
+ Cursor cursor = resolver.query(mUri, PHONE_COLUMNS, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ mDisplayName = cursor.getString(PHONE_DISPLAY_NAME_COLUMN_INDEX);
+ mPhotoId = cursor.getLong(PHONE_PHOTO_ID_COLUMN_INDEX);
+ mPhoneNumber = cursor.getString(PHONE_NUMBER_COLUMN_INDEX);
+ mPhoneType = cursor.getInt(PHONE_TYPE_COLUMN_INDEX);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ createPhoneNumberShortcutIntent(mUri, mDisplayName, mBitmapData, mPhoneNumber,
+ mPhoneType, mShortcutAction);
+ }
+ }
+
+ private void createContactShortcutIntent(Uri contactUri, String displayName,
+ byte[] bitmapData) {
Bitmap bitmap;
-
if (bitmapData != null) {
bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length, null);
} else {
@@ -170,16 +239,44 @@
(String[]) null);
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- Intent intent = new Intent();
+ final Bitmap icon = scaleToAppIconSize(framePhoto(bitmap));
- final Bitmap icon = framePhoto(bitmap);
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaleToAppIconSize(icon));
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName);
mListener.onShortcutIntentCreated(contactUri, intent);
}
+ private void createPhoneNumberShortcutIntent(Uri uri, String displayName, byte[] bitmapData,
+ String phoneNumber, int phoneType, String shortcutAction) {
+ Bitmap bitmap = null;
+ if (bitmapData != null) {
+ bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length, null);
+ }
+
+ Uri phoneUri;
+ if (Intent.ACTION_CALL.equals(shortcutAction)) {
+ // Make the URI a direct tel: URI so that it will always continue to work
+ phoneUri = Uri.fromParts(Constants.SCHEME_TEL, phoneNumber, null);
+ bitmap = generatePhoneNumberIcon(bitmap, phoneType, R.drawable.badge_action_call);
+ } else {
+ phoneUri = Uri.fromParts(Constants.SCHEME_SMSTO, phoneNumber, null);
+ bitmap = generatePhoneNumberIcon(bitmap, phoneType, R.drawable.badge_action_sms);
+ }
+
+ Intent shortcutIntent = new Intent(shortcutAction, phoneUri);
+ shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName);
+
+ mListener.onShortcutIntentCreated(uri, intent);
+ }
+
private Bitmap framePhoto(Bitmap photo) {
final Resources r = mContext.getResources();
final Drawable frame = r.getDrawable(com.android.internal.R.drawable.quickcontact_badge);
@@ -223,4 +320,78 @@
return icon;
}
+
+ /**
+ * Generates a phone number shortcut icon. Adds an overlay describing the type of the phone
+ * number, and if there is a photo also adds the call action icon.
+ */
+ private Bitmap generatePhoneNumberIcon(Bitmap photo, int phoneType, int actionResId) {
+ final Resources r = mContext.getResources();
+ boolean drawPhoneOverlay = true;
+ final float scaleDensity = r.getDisplayMetrics().scaledDensity;
+
+ Bitmap phoneIcon = ((BitmapDrawable) r.getDrawable(actionResId)).getBitmap();
+
+ // If there isn't a photo use the generic phone action icon instead
+ if (photo == null) {
+ photo = phoneIcon;
+ drawPhoneOverlay = false;
+ }
+
+ // Setup the drawing classes
+ Bitmap icon = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(icon);
+
+ // Copy in the photo
+ Paint photoPaint = new Paint();
+ photoPaint.setDither(true);
+ photoPaint.setFilterBitmap(true);
+ Rect src = new Rect(0, 0, photo.getWidth(), photo.getHeight());
+ Rect dst = new Rect(0, 0, mIconSize, mIconSize);
+ canvas.drawBitmap(photo, src, dst, photoPaint);
+
+ // Create an overlay for the phone number type
+ String overlay = null;
+ switch (phoneType) {
+ case Phone.TYPE_HOME:
+ overlay = mContext.getString(R.string.type_short_home);
+ break;
+
+ case Phone.TYPE_MOBILE:
+ overlay = mContext.getString(R.string.type_short_mobile);
+ break;
+
+ case Phone.TYPE_WORK:
+ overlay = mContext.getString(R.string.type_short_work);
+ break;
+
+ case Phone.TYPE_PAGER:
+ overlay = mContext.getString(R.string.type_short_pager);
+ break;
+
+ case Phone.TYPE_OTHER:
+ overlay = mContext.getString(R.string.type_short_other);
+ break;
+ }
+
+ if (overlay != null) {
+ Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
+ textPaint.setTextSize(20.0f * scaleDensity);
+ textPaint.setTypeface(Typeface.DEFAULT_BOLD);
+ textPaint.setColor(r.getColor(R.color.textColorIconOverlay));
+ textPaint.setShadowLayer(3f, 1, 1, r.getColor(R.color.textColorIconOverlayShadow));
+ canvas.drawText(overlay, 2 * scaleDensity, 16 * scaleDensity, textPaint);
+ }
+
+ // Draw the phone action icon as an overlay
+ if (drawPhoneOverlay) {
+ src.set(0, 0, phoneIcon.getWidth(), phoneIcon.getHeight());
+ int iconWidth = icon.getWidth();
+ dst.set(iconWidth - ((int) (20 * scaleDensity)), -1,
+ iconWidth, ((int) (19 * scaleDensity)));
+ canvas.drawBitmap(phoneIcon, src, dst, photoPaint);
+ }
+
+ return icon;
+ }
}
diff --git a/src/com/android/contacts/util/Constants.java b/src/com/android/contacts/util/Constants.java
index e0178ad..433d54d 100644
--- a/src/com/android/contacts/util/Constants.java
+++ b/src/com/android/contacts/util/Constants.java
@@ -19,11 +19,6 @@
import android.app.Service;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-/**
- * Background {@link Service} that is used to keep our process alive long enough
- * for background threads to finish. Started and stopped directly by specific
- * background tasks when needed.
- */
public class Constants {
/**
* Specific MIME-type for {@link Phone#CONTENT_ITEM_TYPE} entries that