auto import from //branches/cupcake_rel/...@140373
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 012a33e..974fc05 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -166,19 +166,19 @@
String callText = null;
switch (callType) {
case Calls.INCOMING_TYPE:
- mCallTypeIcon.setImageResource(android.R.drawable.sym_call_incoming);
+ mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_incoming_call);
mCallType.setText(R.string.type_incoming);
callText = getString(R.string.callBack);
break;
case Calls.OUTGOING_TYPE:
- mCallTypeIcon.setImageResource(android.R.drawable.sym_call_outgoing);
+ mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_outgoing_call);
mCallType.setText(R.string.type_outgoing);
callText = getString(R.string.callAgain);
break;
case Calls.MISSED_TYPE:
- mCallTypeIcon.setImageResource(android.R.drawable.sym_call_missed);
+ mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_missed_call);
mCallType.setText(R.string.type_missed);
callText = getString(R.string.returnCall);
break;
diff --git a/src/com/android/contacts/ContactsGroupSyncSelector.java b/src/com/android/contacts/ContactsGroupSyncSelector.java
index 80b5166..30aec94 100644
--- a/src/com/android/contacts/ContactsGroupSyncSelector.java
+++ b/src/com/android/contacts/ContactsGroupSyncSelector.java
@@ -36,6 +36,8 @@
import android.widget.ArrayAdapter;
import android.widget.ListView;
+import java.util.ArrayList;
+
public final class ContactsGroupSyncSelector extends ListActivity implements View.OnClickListener {
private static final String[] PROJECTION = new String[] {
@@ -51,12 +53,12 @@
private static final int SUBACTIVITY_GET_ACCOUNT = 1;
- boolean[] mChecked;
+ ArrayList<Boolean> mChecked;
+ ArrayList<Long> mGroupIds;
boolean mSyncAllGroups;
- long[] mGroupIds;
private final class GroupsAdapter extends ArrayAdapter<CharSequence> {
- public GroupsAdapter(CharSequence[] items) {
+ public GroupsAdapter(ArrayList<CharSequence> items) {
super(ContactsGroupSyncSelector.this,
android.R.layout.simple_list_item_checked,
android.R.id.text1, items);
@@ -94,7 +96,7 @@
@Override
protected void onListItemClick(ListView list, View view, int position, long id) {
boolean isChecked = list.isItemChecked(position);
- mChecked[position] = isChecked;
+ mChecked.set(position, isChecked);
if (position == 0) {
mSyncAllGroups = isChecked;
adjustChecks();
@@ -127,11 +129,12 @@
Settings.setSetting(resolver, null, Settings.SYNC_EVERYTHING, "1");
} else {
ContentValues values = new ContentValues();
- int count = mChecked.length;
+ int count = mChecked.size();
for (int i = 1; i < count; i++) {
values.clear();
- values.put(Groups.SHOULD_SYNC, mChecked[i]);
- resolver.update(ContentUris.withAppendedId(Groups.CONTENT_URI, mGroupIds[i]),
+ values.put(Groups.SHOULD_SYNC, mChecked.get(i));
+ resolver.update(
+ ContentUris.withAppendedId(Groups.CONTENT_URI, mGroupIds.get(i)),
values, null, null);
}
// For now we only support a single account and the UI doesn't know what
@@ -189,33 +192,34 @@
Cursor cursor = resolver.query(Groups.CONTENT_URI, PROJECTION, null, null, Groups.NAME);
if (cursor != null) {
try {
- int count = cursor.getCount() + 1;
- CharSequence[] items = new String[count];
- boolean[] checked = new boolean[count];
- long[] groupIds = new long[count];
-
- int i = 0;
- items[i++] = getString(R.string.syncAllGroups);
- items[i++] = getString(R.string.groupNameMyContacts);
-
+ int count = cursor.getCount() + 1; // add 1 for "sync all"
+ ArrayList<CharSequence> items = new ArrayList<CharSequence>(count);
+ ArrayList<Boolean> checked = new ArrayList<Boolean>(count);
+ ArrayList<Long> groupIds = new ArrayList<Long>(count);
+
+ // The first item in the list is always "sync all"
+ items.add(getString(R.string.syncAllGroups));
+ checked.add(mSyncAllGroups);
+ groupIds.add(Long.valueOf(0)); // dummy entry
+
while (cursor.moveToNext()) {
String name = cursor.getString(COLUMN_INDEX_NAME);
String systemId = cursor.isNull(COLUMN_INDEX_SYSTEM_ID) ?
null : cursor.getString(COLUMN_INDEX_SYSTEM_ID);
if (systemId == null || !Groups.GROUP_MY_CONTACTS.equals(systemId)) {
- items[i] = name;
- checked[i] = cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0;
- groupIds[i] = cursor.getLong(COLUMN_INDEX_ID);
- i++;
+ items.add(name);
+ checked.add(cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0);
+ groupIds.add(cursor.getLong(COLUMN_INDEX_ID));
} else {
- checked[1] = cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0;
- groupIds[1] = cursor.getLong(COLUMN_INDEX_ID);
+ // If My Contacts is around it wants to be the second list entry
+ items.add(1, getString(R.string.groupNameMyContacts));
+ checked.add(1, cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0);
+ groupIds.add(1, cursor.getLong(COLUMN_INDEX_ID));
}
}
mChecked = checked;
- mSyncAllGroups = getShouldSyncEverything(resolver);
- checked[0] = mSyncAllGroups;
mGroupIds = groupIds;
+ mSyncAllGroups = getShouldSyncEverything(resolver);
// Setup the adapter
setListAdapter(new GroupsAdapter(items));
@@ -233,10 +237,10 @@
list.setItemChecked(i, true);
}
} else {
- boolean[] checked = mChecked;
+ ArrayList<Boolean> checked = mChecked;
int count = list.getCount();
for (int i = 0; i < count; i++) {
- list.setItemChecked(i, checked[i]);
+ list.setItemChecked(i, checked.get(i));
}
}
}
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index b9dc4f2..5ba0ec5 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -41,12 +41,12 @@
import android.preference.PreferenceManager;
import android.provider.Contacts;
import android.provider.Contacts.ContactMethods;
-import android.provider.Contacts.ContactMethodsColumns;
import android.provider.Contacts.Groups;
import android.provider.Contacts.Intents;
import android.provider.Contacts.People;
import android.provider.Contacts.Phones;
import android.provider.Contacts.Presence;
+import android.provider.Contacts.Intents.Insert;
import android.provider.Contacts.Intents.UI;
import android.text.TextUtils;
import android.util.Log;
@@ -70,6 +70,8 @@
import android.widget.SectionIndexer;
import android.widget.TextView;
+import static com.android.contacts.ShowOrCreateActivity.QUERY_KIND_EMAIL_OR_IM;
+
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -139,8 +141,8 @@
55 | MODE_MASK_PICKER | MODE_MASK_NO_PRESENCE | MODE_MASK_NO_FILTER;
/** Run a search query */
static final int MODE_QUERY = 60 | MODE_MASK_NO_FILTER;
- /** Show all contacts matching query, or handle special cases where 0 or 1 contacts found. */
- static final int MODE_SHOW_OR_CREATE_CONTACT = 65 | MODE_MASK_PICKER | MODE_MASK_NO_FILTER;
+ /** Run a search query in PICK mode, but that still launches to VIEW */
+ static final int MODE_QUERY_PICK_TO_VIEW = 65 | MODE_MASK_NO_FILTER | MODE_MASK_PICKER;
static final int DEFAULT_MODE = MODE_ALL_CONTACTS;
@@ -270,27 +272,13 @@
private Uri mGroupUri;
private boolean mJustCreated;
private boolean mSyncEnabled;
-
- /**
- * {@link Bundle} of extras to include when launching
- * {@link Intents.Insert#ACTION}, usually when responding to
- * {@link Intents#SHOW_OR_CREATE_CONTACT}.
- */
- private Bundle mCreateExtras;
-
- /**
- * Title to display to user when asking if a contact should be created,
- * usually the requested E-mail address or phone number when responding to a
- * {@link Intents#SHOW_OR_CREATE_CONTACT}.
- */
- private String mCreateData;
/**
* Cursor row index that holds reference back to {@link People#_ID}, such as
* {@link ContactMethods#PERSON_ID}. Used when responding to a
- * {@link Intents#SHOW_OR_CREATE_CONTACT}.
+ * {@link Intent#ACTION_SEARCH} in mode {@link #MODE_QUERY_PICK_TO_VIEW}.
*/
- private int mCreatePersonIndex;
+ private int mQueryPersonIdIndex;
/**
* Used to keep track of the scroll state of the list.
@@ -300,7 +288,22 @@
private boolean mCreateShortcut;
private boolean mDefaultMode = false;
+
+ /**
+ * Internal query type when in mode {@link #MODE_QUERY_PICK_TO_VIEW}.
+ */
+ private int mQueryMode = QUERY_MODE_NONE;
+ private static final int QUERY_MODE_NONE = -1;
+ private static final int QUERY_MODE_MAILTO = 1;
+ private static final int QUERY_MODE_TEL = 2;
+
+ /**
+ * Data to use when in mode {@link #MODE_QUERY_PICK_TO_VIEW}. Usually
+ * provided by scheme-specific part of incoming {@link Intent#getData()}.
+ */
+ private String mQueryData;
+
private class DeleteClickListener implements DialogInterface.OnClickListener {
private Uri mUri;
@@ -313,23 +316,6 @@
}
}
- private class IntentClickListener implements DialogInterface.OnClickListener {
- private Activity mParent;
- private Intent mIntent;
-
- public IntentClickListener(Activity parent, Intent intent) {
- mParent = parent;
- mIntent = intent;
- }
-
- public void onClick(DialogInterface dialog, int which) {
- if (mIntent != null) {
- mParent.startActivity(mIntent);
- }
- mParent.finish();
- }
- }
-
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -407,8 +393,20 @@
finish();
return;
}
- // Otherwise handle the more normal search case
- mMode = MODE_QUERY;
+
+ // See if search request has extras to specify query
+ if (intent.hasExtra(Insert.EMAIL)) {
+ mMode = MODE_QUERY_PICK_TO_VIEW;
+ mQueryMode = QUERY_MODE_MAILTO;
+ mQueryData = intent.getStringExtra(Insert.EMAIL);
+ } else if (intent.hasExtra(Insert.PHONE)) {
+ mMode = MODE_QUERY_PICK_TO_VIEW;
+ mQueryMode = QUERY_MODE_TEL;
+ mQueryData = intent.getStringExtra(Insert.PHONE);
+ } else {
+ // Otherwise handle the more normal search case
+ mMode = MODE_QUERY;
+ }
// Since this is the filter activity it receives all intents
// dispatched from the SearchManager for security reasons
@@ -436,8 +434,6 @@
startActivity(newIntent);
finish();
return;
- } else if (Intents.SHOW_OR_CREATE_CONTACT.equals(action)) {
- mMode = MODE_SHOW_OR_CREATE_CONTACT;
}
if (mMode == MODE_UNKNOWN) {
@@ -492,60 +488,6 @@
}
}
- /**
- * Handles special cases of the {@link Intents#SHOW_OR_CREATE_CONTACT}
- * intent. When zero results found, prompt user to create new contact. When
- * one contact found, shortcut to viewing that contact.
- *
- * @param c Valid cursor after performing query
- */
- private void handleShowOrCreate(final Cursor c) {
- int count = 0;
- long personId = 0;
- if (c != null) {
- count = c.getCount();
- if (count == 1 && c.moveToFirst()) {
- // Try reading ID for the only contact returned
- personId = c.getLong(mCreatePersonIndex);
- }
- }
-
- if (count == 1) {
- // If we only found one item, jump right to viewing it
- Intent showIntent = new Intent(Intent.ACTION_VIEW,
- ContentUris.withAppendedId(People.CONTENT_URI, personId));
- startActivity(showIntent);
- finish();
-
- } else if (count == 0) {
- // Insert create values coming from our request
- Intent createIntent = new Intent(Intent.ACTION_INSERT, People.CONTENT_URI);
- createIntent.putExtras(mCreateExtras);
-
- // Prompt user if they really want to start creating a new
- // contact. Skip this step if the caller requested {@link
- // Contacts#EXTRA_FORCE_CREATE}.
- boolean forceCreate = getIntent().getBooleanExtra(Intents.EXTRA_FORCE_CREATE, false);
-
- if (forceCreate) {
- startActivity(createIntent);
- finish();
- } else {
- CharSequence message = getResources().getString(
- R.string.add_contact_dlg_message_fmt, mCreateData);
-
- new AlertDialog.Builder(this)
- .setTitle(R.string.add_contact_dlg_title)
- .setMessage(message)
- .setPositiveButton(android.R.string.ok,
- new IntentClickListener(this, createIntent))
- .setNegativeButton(android.R.string.cancel,
- new IntentClickListener(this, null))
- .show();
- }
- }
- }
-
private void setEmptyText() {
TextView empty = (TextView) findViewById(R.id.emptyText);
// Center the text by default
@@ -1046,10 +988,10 @@
Intent intent = new Intent(Intent.ACTION_VIEW,
ContentUris.withAppendedId(People.CONTENT_URI, id));
startActivity(intent);
- } else if (mMode == MODE_SHOW_OR_CREATE_CONTACT) {
- // Figure out person ID because we might be using indirect cursor
+ } else if (mMode == MODE_QUERY_PICK_TO_VIEW) {
+ // Started with query that should launch to view contact
Cursor c = (Cursor) mAdapter.getItem(position);
- long personId = c.getLong(mCreatePersonIndex);
+ long personId = c.getLong(mQueryPersonIdIndex);
Intent intent = new Intent(Intent.ACTION_VIEW,
ContentUris.withAppendedId(People.CONTENT_URI, personId));
startActivity(intent);
@@ -1184,52 +1126,25 @@
break;
}
- case MODE_SHOW_OR_CREATE_CONTACT: {
- // Caller requested a specific E-mail address or phone number,
- // so show only matching entries. Once the query finishes we
- // handle edge cases of 0 or 1 items.
- Uri data = getIntent().getData();
- String scheme = null;
- String ssp = null;
- if (data != null) {
- scheme = data.getScheme();
- ssp = data.getSchemeSpecificPart();
- mCreateData = ssp;
- }
-
- mCreateExtras = new Bundle();
- Bundle originalExtras = getIntent().getExtras();
- if (originalExtras != null) {
- mCreateExtras.putAll(originalExtras);
- }
-
- if ("mailto".equals(scheme)) {
- mCreateExtras.putString(Intents.Insert.EMAIL, ssp);
- mCreatePersonIndex = CONTACT_METHODS_PERSON_ID_INDEX;
-
+ case MODE_QUERY_PICK_TO_VIEW: {
+ if (mQueryMode == QUERY_MODE_MAILTO) {
+ mQueryPersonIdIndex = CONTACT_METHODS_PERSON_ID_INDEX;
mQueryHandler.startQuery(QUERY_TOKEN, null,
ContactMethods.CONTENT_URI, CONTACT_METHODS_PROJECTION,
- ContactMethodsColumns.KIND + "=" + Contacts.KIND_EMAIL + " AND " +
- ContactMethods.DATA + "=?", new String[] { ssp },
+ QUERY_KIND_EMAIL_OR_IM + " AND " + ContactMethods.DATA + "=?",
+ new String[] { mQueryData },
getSortOrder(CONTACT_METHODS_PROJECTION));
- } else if ("tel".equals(scheme)) {
- mCreateExtras.putString(Intents.Insert.PHONE, ssp);
- mCreatePersonIndex = PHONES_PERSON_ID_INDEX;
-
+ } else if (mQueryMode == QUERY_MODE_TEL) {
+ mQueryPersonIdIndex = PHONES_PERSON_ID_INDEX;
mQueryHandler.startQuery(QUERY_TOKEN, null,
- Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, ssp),
+ Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, mQueryData),
PHONES_PROJECTION, null, null,
getSortOrder(PHONES_PROJECTION));
-
- } else {
- Log.w(TAG, "Invalid intent:" + getIntent());
- finish();
}
-
break;
}
-
+
case MODE_STARRED:
mQueryHandler.startQuery(QUERY_TOKEN, null, People.CONTENT_URI,
CONTACTS_PROJECTION,
@@ -1413,7 +1328,6 @@
getString(R.string.groupNameWithPhones));
prefStrings.add(GROUP_WITH_PHONES);
- int i = 3;
int currentIndex = DISPLAY_GROUP_INDEX_ALL_CONTACTS;
while (cursor.moveToNext()) {
String systemId = cursor.getString(GROUPS_COLUMN_INDEX_SYSTEM_ID);
@@ -1423,9 +1337,8 @@
// All groups that aren't My Contacts, since that one is localized on the phone
groups.add(name);
if (name.equals(mDisplayInfo)) {
- currentIndex = i;
+ currentIndex = groups.size() - 1;
}
- i++;
} else {
// The My Contacts group
groups.add(DISPLAY_GROUP_INDEX_MY_CONTACTS,
@@ -1443,8 +1356,7 @@
currentIndex = DISPLAY_GROUP_INDEX_ALL_CONTACTS_WITH_PHONES;
}
mDisplayGroups = groups.toArray(new CharSequence[groups.size()]);
- builder.setSingleChoiceItems(mDisplayGroups,
- currentIndex, this);
+ builder.setSingleChoiceItems(mDisplayGroups, currentIndex, this);
mDisplayGroupOriginalSelection = currentIndex;
} finally {
cursor.close();
@@ -1467,11 +1379,6 @@
activity.getListView().clearTextFilter();
activity.mAdapter.changeCursor(cursor);
- // Handle SHOW_OR_CREATE now that we have valid cursor
- if (activity.mMode == MODE_SHOW_OR_CREATE_CONTACT) {
- activity.handleShowOrCreate(cursor);
- }
-
// Now that the cursor is populated again, it's possible to restore the list state
if (activity.mListState != null) {
activity.mList.onRestoreInstanceState(activity.mListState);
diff --git a/src/com/android/contacts/RecentCallsListActivity.java b/src/com/android/contacts/RecentCallsListActivity.java
index dbf2879..8949f6e 100644
--- a/src/com/android/contacts/RecentCallsListActivity.java
+++ b/src/com/android/contacts/RecentCallsListActivity.java
@@ -114,17 +114,11 @@
private static final int QUERY_TOKEN = 53;
private static final int UPDATE_TOKEN = 54;
- private RecentCallsAdapter mAdapter;
+ RecentCallsAdapter mAdapter;
private QueryHandler mQueryHandler;
- private String mVoiceMailNumber;
+ String mVoiceMailNumber;
- private CharSequence[] mLabelArray;
-
- private Drawable mDrawableIncoming;
- private Drawable mDrawableOutgoing;
- private Drawable mDrawableMissed;
-
- private static final class ContactInfo {
+ static final class ContactInfo {
public long personId;
public String name;
public int type;
@@ -136,13 +130,14 @@
public static final class RecentCallsListItemViews {
TextView line1View;
- TextView line2View;
- TextView durationView;
+ TextView labelView;
+ TextView numberView;
TextView dateView;
ImageView iconView;
+ View callView;
}
- private static final class CallerInfoQuery {
+ static final class CallerInfoQuery {
String number;
int position;
String name;
@@ -151,8 +146,8 @@
}
/** Adapter class to fill in data for the Call Log */
- private final class RecentCallsAdapter extends ResourceCursorAdapter
- implements Runnable, ViewTreeObserver.OnPreDrawListener {
+ final class RecentCallsAdapter extends ResourceCursorAdapter
+ implements Runnable, ViewTreeObserver.OnPreDrawListener, View.OnClickListener {
HashMap<String,ContactInfo> mContactInfo;
private final LinkedList<CallerInfoQuery> mRequests;
private volatile boolean mDone;
@@ -163,6 +158,20 @@
private boolean mFirst;
private Thread mCallerIdThread;
+ private CharSequence[] mLabelArray;
+
+ private Drawable mDrawableIncoming;
+ private Drawable mDrawableOutgoing;
+ private Drawable mDrawableMissed;
+
+ public void onClick(View view) {
+ String number = (String) view.getTag();
+ if (!TextUtils.isEmpty(number)) {
+ Uri telUri = Uri.fromParts("tel", number, null);
+ startActivity(new Intent(Intent.ACTION_CALL_PRIVILEGED, telUri));
+ }
+ }
+
public boolean onPreDraw() {
if (mFirst) {
mHandler.sendEmptyMessageDelayed(START_THREAD, 1000);
@@ -191,6 +200,14 @@
mContactInfo = new HashMap<String,ContactInfo>();
mRequests = new LinkedList<CallerInfoQuery>();
mPreDrawListener = null;
+
+ mDrawableIncoming = getResources().getDrawable(
+ R.drawable.ic_call_log_list_incoming_call);
+ mDrawableOutgoing = getResources().getDrawable(
+ R.drawable.ic_call_log_list_outgoing_call);
+ mDrawableMissed = getResources().getDrawable(
+ R.drawable.ic_call_log_list_missed_call);
+ mLabelArray = getResources().getTextArray(com.android.internal.R.array.phoneTypes);
}
void setLoading(boolean loading) {
@@ -331,11 +348,13 @@
// Get the views to bind to
RecentCallsListItemViews views = new RecentCallsListItemViews();
views.line1View = (TextView) view.findViewById(R.id.line1);
- views.line2View = (TextView) view.findViewById(R.id.line2);
- views.durationView = (TextView) view.findViewById(R.id.duration);
+ views.labelView = (TextView) view.findViewById(R.id.label);
+ views.numberView = (TextView) view.findViewById(R.id.number);
views.dateView = (TextView) view.findViewById(R.id.date);
views.iconView = (ImageView) view.findViewById(R.id.call_type_icon);
-
+ views.callView = view.findViewById(R.id.call_icon);
+ views.callView.setOnClickListener(this);
+
view.setTag(views);
return view;
@@ -350,6 +369,9 @@
String callerName = c.getString(CALLER_NAME_COLUMN_INDEX);
int callerNumberType = c.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
String callerNumberLabel = c.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
+
+ // Store away the number so we can call it directly if you click on the call icon
+ views.callView.setTag(number);
// Lookup contacts with this number
ContactInfo info = mContactInfo.get(number);
@@ -387,32 +409,24 @@
// Set the text lines
if (!TextUtils.isEmpty(name)) {
views.line1View.setText(name);
+ views.labelView.setVisibility(View.VISIBLE);
CharSequence numberLabel = Phones.getDisplayLabel(context, ntype, label,
mLabelArray);
+ views.numberView.setVisibility(View.VISIBLE);
+ views.numberView.setText(number);
if (!TextUtils.isEmpty(numberLabel)) {
- views.line2View.setText(numberLabel);
+ views.labelView.setText(numberLabel);
+ views.labelView.setVisibility(View.VISIBLE);
} else {
- views.line2View.setText(number);
+ views.labelView.setVisibility(View.GONE);
}
-
- // Set the presence icon
-/*
- int serverStatus;
- if (!c.isNull(SERVER_STATUS_COLUMN_INDEX)) {
- serverStatus = c.getInt(SERVER_STATUS_COLUMN_INDEX);
- views.line2View.setCompoundDrawablesWithIntrinsicBounds(
- getResources().getDrawable(
- Presence.getPresenceIconResourceId(serverStatus)),
- null, null, null);
- } else {
- views.line2View.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
- }
-*/
} else {
if (number.equals(CallerInfo.UNKNOWN_NUMBER)) {
number = getString(R.string.unknown);
} else if (number.equals(CallerInfo.PRIVATE_NUMBER)) {
number = getString(R.string.private_num);
+ } else if (number.equals(CallerInfo.PAYPHONE_NUMBER)) {
+ number = getString(R.string.payphone);
} else if (number.equals(mVoiceMailNumber)) {
number = getString(R.string.voicemail);
} else {
@@ -421,29 +435,18 @@
}
views.line1View.setText(number);
- views.line2View.setText(null);
-
- // Clear the presence icon
-// views.line2View.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
+ views.numberView.setVisibility(View.GONE);
+ views.labelView.setVisibility(View.GONE);
}
int type = c.getInt(CALL_TYPE_COLUMN_INDEX);
long date = c.getLong(DATE_COLUMN_INDEX);
- // Set the duration
- if (type == Calls.MISSED_TYPE) {
- views.durationView.setVisibility(View.GONE);
- } else {
- views.durationView.setVisibility(View.VISIBLE);
- views.durationView.setText(DateUtils.formatElapsedTime(c.getLong(DURATION_COLUMN_INDEX)));
- }
-
// Set the date/time field by mixing relative and absolute times.
- int flags = DateUtils.FORMAT_ABBREV_RELATIVE | DateUtils.FORMAT_SHOW_DATE
- | DateUtils.FORMAT_ABBREV_MONTH;
+ int flags = DateUtils.FORMAT_ABBREV_RELATIVE;
- views.dateView.setText(DateUtils.getRelativeDateTimeString(context, date,
- DateUtils.MINUTE_IN_MILLIS, DateUtils.DAY_IN_MILLIS * 2, flags));
+ views.dateView.setText(DateUtils.getRelativeTimeSpanString(date,
+ System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, flags));
// Set the icon
switch (type) {
@@ -459,6 +462,7 @@
views.iconView.setImageDrawable(mDrawableMissed);
break;
}
+
// Listen for the first draw
if (mPreDrawListener == null) {
mFirst = true;
@@ -496,11 +500,6 @@
setContentView(R.layout.recent_calls);
- mDrawableIncoming = getResources().getDrawable(android.R.drawable.sym_call_incoming);
- mDrawableOutgoing = getResources().getDrawable(android.R.drawable.sym_call_outgoing);
- mDrawableMissed = getResources().getDrawable(android.R.drawable.sym_call_missed);
- mLabelArray = getResources().getTextArray(com.android.internal.R.array.phoneTypes);
-
// Typing here goes to the dialer
setDefaultKeyMode(DEFAULT_KEYS_DIALER);
@@ -616,6 +615,8 @@
number = getString(R.string.unknown);
} else if (number.equals(CallerInfo.PRIVATE_NUMBER)) {
number = getString(R.string.private_num);
+ } else if (number.equals(CallerInfo.PAYPHONE_NUMBER)) {
+ number = getString(R.string.payphone);
} else if (number.equals(mVoiceMailNumber)) {
number = getString(R.string.voicemail);
numberUri = Uri.parse("voicemail:x");
@@ -799,7 +800,8 @@
String number = cursor.getString(NUMBER_COLUMN_INDEX);
if (TextUtils.isEmpty(number)
|| number.equals(CallerInfo.UNKNOWN_NUMBER)
- || number.equals(CallerInfo.PRIVATE_NUMBER)) {
+ || number.equals(CallerInfo.PRIVATE_NUMBER)
+ || number.equals(CallerInfo.PAYPHONE_NUMBER)) {
// This number can't be called, do nothing
return;
}
diff --git a/src/com/android/contacts/ShowOrCreateActivity.java b/src/com/android/contacts/ShowOrCreateActivity.java
new file mode 100755
index 0000000..8d3cf0b
--- /dev/null
+++ b/src/com/android/contacts/ShowOrCreateActivity.java
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ */
+
+package com.android.contacts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.AsyncQueryHandler;
+import android.content.ComponentName;
+import android.content.ContentUris;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Contacts;
+import android.provider.Contacts.ContactMethods;
+import android.provider.Contacts.ContactMethodsColumns;
+import android.provider.Contacts.Intents;
+import android.provider.Contacts.People;
+import android.provider.Contacts.Phones;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Handle several edge cases around showing or possibly creating contacts in
+ * connected with a specific E-mail address or phone number. Will search based
+ * on incoming {@link Intent#getData()} as described by
+ * {@link Intents#SHOW_OR_CREATE_CONTACT}.
+ * <ul>
+ * <li>If no matching contacts found, will prompt user with dialog to add to a
+ * contact, then will use {@link Intent#ACTION_INSERT_OR_EDIT} to let create new
+ * contact or edit new data into an existing one.
+ * <li>If one matching contact found, directly show {@link Intent#ACTION_VIEW}
+ * that specific contact.
+ * <li>If more than one matching found, show list of matching contacts using
+ * {@link Intent#ACTION_SEARCH}.
+ * </ul>
+ */
+public final class ShowOrCreateActivity extends Activity {
+ static final String TAG = "ShowOrCreateActivity";
+ static final boolean LOGD = false;
+
+ static final String[] PHONES_PROJECTION = new String[] {
+ Phones._ID,
+ Phones.PERSON_ID,
+ };
+
+ static final String[] CONTACT_METHODS_PROJECTION = new String[] {
+ ContactMethods._ID,
+ ContactMethods.PERSON_ID,
+ };
+
+ static final String SCHEME_MAILTO = "mailto";
+ static final String SCHEME_TEL = "tel";
+
+ static final int ID_INDEX = 0;
+ static final int PERSON_ID_INDEX = 1;
+
+ /**
+ * Query clause to filter {@link ContactMethods#CONTENT_URI} to only search
+ * {@link Contacts#KIND_EMAIL} or {@link Contacts#KIND_IM}.
+ */
+ static final String QUERY_KIND_EMAIL_OR_IM = ContactMethodsColumns.KIND +
+ " IN (" + Contacts.KIND_EMAIL + "," + Contacts.KIND_IM + ")";
+
+ static final int QUERY_TOKEN = 42;
+
+ private QueryHandler mQueryHandler;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Create handler if doesn't exist, otherwise cancel any running
+ if (mQueryHandler == null) {
+ mQueryHandler = new QueryHandler(this);
+ } else {
+ mQueryHandler.cancelOperation(QUERY_TOKEN);
+ }
+
+ final Intent intent = getIntent();
+ final Uri data = intent.getData();
+
+ // Unpack scheme and target data from intent
+ String scheme = null;
+ String ssp = null;
+ if (data != null) {
+ scheme = data.getScheme();
+ ssp = data.getSchemeSpecificPart();
+ }
+
+ // Build set of extras for possible use when creating contact
+ Bundle createExtras = new Bundle();
+ Bundle originalExtras = intent.getExtras();
+ if (originalExtras != null) {
+ createExtras.putAll(originalExtras);
+ }
+ mQueryHandler.setCreateExtras(createExtras);
+
+ // Read possible extra with specific title
+ String createDescrip = intent.getStringExtra(Intents.EXTRA_CREATE_DESCRIPTION);
+ if (createDescrip == null) {
+ createDescrip = ssp;
+ }
+ mQueryHandler.setCreateDescription(createDescrip);
+
+ // Allow caller to bypass dialog prompt
+ boolean createForce = intent.getBooleanExtra(Intents.EXTRA_FORCE_CREATE, false);
+ mQueryHandler.setCreateForce(createForce);
+
+ // Handle specific query request
+ if (SCHEME_MAILTO.equals(scheme)) {
+ createExtras.putString(Intents.Insert.EMAIL, ssp);
+ mQueryHandler.startQuery(QUERY_TOKEN, null,
+ ContactMethods.CONTENT_URI, CONTACT_METHODS_PROJECTION,
+ QUERY_KIND_EMAIL_OR_IM + " AND " + ContactMethods.DATA + "=?",
+ new String[] { ssp }, null);
+
+ } else if (SCHEME_TEL.equals(scheme)) {
+ createExtras.putString(Intents.Insert.PHONE, ssp);
+ mQueryHandler.startQuery(QUERY_TOKEN, null,
+ Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, ssp),
+ PHONES_PROJECTION, null, null, null);
+
+ } else {
+ Log.w(TAG, "Invalid intent:" + getIntent());
+ finish();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (mQueryHandler != null) {
+ mQueryHandler.cancelOperation(QUERY_TOKEN);
+ }
+ }
+
+ /**
+ * Listener for {@link DialogInterface} that launches a given {@link Intent}
+ * when clicked. When clicked, this also closes the parent using
+ * {@link Activity#finish()}.
+ */
+ private static class IntentClickListener implements DialogInterface.OnClickListener {
+ private Activity mParent;
+ private Intent mIntent;
+
+ /**
+ * @param parent {@link Activity} to use for launching target.
+ * @param intent Target {@link Intent} to launch when clicked.
+ */
+ public IntentClickListener(Activity parent, Intent intent) {
+ mParent = parent;
+ mIntent = intent;
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (mIntent != null) {
+ mParent.startActivity(mIntent);
+ }
+ mParent.finish();
+ }
+ }
+
+ /**
+ * Handle asynchronous query to find matching contacts. When query finishes,
+ * will handle based on number of matching contacts found.
+ */
+ private static final class QueryHandler extends AsyncQueryHandler {
+ private final WeakReference<Activity> mActivity;
+ private Bundle mCreateExtras;
+ private String mCreateDescrip;
+ private boolean mCreateForce;
+
+ public QueryHandler(Activity activity) {
+ super(activity.getContentResolver());
+ mActivity = new WeakReference<Activity>(activity);
+ }
+
+ public void setCreateExtras(Bundle createExtras) {
+ mCreateExtras = createExtras;
+ }
+
+ public void setCreateDescription(String createDescrip) {
+ mCreateDescrip = createDescrip;
+ }
+
+ public void setCreateForce(boolean createForce) {
+ mCreateForce = createForce;
+ }
+
+ @Override
+ protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ Activity activity = mActivity.get();
+ if (activity == null) {
+ return;
+ }
+
+ // Count contacts found by query
+ int count = 0;
+ long personId = -1;
+ if (cursor != null) {
+ try {
+ count = cursor.getCount();
+ if (count == 1 && cursor.moveToFirst()) {
+ // Try reading ID if only one contact returned
+ personId = cursor.getLong(PERSON_ID_INDEX);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ if (LOGD) Log.d(TAG, "onQueryComplete count=" + count);
+
+ if (count == 1) {
+ // If we only found one item, jump right to viewing it
+ Intent viewIntent = new Intent(Intent.ACTION_VIEW,
+ ContentUris.withAppendedId(People.CONTENT_URI, personId));
+ activity.startActivity(viewIntent);
+ activity.finish();
+
+ } else if (count > 1) {
+ // If more than one, show pick list
+ Intent listIntent = new Intent(Intent.ACTION_SEARCH);
+ listIntent.setComponent(new ComponentName(activity, ContactsListActivity.class));
+ listIntent.putExtras(mCreateExtras);
+ activity.startActivity(listIntent);
+ activity.finish();
+
+ } else {
+ // No matching contacts found
+ if (mCreateForce) {
+ // Forced to create new contact
+ Intent createIntent = new Intent(Intent.ACTION_INSERT, People.CONTENT_URI);
+ createIntent.putExtras(mCreateExtras);
+ createIntent.setType(People.CONTENT_TYPE);
+
+ activity.startActivity(createIntent);
+ activity.finish();
+
+ } else {
+ // Prompt user to insert or edit contact
+ Intent createIntent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ createIntent.putExtras(mCreateExtras);
+ createIntent.setType(People.CONTENT_ITEM_TYPE);
+
+ CharSequence message = activity.getResources().getString(
+ R.string.add_contact_dlg_message_fmt, mCreateDescrip);
+
+ new AlertDialog.Builder(activity)
+ .setTitle(R.string.add_contact_dlg_title)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok,
+ new IntentClickListener(activity, createIntent))
+ .setNegativeButton(android.R.string.cancel,
+ new IntentClickListener(activity, null))
+ .show();
+ }
+ }
+ }
+ }
+}