am 333a615d: Implement call and SMS shortcuts.
Merge commit '333a615d1e6ced4560f4803510e673bae87d0ca2'
* commit '333a615d1e6ced4560f4803510e673bae87d0ca2':
Implement call and SMS shortcuts.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e4fd510..fb734c4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -246,6 +246,30 @@
</activity-alias>
+ <activity-alias android:name="alias.DialShortcut"
+ android:targetActivity="ContactsListActivity"
+ android:label="@string/shortcutDialContact"
+ android:icon="@drawable/ic_launcher_shortcut_contact">
+
+ <intent-filter>
+ <action android:name="android.intent.action.CREATE_SHORTCUT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+
+ </activity-alias>
+
+ <activity-alias android:name="alias.MessageShortcut"
+ android:targetActivity="ContactsListActivity"
+ android:label="@string/shortcutMessageContact"
+ android:icon="@drawable/ic_launcher_shortcut_contact">
+
+ <intent-filter>
+ <action android:name="android.intent.action.CREATE_SHORTCUT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+
+ </activity-alias>
+
<activity android:name="CallDetailActivity"
android:label="@string/callDetailTitle"
android:theme="@style/TallTitleBarTheme"
diff --git a/res/drawable-finger/badge_action_call.png b/res/drawable-finger/badge_action_call.png
new file mode 100644
index 0000000..3bc88a3
--- /dev/null
+++ b/res/drawable-finger/badge_action_call.png
Binary files differ
diff --git a/res/drawable-finger/badge_action_sms.png b/res/drawable-finger/badge_action_sms.png
new file mode 100644
index 0000000..bbcfb59
--- /dev/null
+++ b/res/drawable-finger/badge_action_sms.png
Binary files differ
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644
index 0000000..fb4019d
--- /dev/null
+++ b/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <color name="textColorIconOverlay">#fff</color>
+ <color name="textColorIconOverlayShadow">#000</color>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4442086..6eff5b4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -27,6 +27,23 @@
This shows up in a list of things like bookmark, folder, music playlist, etc -->
<string name="shortcutContact">Contact</string>
+ <!-- Name of activity that allows users to create shortcuts on the home screen to dial a contact.
+ This shows up in a list of things like bookmark, folder, music playlist, etc -->
+ <string name="shortcutDialContact">Direct Dial</string>
+
+ <!-- Name of activity that allows users to create shortcuts on the home screen to message (SMS) a contact.
+ This shows up in a list of things like bookmark, folder, music playlist, etc -->
+ <string name="shortcutMessageContact">Direct Message</string>
+
+ <!-- Activity title when the user is selecting a contact for a shortcut. -->
+ <string name="shortcutActivityTitle">Choose a contact shortcut</string>
+
+ <!-- Activity title when the user is selecting a contact for a direct dial shortcut. -->
+ <string name="callShortcutActivityTitle">Choose a number to call</string>
+
+ <!-- Activity title when the user is selecting a contact for a direct message shortcut. -->
+ <string name="messageShortcutActivityTitle">Choose a number to message</string>
+
<!-- Title for the activity that shows only starred contacts -->
<string name="starredList">Starred</string>
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index d97c27d..e5143e0 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -30,10 +30,17 @@
import android.content.ISyncAdapter;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.database.CharArrayBuffer;
import android.database.Cursor;
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;
@@ -83,6 +90,8 @@
implements View.OnCreateContextMenuListener, DialogInterface.OnClickListener {
private static final String TAG = "ContactsListActivity";
+ private static final boolean ENABLE_ACTION_ICON_OVERLAYS = false;
+
private static final String LIST_STATE_KEY = "liststate";
private static final String FOCUS_KEY = "focused";
@@ -291,7 +300,7 @@
private Parcelable mListState = null;
private boolean mListHasFocus;
- private boolean mCreateShortcut;
+ private String mShortcutAction;
private boolean mDefaultMode = false;
/**
@@ -401,8 +410,19 @@
mMode = MODE_PICK_POSTAL;
}
} else if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
- mMode = MODE_PICK_OR_CREATE_CONTACT;
- mCreateShortcut = true;
+ if (intent.getComponent().getClassName().equals("alias.DialShortcut")) {
+ mMode = MODE_PICK_PHONE;
+ mShortcutAction = Intent.ACTION_CALL;
+ setTitle(R.string.callShortcutActivityTitle);
+ } else if (intent.getComponent().getClassName().equals("alias.MessageShortcut")) {
+ mMode = MODE_PICK_PHONE;
+ mShortcutAction = Intent.ACTION_SENDTO;
+ setTitle(R.string.messageShortcutActivityTitle);
+ } else {
+ mMode = MODE_PICK_OR_CREATE_CONTACT;
+ mShortcutAction = Intent.ACTION_VIEW;
+ setTitle(R.string.shortcutActivityTitle);
+ }
} else if (Intent.ACTION_GET_CONTENT.equals(action)) {
final String type = intent.resolveType(this);
if (People.CONTENT_ITEM_TYPE.equals(type)) {
@@ -881,8 +901,8 @@
case SUBACTIVITY_NEW_CONTACT:
if (resultCode == RESULT_OK) {
// Contact was created, pass it back
- returnPickerResult(data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME),
- data.getData());
+ returnPickerResult(null, data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME),
+ data.getData(), 0);
}
}
}
@@ -1066,18 +1086,22 @@
} else if (mMode == MODE_PICK_CONTACT
|| mMode == MODE_PICK_OR_CREATE_CONTACT) {
Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, id);
- if (mCreateShortcut) {
+ if (mShortcutAction != null) {
// Subtract one if we have Create Contact at the top
Cursor c = (Cursor) mAdapter.getItem(position
- (mMode == MODE_PICK_OR_CREATE_CONTACT? 1:0));
- returnPickerResult(c.getString(NAME_COLUMN_INDEX), uri);
+ returnPickerResult(c, c.getString(NAME_COLUMN_INDEX), uri, id);
} else {
- returnPickerResult(null, uri);
+ returnPickerResult(null, null, uri, id);
}
} else if (mMode == MODE_PICK_PHONE) {
- setResult(RESULT_OK, new Intent().setData(
- ContentUris.withAppendedId(Phones.CONTENT_URI, id)));
- finish();
+ Uri uri = ContentUris.withAppendedId(Phones.CONTENT_URI, id);
+ if (mShortcutAction != null) {
+ Cursor c = (Cursor) mAdapter.getItem(position);
+ returnPickerResult(c, c.getString(NAME_COLUMN_INDEX), uri, id);
+ } else {
+ returnPickerResult(null, null, uri, id);
+ }
} else if (mMode == MODE_PICK_POSTAL) {
setResult(RESULT_OK, new Intent().setData(
ContentUris.withAppendedId(ContactMethods.CONTENT_URI, id)));
@@ -1092,22 +1116,47 @@
}
}
- private void returnPickerResult(String name, Uri uri) {
+ private void returnPickerResult(Cursor c, String name, Uri uri, long id) {
final Intent intent = new Intent();
- if (mCreateShortcut) {
- Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, uri);
+ if (mShortcutAction != null) {
+ Intent shortcutIntent;
+ if (Intent.ACTION_VIEW.equals(mShortcutAction)) {
+ // This is a simple shortcut to view a contact.
+ shortcutIntent = new Intent(mShortcutAction, uri);
+ final Bitmap icon = People.loadContactPhoto(this, uri, 0, null);
+ if (icon != null) {
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, 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(DATA_COLUMN_INDEX);
+ int type = c.getInt(TYPE_COLUMN_INDEX);
+ String scheme;
+ int resid;
+ if (Intent.ACTION_CALL.equals(mShortcutAction)) {
+ scheme = "tel";
+ resid = R.drawable.badge_action_call;
+ } else {
+ 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);
+
+ Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, id);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON,
+ generatePhoneNumberIcon(personUri, type, resid));
+
+ }
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
- final Bitmap icon = People.loadContactPhoto(this, uri, 0, null);
- if (icon != null) {
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
- } else {
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
- Intent.ShortcutIconResource.fromContext(this,
- R.drawable.ic_launcher_shortcut_contact));
- }
setResult(RESULT_OK, intent);
} else {
setResult(RESULT_OK, intent.setData(uri));
@@ -1115,6 +1164,107 @@
finish();
}
+ /**
+ * 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 personUri 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 personUri, int type, int actionResId) {
+ final Resources r = getResources();
+ boolean drawPhoneOverlay = true;
+
+ Bitmap photo = People.loadContactPhoto(this, personUri, 0, 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
+ int iconSize = (int) r.getDimension(android.R.dimen.app_icon_size);
+ Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, 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, iconSize,iconSize);
+ canvas.drawBitmap(photo, src, dst, photoPaint);
+
+ // Create an overlay for the phone number type
+ String overlay = null;
+ switch (type) {
+ case Phones.TYPE_HOME:
+ overlay = "H";
+ break;
+
+ case Phones.TYPE_MOBILE:
+ overlay = "M";
+ break;
+
+ case Phones.TYPE_WORK:
+ overlay = "W";
+ break;
+
+ case Phones.TYPE_PAGER:
+ overlay = "P";
+ break;
+
+ case Phones.TYPE_OTHER:
+ overlay = "O";
+ break;
+ }
+ if (overlay != null) {
+ Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
+ textPaint.setTextSize(20.0f);
+ 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, 16, 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 - 20, -1, iconWidth, 19);
+ canvas.drawBitmap(phoneIcon, src, dst, photoPaint);
+ }
+ }
+
+ return icon;
+ }
+
+ /**
+ * 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;
+ }
+ }
+
String[] getProjection() {
switch (mMode) {
case MODE_GROUP: