summaryrefslogtreecommitdiffstats
path: root/chips/src/com/android/ex
diff options
context:
space:
mode:
authorScott Kennedy <skennedy@google.com>2013-11-21 14:31:33 -0800
committerScott Kennedy <skennedy@google.com>2014-02-05 21:33:37 -0800
commitae07c2be104a1f95426b697f3074bea72bc140e1 (patch)
tree0c86989672f1a2876f8a6a6ca41d6e0e179bb1b7 /chips/src/com/android/ex
parent95fedd51882128dea2152c3d1c7ff194f8e557bf (diff)
downloadandroid_frameworks_ex-ae07c2be104a1f95426b697f3074bea72bc140e1.tar.gz
android_frameworks_ex-ae07c2be104a1f95426b697f3074bea72bc140e1.tar.bz2
android_frameworks_ex-ae07c2be104a1f95426b697f3074bea72bc140e1.zip
Fix directory lookups
The previous "fix" disabled the lookups. Now we will do the lookups, with the proper lookup key and directory id. We also do a much better job of showing directory images. Bug: 11693322 Bug: 12793279 Change-Id: I372711fd7b485f3183516fce2b11f9eff46a9b23
Diffstat (limited to 'chips/src/com/android/ex')
-rw-r--r--chips/src/com/android/ex/chips/BaseRecipientAdapter.java69
-rw-r--r--chips/src/com/android/ex/chips/DropdownChipLayouter.java2
-rw-r--r--chips/src/com/android/ex/chips/Queries.java41
-rw-r--r--chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java168
-rw-r--r--chips/src/com/android/ex/chips/RecipientEditTextView.java12
-rw-r--r--chips/src/com/android/ex/chips/RecipientEntry.java53
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java17
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java15
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java21
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java15
10 files changed, 303 insertions, 110 deletions
diff --git a/chips/src/com/android/ex/chips/BaseRecipientAdapter.java b/chips/src/com/android/ex/chips/BaseRecipientAdapter.java
index 531fd37..8233081 100644
--- a/chips/src/com/android/ex/chips/BaseRecipientAdapter.java
+++ b/chips/src/com/android/ex/chips/BaseRecipientAdapter.java
@@ -23,6 +23,8 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
@@ -45,6 +47,7 @@ import android.widget.Filterable;
import com.android.ex.chips.DropdownChipLayouter.AdapterType;
import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -147,10 +150,11 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
public final int destinationType;
public final String destinationLabel;
public final long contactId;
+ public final Long directoryId;
public final long dataId;
public final String thumbnailUriString;
public final int displayNameSource;
- public final boolean isGalContact;
+ public final String lookupKey;
public TemporaryEntry(
String displayName,
@@ -158,31 +162,34 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
int destinationType,
String destinationLabel,
long contactId,
+ Long directoryId,
long dataId,
String thumbnailUriString,
int displayNameSource,
- boolean isGalContact) {
+ String lookupKey) {
this.displayName = displayName;
this.destination = destination;
this.destinationType = destinationType;
this.destinationLabel = destinationLabel;
this.contactId = contactId;
+ this.directoryId = directoryId;
this.dataId = dataId;
this.thumbnailUriString = thumbnailUriString;
this.displayNameSource = displayNameSource;
- this.isGalContact = isGalContact;
+ this.lookupKey = lookupKey;
}
- public TemporaryEntry(Cursor cursor, boolean isGalContact) {
+ public TemporaryEntry(Cursor cursor, Long directoryId) {
this.displayName = cursor.getString(Queries.Query.NAME);
this.destination = cursor.getString(Queries.Query.DESTINATION);
this.destinationType = cursor.getInt(Queries.Query.DESTINATION_TYPE);
this.destinationLabel = cursor.getString(Queries.Query.DESTINATION_LABEL);
this.contactId = cursor.getLong(Queries.Query.CONTACT_ID);
+ this.directoryId = directoryId;
this.dataId = cursor.getLong(Queries.Query.DATA_ID);
this.thumbnailUriString = cursor.getString(Queries.Query.PHOTO_THUMBNAIL_URI);
this.displayNameSource = cursor.getInt(Queries.Query.DISPLAY_NAME_SOURCE);
- this.isGalContact = isGalContact;
+ this.lookupKey = cursor.getString(Queries.Query.LOOKUP_KEY);
}
}
@@ -234,7 +241,8 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
}
try {
- defaultDirectoryCursor = doQuery(constraint, mPreferredMaxResultCount, null);
+ defaultDirectoryCursor = doQuery(constraint, mPreferredMaxResultCount,
+ null /* directoryId */);
if (defaultDirectoryCursor == null) {
if (DEBUG) {
@@ -254,7 +262,7 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
// Note: At this point each entry doesn't contain any photo
// (thus getPhotoBytes() returns null).
putOneEntry(new TemporaryEntry(defaultDirectoryCursor,
- false /* isGalContact */),
+ null /* directoryId */),
true, entryMap, nonAggregatedEntries, existingDestinations);
}
@@ -385,7 +393,7 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
if (cursor != null) {
while (cursor.moveToNext()) {
- tempEntries.add(new TemporaryEntry(cursor, true /* isGalContact */));
+ tempEntries.add(new TemporaryEntry(cursor, mParams.directoryId));
}
}
} finally {
@@ -695,8 +703,8 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
entry.displayName,
entry.displayNameSource,
entry.destination, entry.destinationType, entry.destinationLabel,
- entry.contactId, entry.dataId, entry.thumbnailUriString, true,
- entry.isGalContact));
+ entry.contactId, entry.directoryId, entry.dataId, entry.thumbnailUriString,
+ true, entry.lookupKey));
} else if (entryMap.containsKey(entry.contactId)) {
// We already have a section for the person.
final List<RecipientEntry> entryList = entryMap.get(entry.contactId);
@@ -704,16 +712,16 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
entry.displayName,
entry.displayNameSource,
entry.destination, entry.destinationType, entry.destinationLabel,
- entry.contactId, entry.dataId, entry.thumbnailUriString, true,
- entry.isGalContact));
+ entry.contactId, entry.directoryId, entry.dataId, entry.thumbnailUriString,
+ true, entry.lookupKey));
} else {
final List<RecipientEntry> entryList = new ArrayList<RecipientEntry>();
entryList.add(RecipientEntry.constructTopLevelEntry(
entry.displayName,
entry.displayNameSource,
entry.destination, entry.destinationType, entry.destinationLabel,
- entry.contactId, entry.dataId, entry.thumbnailUriString, true,
- entry.isGalContact));
+ entry.contactId, entry.directoryId, entry.dataId, entry.thumbnailUriString,
+ true, entry.lookupKey));
entryMap.put(entry.contactId, entryList);
}
}
@@ -879,6 +887,39 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
} finally {
photoCursor.close();
}
+ } else {
+ InputStream inputStream = null;
+ ByteArrayOutputStream outputStream = null;
+ try {
+ inputStream = mContentResolver.openInputStream(photoThumbnailUri);
+ final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+
+ if (bitmap != null) {
+ outputStream = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
+ photoBytes = outputStream.toByteArray();
+
+ entry.setPhotoBytes(photoBytes);
+ mPhotoCacheMap.put(photoThumbnailUri, photoBytes);
+ }
+ } catch (final FileNotFoundException e) {
+ Log.w(TAG, "Error opening InputStream for photo", e);
+ } finally {
+ try {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing photo input stream", e);
+ }
+ try {
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing photo output stream", e);
+ }
+ }
}
}
diff --git a/chips/src/com/android/ex/chips/DropdownChipLayouter.java b/chips/src/com/android/ex/chips/DropdownChipLayouter.java
index aceefab..6b0e78e 100644
--- a/chips/src/com/android/ex/chips/DropdownChipLayouter.java
+++ b/chips/src/com/android/ex/chips/DropdownChipLayouter.java
@@ -171,7 +171,7 @@ public class DropdownChipLayouter {
if (thumbnailUri != null) {
// TODO: see if this needs to be done outside the main thread
// as it may be too slow to get immediately.
- view.setImageURI(entry.getPhotoThumbnailUri());
+ view.setImageURI(thumbnailUri);
} else {
view.setImageResource(getDefaultPhotoResId());
}
diff --git a/chips/src/com/android/ex/chips/Queries.java b/chips/src/com/android/ex/chips/Queries.java
index 9d31aec..1e66b96 100644
--- a/chips/src/com/android/ex/chips/Queries.java
+++ b/chips/src/com/android/ex/chips/Queries.java
@@ -18,6 +18,7 @@ package com.android.ex.chips;
import android.content.res.Resources;
import android.net.Uri;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
@@ -28,14 +29,16 @@ import android.provider.ContactsContract.Contacts;
/* package */ class Queries {
public static final Query PHONE = new Query(new String[] {
- Contacts.DISPLAY_NAME, // 0
- Phone.NUMBER, // 1
- Phone.TYPE, // 2
- Phone.LABEL, // 3
- Phone.CONTACT_ID, // 4
- Phone._ID, // 5
- Contacts.PHOTO_THUMBNAIL_URI,// 6
- Contacts.DISPLAY_NAME_SOURCE // 7
+ Contacts.DISPLAY_NAME, // 0
+ Phone.NUMBER, // 1
+ Phone.TYPE, // 2
+ Phone.LABEL, // 3
+ Phone.CONTACT_ID, // 4
+ Phone._ID, // 5
+ Contacts.PHOTO_THUMBNAIL_URI, // 6
+ Contacts.DISPLAY_NAME_SOURCE, // 7
+ Contacts.LOOKUP_KEY, // 8
+ ContactsContract.CommonDataKinds.Email.MIMETYPE // 9
}, Phone.CONTENT_FILTER_URI, Phone.CONTENT_URI) {
@Override
@@ -46,14 +49,16 @@ import android.provider.ContactsContract.Contacts;
};
public static final Query EMAIL = new Query(new String[]{
- Contacts.DISPLAY_NAME, // 0
- Email.DATA, // 1
- Email.TYPE, // 2
- Email.LABEL, // 3
- Email.CONTACT_ID, // 4
- Email._ID, // 5
- Contacts.PHOTO_THUMBNAIL_URI,// 6
- Contacts.DISPLAY_NAME_SOURCE // 7
+ Contacts.DISPLAY_NAME, // 0
+ Email.DATA, // 1
+ Email.TYPE, // 2
+ Email.LABEL, // 3
+ Email.CONTACT_ID, // 4
+ Email._ID, // 5
+ Contacts.PHOTO_THUMBNAIL_URI, // 6
+ Contacts.DISPLAY_NAME_SOURCE, // 7
+ Contacts.LOOKUP_KEY, // 8
+ ContactsContract.CommonDataKinds.Email.MIMETYPE // 9
}, Email.CONTENT_FILTER_URI, Email.CONTENT_URI) {
@Override
@@ -76,8 +81,10 @@ import android.provider.ContactsContract.Contacts;
public static final int DATA_ID = 5; // long
public static final int PHOTO_THUMBNAIL_URI = 6; // String
public static final int DISPLAY_NAME_SOURCE = 7; // int
+ public static final int LOOKUP_KEY = 8; // String
+ public static final int MIME_TYPE = 9; // String
- public Query (String[] projection, Uri contentFilter, Uri content) {
+ public Query(String[] projection, Uri contentFilter, Uri content) {
mProjection = projection;
mContentFilterUri = contentFilter;
mContentUri = content;
diff --git a/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java b/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java
index 547a76b..f6f662d 100644
--- a/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java
+++ b/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java
@@ -23,6 +23,7 @@ import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
@@ -60,9 +61,11 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
public static final int QUERY_TYPE_EMAIL = 0;
public static final int QUERY_TYPE_PHONE = 1;
- private Query mQuery;
+ private final Long mDirectoryId;
private DropdownChipLayouter mDropdownChipLayouter;
+ private static final Map<String, String> sCorrectedPhotoUris = new HashMap<String, String>();
+
public interface RecipientMatchCallback {
public void matchesFound(Map<String, RecipientEntry> results);
/**
@@ -123,7 +126,7 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
query.getProjection(),
query.getProjection()[Queries.Query.DESTINATION] + " IN ("
+ bindString.toString() + ")", addressArray, null);
- recipientEntries = processContactEntries(c);
+ recipientEntries = processContactEntries(c, null /* directoryId */);
callback.matchesFound(recipientEntries);
} finally {
if (c != null) {
@@ -163,6 +166,7 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
if (paramsList != null) {
Cursor directoryContactsCursor = null;
for (String unresolvedAddress : unresolvedAddresses) {
+ Long directoryId = null;
for (int i = 0; i < paramsList.size(); i++) {
try {
directoryContactsCursor = doQuery(unresolvedAddress, 1,
@@ -174,6 +178,7 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
directoryContactsCursor.close();
directoryContactsCursor = null;
} else {
+ directoryId = paramsList.get(i).directoryId;
break;
}
}
@@ -181,7 +186,7 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
if (directoryContactsCursor != null) {
try {
final Map<String, RecipientEntry> entries =
- processContactEntries(directoryContactsCursor);
+ processContactEntries(directoryContactsCursor, directoryId);
for (final String address : entries.keySet()) {
matchesNotFound.remove(address);
@@ -212,7 +217,8 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
callback.matchesNotFound(matchesNotFound);
}
- private static HashMap<String, RecipientEntry> processContactEntries(Cursor c) {
+ private static HashMap<String, RecipientEntry> processContactEntries(Cursor c,
+ Long directoryId) {
HashMap<String, RecipientEntry> recipientEntries = new HashMap<String, RecipientEntry>();
if (c != null && c.moveToFirst()) {
do {
@@ -225,10 +231,11 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
c.getInt(Queries.Query.DESTINATION_TYPE),
c.getString(Queries.Query.DESTINATION_LABEL),
c.getLong(Queries.Query.CONTACT_ID),
+ directoryId,
c.getLong(Queries.Query.DATA_ID),
c.getString(Queries.Query.PHOTO_THUMBNAIL_URI),
true,
- false /* isGalContact TODO(skennedy) We should look these up eventually */);
+ c.getString(Queries.Query.LOOKUP_KEY));
/*
* In certain situations, we may have two results for one address, where one of the
@@ -325,43 +332,74 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
return cursor;
}
- public RecipientAlternatesAdapter(Context context, long contactId, long currentId,
- int queryMode, OnCheckedItemChangedListener listener,
- DropdownChipLayouter dropdownChipLayouter) {
- super(context, getCursorForConstruction(context, contactId, queryMode), 0);
+ public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId,
+ String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener,
+ DropdownChipLayouter dropdownChipLayouter) {
+ super(context,
+ getCursorForConstruction(context, contactId, directoryId, lookupKey, queryMode), 0);
mCurrentId = currentId;
+ mDirectoryId = directoryId;
mCheckedItemChangedListener = listener;
- if (queryMode == QUERY_TYPE_EMAIL) {
- mQuery = Queries.EMAIL;
- } else if (queryMode == QUERY_TYPE_PHONE) {
- mQuery = Queries.PHONE;
- } else {
- mQuery = Queries.EMAIL;
- Log.e(TAG, "Unsupported query type: " + queryMode);
- }
-
mDropdownChipLayouter = dropdownChipLayouter;
}
- private static Cursor getCursorForConstruction(Context context, long contactId, int queryType) {
+ private static Cursor getCursorForConstruction(Context context, long contactId,
+ Long directoryId, String lookupKey, int queryType) {
final Cursor cursor;
+ final String desiredMimeType;
if (queryType == QUERY_TYPE_EMAIL) {
+ final Uri uri;
+ final StringBuilder selection = new StringBuilder();
+ selection.append(Queries.EMAIL.getProjection()[Queries.Query.CONTACT_ID]);
+ selection.append(" = ?");
+
+ if (directoryId == null || lookupKey == null) {
+ uri = Queries.EMAIL.getContentUri();
+ desiredMimeType = null;
+ } else {
+ final Uri.Builder builder = Contacts.getLookupUri(contactId, lookupKey).buildUpon();
+ builder.appendPath(Contacts.Entity.CONTENT_DIRECTORY)
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId));
+ uri = builder.build();
+ desiredMimeType = ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE;
+ }
cursor = context.getContentResolver().query(
- Queries.EMAIL.getContentUri(),
+ uri,
Queries.EMAIL.getProjection(),
- Queries.EMAIL.getProjection()[Queries.Query.CONTACT_ID] + " =?", new String[] {
+ selection.toString(), new String[] {
String.valueOf(contactId)
}, null);
} else {
+ final Uri uri;
+ final StringBuilder selection = new StringBuilder();
+ selection.append(Queries.PHONE.getProjection()[Queries.Query.CONTACT_ID]);
+ selection.append(" = ?");
+
+ if (lookupKey == null) {
+ uri = Queries.PHONE.getContentUri();
+ desiredMimeType = null;
+ } else {
+ final Uri.Builder builder = Contacts.getLookupUri(contactId, lookupKey).buildUpon();
+ builder.appendPath(Contacts.Entity.CONTENT_DIRECTORY)
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId));
+ uri = builder.build();
+ desiredMimeType = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE;
+ }
cursor = context.getContentResolver().query(
- Queries.PHONE.getContentUri(),
+ uri,
Queries.PHONE.getProjection(),
- Queries.PHONE.getProjection()[Queries.Query.CONTACT_ID] + " =?", new String[] {
+ selection.toString(), new String[] {
String.valueOf(contactId)
}, null);
}
- return removeDuplicateDestinations(cursor);
+
+ final Cursor resultCursor = removeUndesiredDestinations(cursor, desiredMimeType, lookupKey);
+ cursor.close();
+
+ return resultCursor;
}
/**
@@ -374,22 +412,53 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
* - This method creates a MatrixCursor, so all data will be kept in memory. We wouldn't want
* to do this if the original cursor is large, but it's okay here because the alternate list
* won't be that big.
+ *
+ * @param desiredMimeType If this is non-<code>null</code>, only entries with this mime type
+ * will be added to the cursor
+ * @param lookupKey The lookup key used for this contact if there isn't one in the cursor. This
+ * should be the same one used in the query that returned the cursor
*/
// Visible for testing
- /* package */ static Cursor removeDuplicateDestinations(Cursor original) {
+ static Cursor removeUndesiredDestinations(final Cursor original, final String desiredMimeType,
+ final String lookupKey) {
final MatrixCursor result = new MatrixCursor(
original.getColumnNames(), original.getCount());
final HashSet<String> destinationsSeen = new HashSet<String>();
+ String defaultDisplayName = null;
+ String defaultPhotoThumbnailUri = null;
+ int defaultDisplayNameSource = 0;
+
+ // Find some nice defaults in case we need them
+ original.moveToPosition(-1);
+ while (original.moveToNext()) {
+ final String mimeType = original.getString(Query.MIME_TYPE);
+
+ if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(
+ mimeType)) {
+ // Store this data
+ defaultDisplayName = original.getString(Query.NAME);
+ defaultPhotoThumbnailUri = original.getString(Query.PHOTO_THUMBNAIL_URI);
+ defaultDisplayNameSource = original.getInt(Query.DISPLAY_NAME_SOURCE);
+ break;
+ }
+ }
+
original.moveToPosition(-1);
while (original.moveToNext()) {
+ if (desiredMimeType != null) {
+ final String mimeType = original.getString(Query.MIME_TYPE);
+ if (!desiredMimeType.equals(mimeType)) {
+ continue;
+ }
+ }
final String destination = original.getString(Query.DESTINATION);
if (destinationsSeen.contains(destination)) {
continue;
}
destinationsSeen.add(destination);
- result.addRow(new Object[] {
+ final Object[] row = new Object[] {
original.getString(Query.NAME),
original.getString(Query.DESTINATION),
original.getInt(Query.DESTINATION_TYPE),
@@ -397,8 +466,48 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
original.getLong(Query.CONTACT_ID),
original.getLong(Query.DATA_ID),
original.getString(Query.PHOTO_THUMBNAIL_URI),
- original.getInt(Query.DISPLAY_NAME_SOURCE)
- });
+ original.getInt(Query.DISPLAY_NAME_SOURCE),
+ original.getString(Query.LOOKUP_KEY),
+ original.getString(Query.MIME_TYPE)
+ };
+
+ if (row[Query.NAME] == null) {
+ row[Query.NAME] = defaultDisplayName;
+ }
+ if (row[Query.PHOTO_THUMBNAIL_URI] == null) {
+ row[Query.PHOTO_THUMBNAIL_URI] = defaultPhotoThumbnailUri;
+ }
+ if ((Integer) row[Query.DISPLAY_NAME_SOURCE] == 0) {
+ row[Query.DISPLAY_NAME_SOURCE] = defaultDisplayNameSource;
+ }
+ if (row[Query.LOOKUP_KEY] == null) {
+ row[Query.LOOKUP_KEY] = lookupKey;
+ }
+
+ // Ensure we don't have two '?' like content://.../...?account_name=...?sz=...
+ final String photoThumbnailUri = (String) row[Query.PHOTO_THUMBNAIL_URI];
+ if (photoThumbnailUri != null) {
+ if (sCorrectedPhotoUris.containsKey(photoThumbnailUri)) {
+ row[Query.PHOTO_THUMBNAIL_URI] = sCorrectedPhotoUris.get(photoThumbnailUri);
+ } else if (photoThumbnailUri.indexOf('?') != photoThumbnailUri.lastIndexOf('?')) {
+ final String[] parts = photoThumbnailUri.split("\\?");
+ final StringBuilder correctedUriBuilder = new StringBuilder();
+ for (int i = 0; i < parts.length; i++) {
+ if (i == 1) {
+ correctedUriBuilder.append("?"); // We only want one of these
+ } else if (i > 1) {
+ correctedUriBuilder.append("&"); // And we want these elsewhere
+ }
+ correctedUriBuilder.append(parts[i]);
+ }
+
+ final String correctedUri = correctedUriBuilder.toString();
+ sCorrectedPhotoUris.put(photoThumbnailUri, correctedUri);
+ row[Query.PHOTO_THUMBNAIL_URI] = correctedUri;
+ }
+ }
+
+ result.addRow(row);
}
return result;
@@ -423,10 +532,11 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
c.getInt(Queries.Query.DESTINATION_TYPE),
c.getString(Queries.Query.DESTINATION_LABEL),
c.getLong(Queries.Query.CONTACT_ID),
+ mDirectoryId,
c.getLong(Queries.Query.DATA_ID),
c.getString(Queries.Query.PHOTO_THUMBNAIL_URI),
true,
- false /* isGalContact TODO(skennedy) We should look these up eventually */);
+ c.getString(Queries.Query.LOOKUP_KEY));
}
@Override
diff --git a/chips/src/com/android/ex/chips/RecipientEditTextView.java b/chips/src/com/android/ex/chips/RecipientEditTextView.java
index 9a4609d..eca0afb 100644
--- a/chips/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/chips/src/com/android/ex/chips/RecipientEditTextView.java
@@ -483,7 +483,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
protected ScrollView getScrollView() {
- return mScrollView;
+ return mScrollView;
}
@Override
@@ -1571,7 +1571,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
private ListAdapter createAlternatesAdapter(DrawableRecipientChip chip) {
- return new RecipientAlternatesAdapter(getContext(), chip.getContactId(), chip.getDataId(),
+ return new RecipientAlternatesAdapter(getContext(), chip.getContactId(),
+ chip.getDirectoryId(), chip.getLookupKey(), chip.getDataId(),
getAdapter().getQueryType(), this, mDropdownChipLayouter);
}
@@ -2046,8 +2047,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return constructChipSpan(
RecipientEntry.constructFakeEntry((String) text, isValid(text.toString())),
true, false);
- } else if (currentChip.getContactId() == RecipientEntry.GENERATED_CONTACT
- || currentChip.isGalContact()) {
+ } else if (currentChip.getContactId() == RecipientEntry.GENERATED_CONTACT) {
int start = getChipStart(currentChip);
int end = getChipEnd(currentChip);
getSpannable().removeSpan(currentChip);
@@ -2590,7 +2590,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
addresses.add(createAddressText(chip.getEntry()));
}
}
- final BaseRecipientAdapter adapter = (BaseRecipientAdapter) getAdapter();
+ final BaseRecipientAdapter adapter = getAdapter();
RecipientAlternatesAdapter.getMatchingRecipients(getContext(), adapter, addresses,
adapter.getAccount(), new RecipientMatchCallback() {
@Override
@@ -2718,7 +2718,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
addresses.add(createAddressText(chip.getEntry()));
}
}
- final BaseRecipientAdapter adapter = (BaseRecipientAdapter) getAdapter();
+ final BaseRecipientAdapter adapter = getAdapter();
RecipientAlternatesAdapter.getMatchingRecipients(getContext(), adapter, addresses,
adapter.getAccount(),
new RecipientMatchCallback() {
diff --git a/chips/src/com/android/ex/chips/RecipientEntry.java b/chips/src/com/android/ex/chips/RecipientEntry.java
index 30fccae..7d9b87f 100644
--- a/chips/src/com/android/ex/chips/RecipientEntry.java
+++ b/chips/src/com/android/ex/chips/RecipientEntry.java
@@ -61,6 +61,8 @@ public class RecipientEntry {
private final String mDestinationLabel;
/** ID for the person */
private final long mContactId;
+ /** ID for the directory this contact came from, or <code>null</code> */
+ private final Long mDirectoryId;
/** ID for the destination */
private final long mDataId;
private final boolean mIsDivider;
@@ -74,11 +76,13 @@ public class RecipientEntry {
*/
private byte[] mPhotoBytes;
- private final boolean mIsGalContact;
+ /** See {@link ContactsContract.Contacts#LOOKUP_KEY} */
+ private final String mLookupKey;
private RecipientEntry(int entryType, String displayName, String destination,
- int destinationType, String destinationLabel, long contactId, long dataId,
- Uri photoThumbnailUri, boolean isFirstLevel, boolean isValid, boolean isGalContact) {
+ int destinationType, String destinationLabel, long contactId, Long directoryId,
+ long dataId, Uri photoThumbnailUri, boolean isFirstLevel, boolean isValid,
+ String lookupKey) {
mEntryType = entryType;
mIsFirstLevel = isFirstLevel;
mDisplayName = displayName;
@@ -86,12 +90,13 @@ public class RecipientEntry {
mDestinationType = destinationType;
mDestinationLabel = destinationLabel;
mContactId = contactId;
+ mDirectoryId = directoryId;
mDataId = dataId;
mPhotoThumbnailUri = photoThumbnailUri;
mPhotoBytes = null;
mIsDivider = false;
mIsValid = isValid;
- mIsGalContact = isGalContact;
+ mLookupKey = lookupKey;
}
public boolean isValid() {
@@ -116,8 +121,8 @@ public class RecipientEntry {
final String tokenizedAddress = tokens.length > 0 ? tokens[0].getAddress() : address;
return new RecipientEntry(ENTRY_TYPE_PERSON, tokenizedAddress, tokenizedAddress,
- INVALID_DESTINATION_TYPE, null,
- INVALID_CONTACT, INVALID_CONTACT, null, true, isValid, false /* isGalContact */);
+ INVALID_DESTINATION_TYPE, null, INVALID_CONTACT, null /* directoryId */,
+ INVALID_CONTACT, null, true, isValid, null /* lookupKey */);
}
/**
@@ -126,8 +131,8 @@ public class RecipientEntry {
public static RecipientEntry constructFakePhoneEntry(final String phoneNumber,
final boolean isValid) {
return new RecipientEntry(ENTRY_TYPE_PERSON, phoneNumber, phoneNumber,
- INVALID_DESTINATION_TYPE, null,
- INVALID_CONTACT, INVALID_CONTACT, null, true, isValid, false /* isGalContact */);
+ INVALID_DESTINATION_TYPE, null, INVALID_CONTACT, null /* directoryId */,
+ INVALID_CONTACT, null, true, isValid, null /* lookupKey */);
}
/**
@@ -149,35 +154,37 @@ public class RecipientEntry {
public static RecipientEntry constructGeneratedEntry(String display, String address,
boolean isValid) {
return new RecipientEntry(ENTRY_TYPE_PERSON, display, address, INVALID_DESTINATION_TYPE,
- null, GENERATED_CONTACT, GENERATED_CONTACT, null, true, isValid,
- false /* isGalContact */);
+ null, GENERATED_CONTACT, null /* directoryId */, GENERATED_CONTACT, null, true,
+ isValid, null /* lookupKey */);
}
public static RecipientEntry constructTopLevelEntry(String displayName, int displayNameSource,
String destination, int destinationType, String destinationLabel, long contactId,
- long dataId, Uri photoThumbnailUri, boolean isValid, boolean isGalContact) {
+ Long directoryId, long dataId, Uri photoThumbnailUri, boolean isValid,
+ String lookupKey) {
return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource,
displayName, destination), destination, destinationType, destinationLabel,
- contactId, dataId, photoThumbnailUri, true, isValid, isGalContact);
+ contactId, directoryId, dataId, photoThumbnailUri, true, isValid, lookupKey);
}
public static RecipientEntry constructTopLevelEntry(String displayName, int displayNameSource,
String destination, int destinationType, String destinationLabel, long contactId,
- long dataId, String thumbnailUriAsString, boolean isValid, boolean isGalContact) {
+ Long directoryId, long dataId, String thumbnailUriAsString, boolean isValid,
+ String lookupKey) {
return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource,
displayName, destination), destination, destinationType, destinationLabel,
- contactId, dataId, (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString)
- : null), true, isValid, isGalContact);
+ contactId, directoryId, dataId, (thumbnailUriAsString != null
+ ? Uri.parse(thumbnailUriAsString) : null), true, isValid, lookupKey);
}
public static RecipientEntry constructSecondLevelEntry(String displayName,
int displayNameSource, String destination, int destinationType,
- String destinationLabel, long contactId, long dataId, String thumbnailUriAsString,
- boolean isValid, boolean isGalContact) {
+ String destinationLabel, long contactId, Long directoryId, long dataId,
+ String thumbnailUriAsString, boolean isValid, String lookupKey) {
return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource,
displayName, destination), destination, destinationType, destinationLabel,
- contactId, dataId, (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString)
- : null), false, isValid, isGalContact);
+ contactId, directoryId, dataId, (thumbnailUriAsString != null
+ ? Uri.parse(thumbnailUriAsString) : null), false, isValid, lookupKey);
}
public int getEntryType() {
@@ -204,6 +211,10 @@ public class RecipientEntry {
return mContactId;
}
+ public Long getDirectoryId() {
+ return mDirectoryId;
+ }
+
public long getDataId() {
return mDataId;
}
@@ -234,8 +245,8 @@ public class RecipientEntry {
return mEntryType == ENTRY_TYPE_PERSON;
}
- public boolean isGalContact() {
- return mIsGalContact;
+ public String getLookupKey() {
+ return mLookupKey;
}
@Override
diff --git a/chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java
index 032d3b2..8012b5c 100644
--- a/chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java
+++ b/chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java
@@ -50,6 +50,16 @@ interface BaseRecipientChip {
long getContactId();
/**
+ * Get the directory id of the contact associated with this chip.
+ */
+ Long getDirectoryId();
+
+ /**
+ * Get the directory lookup key associated with this chip, or <code>null</code>.
+ */
+ String getLookupKey();
+
+ /**
* Get the id of the data associated with this chip.
*/
long getDataId();
@@ -70,11 +80,4 @@ interface BaseRecipientChip {
* before any reverse lookups.
*/
CharSequence getOriginalText();
-
- /**
- * Checks if this contact was retrieved from a GAL lookup.
- *
- * @return <code>true</code> if it came from GAL, <code>false</code> otherwise
- */
- boolean isGalContact();
}
diff --git a/chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java
index 11a66da..455f2cb 100644
--- a/chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java
+++ b/chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java
@@ -62,6 +62,16 @@ public class InvisibleRecipientChip extends ReplacementSpan implements DrawableR
}
@Override
+ public Long getDirectoryId() {
+ return mDelegate.getDirectoryId();
+ }
+
+ @Override
+ public String getLookupKey() {
+ return mDelegate.getLookupKey();
+ }
+
+ @Override
public long getDataId() {
return mDelegate.getDataId();
}
@@ -82,11 +92,6 @@ public class InvisibleRecipientChip extends ReplacementSpan implements DrawableR
}
@Override
- public boolean isGalContact() {
- return mDelegate.isGalContact();
- }
-
- @Override
public void draw(final Canvas canvas, final CharSequence text, final int start, final int end,
final float x, final int top, final int y, final int bottom, final Paint paint) {
// Do nothing.
diff --git a/chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java
index ac8e897..533f53f 100644
--- a/chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java
+++ b/chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java
@@ -27,6 +27,10 @@ class SimpleRecipientChip implements BaseRecipientChip {
private final long mContactId;
+ private final Long mDirectoryId;
+
+ private final String mLookupKey;
+
private final long mDataId;
private final RecipientEntry mEntry;
@@ -39,6 +43,8 @@ class SimpleRecipientChip implements BaseRecipientChip {
mDisplay = entry.getDisplayName();
mValue = entry.getDestination().trim();
mContactId = entry.getContactId();
+ mDirectoryId = entry.getDirectoryId();
+ mLookupKey = entry.getLookupKey();
mDataId = entry.getDataId();
mEntry = entry;
}
@@ -69,6 +75,16 @@ class SimpleRecipientChip implements BaseRecipientChip {
}
@Override
+ public Long getDirectoryId() {
+ return mDirectoryId;
+ }
+
+ @Override
+ public String getLookupKey() {
+ return mLookupKey;
+ }
+
+ @Override
public long getDataId() {
return mDataId;
}
@@ -93,11 +109,6 @@ class SimpleRecipientChip implements BaseRecipientChip {
}
@Override
- public boolean isGalContact() {
- return mEntry.isGalContact();
- }
-
- @Override
public String toString() {
return mDisplay + " <" + mValue + ">";
}
diff --git a/chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java
index 4637f69..ce32e3d 100644
--- a/chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java
+++ b/chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java
@@ -63,6 +63,16 @@ public class VisibleRecipientChip extends ImageSpan implements DrawableRecipient
}
@Override
+ public Long getDirectoryId() {
+ return mDelegate.getDirectoryId();
+ }
+
+ @Override
+ public String getLookupKey() {
+ return mDelegate.getLookupKey();
+ }
+
+ @Override
public long getDataId() {
return mDelegate.getDataId();
}
@@ -83,11 +93,6 @@ public class VisibleRecipientChip extends ImageSpan implements DrawableRecipient
}
@Override
- public boolean isGalContact() {
- return mDelegate.isGalContact();
- }
-
- @Override
public Rect getBounds() {
return getDrawable().getBounds();
}