Merge "Extract the full telephone number from the tel: URL." into eclair-mr2
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index 24f683f..a277744 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -17,6 +17,9 @@
package com.android.contacts;
+import com.android.contacts.model.ContactsSource;
+import com.android.contacts.util.Constants;
+
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -36,7 +39,6 @@
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.Im.ProviderNames;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.view.LayoutInflater;
@@ -45,9 +47,6 @@
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.util.Constants;
-
import java.util.ArrayList;
public class ContactsUtils {
@@ -191,6 +190,19 @@
return photoBm;
}
+ // TODO find a proper place for the canonical version of these
+ public interface ProviderNames {
+ String YAHOO = "Yahoo";
+ String GTALK = "GTalk";
+ String MSN = "MSN";
+ String ICQ = "ICQ";
+ String AIM = "AIM";
+ String XMPP = "XMPP";
+ String JABBER = "JABBER";
+ String SKYPE = "SKYPE";
+ String QQ = "QQ";
+ }
+
/**
* This looks up the provider name defined in
* {@link android.provider.Im.ProviderNames} from the predefined IM protocol id.
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index eb5aec5..2aeb34d 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -59,6 +59,7 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.RawContactsEntity;
import android.provider.ContactsContract.StatusUpdates;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Im;
@@ -297,31 +298,27 @@
return null;
}
- // QUERY CODE //
/** {@inheritDoc} */
- public void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator) {
- try {
- // Read incoming entities and consider binding
- readEntities(iterator);
- considerBindData();
- } finally {
- if (iterator != null) {
+ public void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ if (token == TOKEN_STATUSES) {
+ try {
+ // Read available social rows and consider binding
+ readStatuses(cursor);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ } else {
+ EntityIterator iterator = RawContacts.newEntityIterator(cursor);
+ try {
+ // Read incoming entities and consider binding
+ readEntities(iterator);
+ } finally {
iterator.close();
}
}
- }
-
- /** {@inheritDoc} */
- public void onQueryComplete(int token, Object cookie, Cursor cursor) {
- try {
- // Read available social rows and consider binding
- readStatuses(cursor);
- considerBindData();
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
+ considerBindData();
}
private long getRefreshedContactId() {
@@ -399,7 +396,7 @@
mHasEntities = false;
mHasStatuses = false;
- mHandler.startQueryEntities(TOKEN_ENTITIES, null, RawContacts.CONTENT_URI,
+ mHandler.startQuery(TOKEN_ENTITIES, null, RawContactsEntity.CONTENT_URI, null,
RawContacts.CONTACT_ID + "=" + contactId, null, null);
mHandler.startQuery(TOKEN_STATUSES, null, dataUri, StatusQuery.PROJECTION,
StatusUpdates.PRESENCE + " IS NOT NULL OR " + StatusUpdates.STATUS
diff --git a/src/com/android/contacts/model/EntitySet.java b/src/com/android/contacts/model/EntitySet.java
index be2f70f..ac53611 100644
--- a/src/com/android/contacts/model/EntitySet.java
+++ b/src/com/android/contacts/model/EntitySet.java
@@ -21,15 +21,13 @@
import android.content.Entity;
import android.content.EntityIterator;
import android.content.ContentProviderOperation.Builder;
-import android.graphics.BitmapFactory;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.RawContactsEntity;
import com.google.android.collect.Lists;
@@ -65,26 +63,24 @@
*/
public static EntitySet fromQuery(ContentResolver resolver, String selection,
String[] selectionArgs, String sortOrder) {
- EntityIterator iterator = null;
- final EntitySet state = new EntitySet();
+ EntityIterator iterator = RawContacts.newEntityIterator(resolver.query(
+ RawContactsEntity.CONTENT_URI, null, selection, selectionArgs,
+ sortOrder));
try {
+ final EntitySet state = new EntitySet();
// Perform background query to pull contact details
- iterator = resolver.queryEntities(RawContacts.CONTENT_URI, selection, selectionArgs,
- sortOrder);
while (iterator.hasNext()) {
// Read all contacts into local deltas to prepare for edits
final Entity before = iterator.next();
final EntityDelta entity = EntityDelta.fromBefore(before);
state.add(entity);
}
+ return state;
} catch (RemoteException e) {
throw new IllegalStateException("Problem querying contact details", e);
} finally {
- if (iterator != null) {
- iterator.close();
- }
+ iterator.close();
}
- return state;
}
/**
diff --git a/src/com/android/contacts/ui/DisplayGroupsActivity.java b/src/com/android/contacts/ui/DisplayGroupsActivity.java
index 9ac46ce..16af321 100644
--- a/src/com/android/contacts/ui/DisplayGroupsActivity.java
+++ b/src/com/android/contacts/ui/DisplayGroupsActivity.java
@@ -379,30 +379,29 @@
mName = accountName;
mType = accountType;
- boolean hasGroups = false;
-
final Uri groupsUri = Groups.CONTENT_URI.buildUpon()
.appendQueryParameter(Groups.ACCOUNT_NAME, accountName)
.appendQueryParameter(Groups.ACCOUNT_TYPE, accountType).build();
- EntityIterator iterator = null;
+ EntityIterator iterator = ContactsContract.Groups.newEntityIterator(resolver.query(
+ groupsUri, null, null, null, null));
try {
+ boolean hasGroups = false;
+
// Create entries for each known group
- iterator = resolver.queryEntities(groupsUri, null, null, null);
while (iterator.hasNext()) {
final ContentValues values = iterator.next().getEntityValues();
final GroupDelta group = GroupDelta.fromBefore(values);
addGroup(group);
hasGroups = true;
}
+ // Create single entry handling ungrouped status
+ mUngrouped = GroupDelta.fromSettings(resolver, accountName, accountType, hasGroups);
+ addGroup(mUngrouped);
} catch (RemoteException e) {
Log.w(TAG, "Problem reading groups: " + e.toString());
} finally {
- if (iterator != null) iterator.close();
+ iterator.close();
}
-
- // Create single entry handling ungrouped status
- mUngrouped = GroupDelta.fromSettings(resolver, accountName, accountType, hasGroups);
- addGroup(mUngrouped);
}
/**
diff --git a/src/com/android/contacts/ui/QuickContactWindow.java b/src/com/android/contacts/ui/QuickContactWindow.java
index e1ff0e3..baf42ac 100644
--- a/src/com/android/contacts/ui/QuickContactWindow.java
+++ b/src/com/android/contacts/ui/QuickContactWindow.java
@@ -55,6 +55,8 @@
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.CommonDataKinds.Website;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -175,10 +177,17 @@
private String[] mExcludeMimes;
/**
- * Specific MIME-types that should be bumped to the front of the dialog.
- * Other MIME-types not appearing in this list follow in alphabetic order.
+ * {@link #PRECEDING_MIMETYPES} and {@link #FOLLOWING_MIMETYPES} are used to sort MIME-types.
+ *
+ * <p>The MIME-types in {@link #PRECEDING_MIMETYPES} appear in the front of the dialog,
+ * in the order in the array.
+ *
+ * <p>The ones in {@link #FOLLOWING_MIMETYPES} appear in the end of the dialog, in alphabetical
+ * order.
+ *
+ * <p>The rest go between them, in the order in the array.
*/
- private static final String[] ORDERED_MIMETYPES = new String[] {
+ private static final String[] PRECEDING_MIMETYPES = new String[] {
Phone.CONTENT_ITEM_TYPE,
Contacts.CONTENT_ITEM_TYPE,
Constants.MIME_SMS_ADDRESS,
@@ -186,6 +195,14 @@
};
/**
+ * See {@link #PRECEDING_MIMETYPES}.
+ */
+ private static final String[] FOLLOWING_MIMETYPES = new String[] {
+ StructuredPostal.CONTENT_ITEM_TYPE,
+ Website.CONTENT_ITEM_TYPE,
+ };
+
+ /**
* Specific list {@link ApplicationInfo#packageName} of apps that are
* prefered <strong>only</strong> for the purposes of default icons when
* multiple {@link ResolveInfo} are found to match. This only happens when
@@ -197,7 +214,8 @@
"com.android.calendar",
"com.android.contacts",
"com.android.mms",
- "com.android.phone");
+ "com.android.phone",
+ "com.android.browser");
private static final int TOKEN_DATA = 1;
@@ -741,6 +759,12 @@
mIntent = new Intent(Intent.ACTION_SENDTO, mailUri);
}
+ } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ final String url = getAsString(cursor, Website.URL);
+ if (!TextUtils.isEmpty(url)) {
+ mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ }
+
} else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(
getAsString(cursor, Data.MIMETYPE));
@@ -1198,22 +1222,39 @@
setHeaderText(R.id.timestamp, status.getTimestampLabel(mContext));
}
- // Turn our list of actions into UI elements, starting with common types
- final Set<String> containedTypes = mActions.keySet();
- for (String mimeType : ORDERED_MIMETYPES) {
+ // Turn our list of actions into UI elements
+
+ // Index where we start adding child views.
+ int index = mTrack.getChildCount() - 1;
+
+ // All the mime-types to add.
+ final Set<String> containedTypes = new HashSet<String>(mActions.keySet());
+
+ // First, add PRECEDING_MIMETYPES, which are most common.
+ for (String mimeType : PRECEDING_MIMETYPES) {
if (containedTypes.contains(mimeType)) {
- final int index = mTrack.getChildCount() - 1;
- mTrack.addView(inflateAction(mimeType), index);
+ mTrack.addView(inflateAction(mimeType), index++);
containedTypes.remove(mimeType);
}
}
- // Then continue with remaining MIME-types in alphabetical order
+ // Keep the current index to append non PRECEDING/FOLLOWING items.
+ final int indexAfterPreceding = index;
+
+ // Then, add FOLLOWING_MIMETYPES, which are least common.
+ for (String mimeType : FOLLOWING_MIMETYPES) {
+ if (containedTypes.contains(mimeType)) {
+ mTrack.addView(inflateAction(mimeType), index++);
+ containedTypes.remove(mimeType);
+ }
+ }
+
+ // Go back to just after PRECEDING_MIMETYPES, and append the rest.
+ index = indexAfterPreceding;
final String[] remainingTypes = containedTypes.toArray(new String[containedTypes.size()]);
Arrays.sort(remainingTypes);
for (String mimeType : remainingTypes) {
- final int index = mTrack.getChildCount() - 1;
- mTrack.addView(inflateAction(mimeType), index);
+ mTrack.addView(inflateAction(mimeType), index++);
}
}
@@ -1554,11 +1595,6 @@
}
/** {@inheritDoc} */
- public void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator) {
- // No actions
- }
-
- /** {@inheritDoc} */
public void onAttachedToWindow() {
// No actions
}
diff --git a/src/com/android/contacts/ui/ShowOrCreateActivity.java b/src/com/android/contacts/ui/ShowOrCreateActivity.java
index 7728b36..0828b3f 100755
--- a/src/com/android/contacts/ui/ShowOrCreateActivity.java
+++ b/src/com/android/contacts/ui/ShowOrCreateActivity.java
@@ -221,11 +221,6 @@
return super.onCreateDialog(id);
}
- /** {@inheritDoc} */
- public void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator) {
- // No actions
- }
-
/**
* Listener for {@link DialogInterface} that launches a given {@link Intent}
* when clicked. When clicked, this also closes the parent using
diff --git a/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java b/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java
index 795ac79..83fae29 100644
--- a/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java
+++ b/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java
@@ -18,7 +18,6 @@
import android.content.AsyncQueryHandler;
import android.content.Context;
-import android.content.EntityIterator;
import android.database.Cursor;
import java.lang.ref.WeakReference;
@@ -26,7 +25,7 @@
/**
* Slightly more abstract {@link AsyncQueryHandler} that helps keep a
* {@link WeakReference} back to a listener. Will properly close any
- * {@link Cursor} or {@link EntityIterator} if the listener ceases to exist.
+ * {@link Cursor} if the listener ceases to exist.
* <p>
* This pattern can be used to perform background queries without leaking
* {@link Context} objects.
@@ -41,7 +40,6 @@
*/
public interface AsyncQueryListener {
void onQueryComplete(int token, Object cookie, Cursor cursor);
- void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator);
}
public NotifyingAsyncQueryHandler(Context context, AsyncQueryListener listener) {
@@ -67,15 +65,4 @@
cursor.close();
}
}
-
- /** {@inheritDoc} */
- @Override
- protected void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator) {
- final AsyncQueryListener listener = mListener.get();
- if (listener != null) {
- listener.onQueryEntitiesComplete(token, cookie, iterator);
- } else if (iterator != null) {
- iterator.close();
- }
- }
}