Loading src/com/android/contacts/activities/ContactEditorActivity.java +4 −4 Original line number Diff line number Diff line Loading @@ -304,10 +304,10 @@ public class ContactEditorActivity extends ContactsActivity implements } @Override public void onEditOtherContactRequested( Uri contactLookupUri, ArrayList<ContentValues> values) { final Intent intent = EditorIntents.createEditOtherContactIntent( ContactEditorActivity.this, contactLookupUri, values); public void onEditOtherRawContactRequested( Uri contactLookupUri, long rawContactId, ArrayList<ContentValues> values) { final Intent intent = EditorIntents.createEditOtherRawContactIntent( ContactEditorActivity.this, contactLookupUri, rawContactId, values); ImplicitIntentsUtil.startActivityInApp( ContactEditorActivity.this, intent); finish(); Loading src/com/android/contacts/editor/AggregationSuggestionEngine.java +66 −145 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.os.Process; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.Nickname; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.Photo; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts.AggregationSuggestions; Loading @@ -41,6 +40,8 @@ import android.text.TextUtils; import com.android.contacts.common.model.ValuesDelta; import com.android.contacts.common.model.account.AccountWithDataSet; import com.android.contacts.compat.AggregationSuggestionsCompat; import com.google.common.base.Objects; import com.google.common.collect.Lists; import java.util.ArrayList; Loading @@ -57,36 +58,26 @@ public class AggregationSuggestionEngine extends HandlerThread { void onAggregationSuggestionChange(); } public static final class RawContact { public long rawContactId; public String accountType; public String accountName; public String dataSet; @Override public String toString() { return "ID: " + rawContactId + " account: " + accountType + "/" + accountName + " dataSet: " + dataSet; } } public static final class Suggestion { public long contactId; public long photoId; public String lookupKey; public String contactLookupKey; public long rawContactId; public String name; public String phoneNumber; public String emailAddress; public String nickname; public byte[] photo; public List<RawContact> rawContacts; @Override public String toString() { return "ID: " + contactId + " rawContacts: " + rawContacts + " name: " + name + " phone: " + phoneNumber + " email: " + emailAddress + " nickname: " + nickname + (photo != null ? " [has photo]" : ""); return Objects.toStringHelper(Suggestion.class) .add("contactId", contactId) .add("contactLookupKey", contactLookupKey) .add("rawContactId", rawContactId) .add("name", name) .add("phoneNumber", phoneNumber) .add("emailAddress", emailAddress) .add("nickname", nickname) .toString(); } } Loading @@ -107,10 +98,11 @@ public class AggregationSuggestionEngine extends HandlerThread { private static final long SUGGESTION_LOOKUP_DELAY_MILLIS = 300; private static final int SUGGESTIONS_LIMIT = 3; private final Context mContext; private long[] mSuggestedContactIds = new long[0]; private Handler mMainHandler; private Handler mHandler; private long mContactId; Loading @@ -119,8 +111,6 @@ public class AggregationSuggestionEngine extends HandlerThread { private Cursor mDataCursor; private ContentObserver mContentObserver; private Uri mSuggestionsUri; private int mSuggestionsLimit = 3; private boolean mPruneInvisibleContacts = false; public AggregationSuggestionEngine(Context context) { super("AggregationSuggestions", Process.THREAD_PRIORITY_BACKGROUND); Loading Loading @@ -156,14 +146,6 @@ public class AggregationSuggestionEngine extends HandlerThread { mAccountFilter = account; } public void setSuggestionsLimit(int suggestionsLimit) { mSuggestionsLimit = suggestionsLimit; } public void setPruneInvisibleContacts (boolean pruneInvisibleContacts) { mPruneInvisibleContacts = pruneInvisibleContacts; } public void setListener(Listener listener) { mListener = listener; } Loading Loading @@ -238,7 +220,7 @@ public class AggregationSuggestionEngine extends HandlerThread { // AggregationSuggestions.Builder() became visible in API level 23, so use it if applicable. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { final Builder uriBuilder = new AggregationSuggestions.Builder() .setLimit(mSuggestionsLimit) .setLimit(SUGGESTIONS_LIMIT) .setContactId(mContactId); if (nameSb.length() != 0) { uriBuilder.addNameParameter(nameSb.toString()); Loading @@ -252,7 +234,7 @@ public class AggregationSuggestionEngine extends HandlerThread { // For previous SDKs, use the backup plan. final AggregationSuggestionsCompat.Builder uriBuilder = new AggregationSuggestionsCompat.Builder() .setLimit(mSuggestionsLimit) .setLimit(SUGGESTIONS_LIMIT) .setContactId(mContactId); if (nameSb.length() != 0) { uriBuilder.addNameParameter(nameSb.toString()); Loading Loading @@ -291,39 +273,30 @@ public class AggregationSuggestionEngine extends HandlerThread { + Phone.CONTENT_ITEM_TYPE + "','" + Email.CONTENT_ITEM_TYPE + "','" + StructuredName.CONTENT_ITEM_TYPE + "','" + Nickname.CONTENT_ITEM_TYPE + "','" + Photo.CONTENT_ITEM_TYPE + "')" + Nickname.CONTENT_ITEM_TYPE + "')" + " AND " + Data.CONTACT_ID + " IN ("; public static final String[] COLUMNS = { Data._ID, Data.CONTACT_ID, Data.LOOKUP_KEY, Data.PHOTO_ID, Data.DISPLAY_NAME, Data.RAW_CONTACT_ID, Data.MIMETYPE, Data.DATA1, Data.IS_SUPER_PRIMARY, Photo.PHOTO, RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_NAME, RawContacts.DATA_SET }; public static final int ID = 0; public static final int CONTACT_ID = 1; public static final int LOOKUP_KEY = 2; public static final int PHOTO_ID = 3; public static final int DISPLAY_NAME = 4; public static final int RAW_CONTACT_ID = 5; public static final int MIMETYPE = 6; public static final int DATA1 = 7; public static final int IS_SUPERPRIMARY = 8; public static final int PHOTO = 9; public static final int ACCOUNT_TYPE = 10; public static final int ACCOUNT_NAME = 11; public static final int DATA_SET = 12; public static final int CONTACT_ID = 0; public static final int LOOKUP_KEY = 1; public static final int RAW_CONTACT_ID = 2; public static final int MIMETYPE = 3; public static final int DATA1 = 4; public static final int IS_SUPERPRIMARY = 5; public static final int ACCOUNT_TYPE = 6; public static final int ACCOUNT_NAME = 7; public static final int DATA_SET = 8; } private void loadAggregationSuggestions(Uri uri) { Loading Loading @@ -352,12 +325,12 @@ public class AggregationSuggestionEngine extends HandlerThread { sb.append(mSuggestedContactIds[i]); } sb.append(')'); sb.toString(); Cursor dataCursor = contentResolver.query(Data.CONTENT_URI, DataQuery.COLUMNS, sb.toString(), null, Data.CONTACT_ID); if (dataCursor != null) { mMainHandler.sendMessage(mMainHandler.obtainMessage(MESSAGE_DATA_CURSOR, dataCursor)); mMainHandler.sendMessage( mMainHandler.obtainMessage(MESSAGE_DATA_CURSOR, dataCursor)); } } finally { cursor.close(); Loading @@ -370,8 +343,7 @@ public class AggregationSuggestionEngine extends HandlerThread { final ArrayList<Long> newIds = new ArrayList<Long>(count); while (cursor.moveToNext()) { final long contactId = cursor.getLong(0); if (!changed && Arrays.binarySearch(mSuggestedContactIds, contactId) < 0) { if (!changed && Arrays.binarySearch(mSuggestedContactIds, contactId) < 0) { changed = true; } newIds.add(contactId); Loading Loading @@ -404,110 +376,59 @@ public class AggregationSuggestionEngine extends HandlerThread { } public List<Suggestion> getSuggestions() { final ArrayList<Long> visibleContacts = new ArrayList<>(); if (mPruneInvisibleContacts) { final Uri contactFilterUri = Data.CONTENT_URI.buildUpon() .appendQueryParameter(Data.VISIBLE_CONTACTS_ONLY, "true") .build(); final ContentResolver contentResolver = mContext.getContentResolver(); final Cursor contactCursor = contentResolver.query(contactFilterUri, new String[]{Data.CONTACT_ID}, null, null, null); try { if (contactCursor != null) { while (contactCursor.moveToNext()) { final long contactId = contactCursor.getLong(0); visibleContacts.add(contactId); } } } finally { contactCursor.close(); } } final ArrayList<Suggestion> list = Lists.newArrayList(); ArrayList<Suggestion> list = Lists.newArrayList(); if (mDataCursor != null) { if (mDataCursor != null && mAccountFilter != null) { Suggestion suggestion = null; long currentContactId = -1; long currentRawContactId = -1; mDataCursor.moveToPosition(-1); while (mDataCursor.moveToNext()) { long contactId = mDataCursor.getLong(DataQuery.CONTACT_ID); if (mPruneInvisibleContacts && !visibleContacts.contains(contactId)) { continue; } if (contactId != currentContactId) { final long rawContactId = mDataCursor.getLong(DataQuery.RAW_CONTACT_ID); if (rawContactId != currentRawContactId) { suggestion = new Suggestion(); suggestion.contactId = contactId; suggestion.name = mDataCursor.getString(DataQuery.DISPLAY_NAME); suggestion.lookupKey = mDataCursor.getString(DataQuery.LOOKUP_KEY); suggestion.rawContacts = Lists.newArrayList(); // No restriction, add all suggestions. if (mAccountFilter == null) { list.add(suggestion); } currentContactId = contactId; } long rawContactId = mDataCursor.getLong(DataQuery.RAW_CONTACT_ID); if (!containsRawContact(suggestion, rawContactId)) { RawContact rawContact = new RawContact(); rawContact.rawContactId = rawContactId; rawContact.accountName = mDataCursor.getString(DataQuery.ACCOUNT_NAME); rawContact.accountType = mDataCursor.getString(DataQuery.ACCOUNT_TYPE); rawContact.dataSet = mDataCursor.getString(DataQuery.DATA_SET); suggestion.rawContactId = rawContactId; suggestion.contactId = mDataCursor.getLong(DataQuery.CONTACT_ID); suggestion.contactLookupKey = mDataCursor.getString(DataQuery.LOOKUP_KEY); final String accountName = mDataCursor.getString(DataQuery.ACCOUNT_NAME); final String accountType = mDataCursor.getString(DataQuery.ACCOUNT_TYPE); final String dataSet = mDataCursor.getString(DataQuery.DATA_SET); final AccountWithDataSet account = new AccountWithDataSet( rawContact.accountName, rawContact.accountType, rawContact.dataSet); // If we're restricting to a certain account, only add the suggestion if // it has a raw contact from that account. if (mAccountFilter != null && mAccountFilter.equals(account) && !list.contains(suggestion)) { accountName, accountType, dataSet); if (mAccountFilter.equals(account)) { list.add(suggestion); } suggestion.rawContacts.add(rawContact); currentRawContactId = rawContactId; } String mimetype = mDataCursor.getString(DataQuery.MIMETYPE); final String mimetype = mDataCursor.getString(DataQuery.MIMETYPE); if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); final String data = mDataCursor.getString(DataQuery.DATA1); int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.phoneNumber == null)) { suggestion.phoneNumber = data; } } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); final String data = mDataCursor.getString(DataQuery.DATA1); int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.emailAddress == null)) { suggestion.emailAddress = data; } } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); final String data = mDataCursor.getString(DataQuery.DATA1); if (!TextUtils.isEmpty(data)) { suggestion.nickname = data; } } else if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) { long dataId = mDataCursor.getLong(DataQuery.ID); long photoId = mDataCursor.getLong(DataQuery.PHOTO_ID); if (dataId == photoId && !mDataCursor.isNull(DataQuery.PHOTO)) { suggestion.photo = mDataCursor.getBlob(DataQuery.PHOTO); suggestion.photoId = photoId; } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) { // DATA1 stores the display name for the raw contact. final String data = mDataCursor.getString(DataQuery.DATA1); if (!TextUtils.isEmpty(data) && suggestion.name == null) { suggestion.name = data; } } } } return list; } public boolean containsRawContact(Suggestion suggestion, long rawContactId) { if (suggestion.rawContacts != null) { int count = suggestion.rawContacts.size(); for (int i = 0; i < count; i++) { if (suggestion.rawContacts.get(i).rawContactId == rawContactId) { return true; } } } return false; } } src/com/android/contacts/editor/AggregationSuggestionView.java +26 −74 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ package com.android.contacts.editor; import android.content.ContentUris; import android.content.Context; import android.graphics.BitmapFactory; import android.net.Uri; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; import android.text.TextUtils; import android.util.AttributeSet; Loading @@ -28,16 +29,8 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.android.contacts.R; import com.android.contacts.editor.AggregationSuggestionEngine.RawContact; import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.account.AccountType; import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; /** * A view that contains a name, picture and other data for a contact aggregation suggestion. Loading @@ -45,25 +38,15 @@ import java.util.List; public class AggregationSuggestionView extends LinearLayout { public interface Listener { /** * Callback that passes the contact ID to join with and, for convenience, * also the list of constituent raw contact IDs to avoid a separate query * for those. */ public void onJoinAction(long contactId, List<Long> rawContacIds); /** * Callback that passes the contact ID to edit instead of the current contact. * Callback that passes the contact URI and raw contact ID to edit instead of the * current contact. */ public void onEditAction(Uri contactLookupUri); void onEditAction(Uri contactLookupUri, long rawContactId); } private Listener mListener; private long mContactId; private String mLookupKey; private List<RawContact> mRawContacts = Lists.newArrayList(); private boolean mNewContact; private Suggestion mSuggestion; public AggregationSuggestionView(Context context) { super(context); Loading @@ -77,22 +60,21 @@ public class AggregationSuggestionView extends LinearLayout { super(context, attrs, defStyle); } public void setNewContact(boolean flag) { mNewContact = flag; } public void bindSuggestion(Suggestion suggestion) { mContactId = suggestion.contactId; mLookupKey = suggestion.lookupKey; mRawContacts = suggestion.rawContacts; ImageView photo = (ImageView) findViewById(R.id.aggregation_suggestion_photo); if (suggestion.photo != null) { photo.setImageBitmap(BitmapFactory.decodeByteArray( suggestion.photo, 0, suggestion.photo.length)); } else { photo.setImageDrawable(ContactPhotoManager.getDefaultAvatarDrawableForContact( getResources(), false, null)); } mSuggestion = suggestion; final ContactPhotoManager.DefaultImageRequest request = new ContactPhotoManager.DefaultImageRequest( suggestion.name, String.valueOf(suggestion.rawContactId), /* isCircular = */ false); final Uri photoUri = Uri.withAppendedPath(ContentUris.withAppendedId( ContactsContract.RawContacts.CONTENT_URI, suggestion.rawContactId), ContactsContract.RawContacts.DisplayPhoto.CONTENT_DIRECTORY); final ImageView photoView = (ImageView) findViewById( R.id.aggregation_suggestion_photo); ContactPhotoManager.getInstance(getContext()).loadDirectoryPhoto(photoView, photoUri, /* darkTheme = */ false, /* isCircular = */ false, request); TextView name = (TextView) findViewById(R.id.aggregation_suggestion_name); name.setText(suggestion.name); Loading @@ -111,48 +93,18 @@ public class AggregationSuggestionView extends LinearLayout { data.setText(dataText); } /** * Returns true if the suggested contact can be edited. */ private boolean canEditSuggestedContact() { if (!mNewContact) { return false; } AccountTypeManager accountTypes = AccountTypeManager.getInstance(getContext()); for (RawContact rawContact : mRawContacts) { String accountType = rawContact.accountType; String dataSet = rawContact.dataSet; if (accountType == null) { return true; } AccountType type = accountTypes.getAccountType(accountType, dataSet); if (type.areContactsWritable()) { return true; } } return false; } public void setListener(Listener listener) { mListener = listener; } public boolean handleItemClickEvent() { if (mListener != null && isEnabled()) { if (canEditSuggestedContact()) { if (TextUtils.isEmpty(mLookupKey)) { if (TextUtils.isEmpty(mSuggestion.contactLookupKey)) { return false; } mListener.onEditAction(Contacts.getLookupUri(mContactId, mLookupKey)); } else { ArrayList<Long> rawContactIds = Lists.newArrayList(); for (RawContact rawContact : mRawContacts) { rawContactIds.add(rawContact.rawContactId); } mListener.onJoinAction(mContactId, rawContactIds); } mListener.onEditAction( Contacts.getLookupUri(mSuggestion.contactId, mSuggestion.contactLookupKey), mSuggestion.rawContactId); return true; } return false; Loading Loading
src/com/android/contacts/activities/ContactEditorActivity.java +4 −4 Original line number Diff line number Diff line Loading @@ -304,10 +304,10 @@ public class ContactEditorActivity extends ContactsActivity implements } @Override public void onEditOtherContactRequested( Uri contactLookupUri, ArrayList<ContentValues> values) { final Intent intent = EditorIntents.createEditOtherContactIntent( ContactEditorActivity.this, contactLookupUri, values); public void onEditOtherRawContactRequested( Uri contactLookupUri, long rawContactId, ArrayList<ContentValues> values) { final Intent intent = EditorIntents.createEditOtherRawContactIntent( ContactEditorActivity.this, contactLookupUri, rawContactId, values); ImplicitIntentsUtil.startActivityInApp( ContactEditorActivity.this, intent); finish(); Loading
src/com/android/contacts/editor/AggregationSuggestionEngine.java +66 −145 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.os.Process; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.Nickname; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.Photo; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts.AggregationSuggestions; Loading @@ -41,6 +40,8 @@ import android.text.TextUtils; import com.android.contacts.common.model.ValuesDelta; import com.android.contacts.common.model.account.AccountWithDataSet; import com.android.contacts.compat.AggregationSuggestionsCompat; import com.google.common.base.Objects; import com.google.common.collect.Lists; import java.util.ArrayList; Loading @@ -57,36 +58,26 @@ public class AggregationSuggestionEngine extends HandlerThread { void onAggregationSuggestionChange(); } public static final class RawContact { public long rawContactId; public String accountType; public String accountName; public String dataSet; @Override public String toString() { return "ID: " + rawContactId + " account: " + accountType + "/" + accountName + " dataSet: " + dataSet; } } public static final class Suggestion { public long contactId; public long photoId; public String lookupKey; public String contactLookupKey; public long rawContactId; public String name; public String phoneNumber; public String emailAddress; public String nickname; public byte[] photo; public List<RawContact> rawContacts; @Override public String toString() { return "ID: " + contactId + " rawContacts: " + rawContacts + " name: " + name + " phone: " + phoneNumber + " email: " + emailAddress + " nickname: " + nickname + (photo != null ? " [has photo]" : ""); return Objects.toStringHelper(Suggestion.class) .add("contactId", contactId) .add("contactLookupKey", contactLookupKey) .add("rawContactId", rawContactId) .add("name", name) .add("phoneNumber", phoneNumber) .add("emailAddress", emailAddress) .add("nickname", nickname) .toString(); } } Loading @@ -107,10 +98,11 @@ public class AggregationSuggestionEngine extends HandlerThread { private static final long SUGGESTION_LOOKUP_DELAY_MILLIS = 300; private static final int SUGGESTIONS_LIMIT = 3; private final Context mContext; private long[] mSuggestedContactIds = new long[0]; private Handler mMainHandler; private Handler mHandler; private long mContactId; Loading @@ -119,8 +111,6 @@ public class AggregationSuggestionEngine extends HandlerThread { private Cursor mDataCursor; private ContentObserver mContentObserver; private Uri mSuggestionsUri; private int mSuggestionsLimit = 3; private boolean mPruneInvisibleContacts = false; public AggregationSuggestionEngine(Context context) { super("AggregationSuggestions", Process.THREAD_PRIORITY_BACKGROUND); Loading Loading @@ -156,14 +146,6 @@ public class AggregationSuggestionEngine extends HandlerThread { mAccountFilter = account; } public void setSuggestionsLimit(int suggestionsLimit) { mSuggestionsLimit = suggestionsLimit; } public void setPruneInvisibleContacts (boolean pruneInvisibleContacts) { mPruneInvisibleContacts = pruneInvisibleContacts; } public void setListener(Listener listener) { mListener = listener; } Loading Loading @@ -238,7 +220,7 @@ public class AggregationSuggestionEngine extends HandlerThread { // AggregationSuggestions.Builder() became visible in API level 23, so use it if applicable. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { final Builder uriBuilder = new AggregationSuggestions.Builder() .setLimit(mSuggestionsLimit) .setLimit(SUGGESTIONS_LIMIT) .setContactId(mContactId); if (nameSb.length() != 0) { uriBuilder.addNameParameter(nameSb.toString()); Loading @@ -252,7 +234,7 @@ public class AggregationSuggestionEngine extends HandlerThread { // For previous SDKs, use the backup plan. final AggregationSuggestionsCompat.Builder uriBuilder = new AggregationSuggestionsCompat.Builder() .setLimit(mSuggestionsLimit) .setLimit(SUGGESTIONS_LIMIT) .setContactId(mContactId); if (nameSb.length() != 0) { uriBuilder.addNameParameter(nameSb.toString()); Loading Loading @@ -291,39 +273,30 @@ public class AggregationSuggestionEngine extends HandlerThread { + Phone.CONTENT_ITEM_TYPE + "','" + Email.CONTENT_ITEM_TYPE + "','" + StructuredName.CONTENT_ITEM_TYPE + "','" + Nickname.CONTENT_ITEM_TYPE + "','" + Photo.CONTENT_ITEM_TYPE + "')" + Nickname.CONTENT_ITEM_TYPE + "')" + " AND " + Data.CONTACT_ID + " IN ("; public static final String[] COLUMNS = { Data._ID, Data.CONTACT_ID, Data.LOOKUP_KEY, Data.PHOTO_ID, Data.DISPLAY_NAME, Data.RAW_CONTACT_ID, Data.MIMETYPE, Data.DATA1, Data.IS_SUPER_PRIMARY, Photo.PHOTO, RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_NAME, RawContacts.DATA_SET }; public static final int ID = 0; public static final int CONTACT_ID = 1; public static final int LOOKUP_KEY = 2; public static final int PHOTO_ID = 3; public static final int DISPLAY_NAME = 4; public static final int RAW_CONTACT_ID = 5; public static final int MIMETYPE = 6; public static final int DATA1 = 7; public static final int IS_SUPERPRIMARY = 8; public static final int PHOTO = 9; public static final int ACCOUNT_TYPE = 10; public static final int ACCOUNT_NAME = 11; public static final int DATA_SET = 12; public static final int CONTACT_ID = 0; public static final int LOOKUP_KEY = 1; public static final int RAW_CONTACT_ID = 2; public static final int MIMETYPE = 3; public static final int DATA1 = 4; public static final int IS_SUPERPRIMARY = 5; public static final int ACCOUNT_TYPE = 6; public static final int ACCOUNT_NAME = 7; public static final int DATA_SET = 8; } private void loadAggregationSuggestions(Uri uri) { Loading Loading @@ -352,12 +325,12 @@ public class AggregationSuggestionEngine extends HandlerThread { sb.append(mSuggestedContactIds[i]); } sb.append(')'); sb.toString(); Cursor dataCursor = contentResolver.query(Data.CONTENT_URI, DataQuery.COLUMNS, sb.toString(), null, Data.CONTACT_ID); if (dataCursor != null) { mMainHandler.sendMessage(mMainHandler.obtainMessage(MESSAGE_DATA_CURSOR, dataCursor)); mMainHandler.sendMessage( mMainHandler.obtainMessage(MESSAGE_DATA_CURSOR, dataCursor)); } } finally { cursor.close(); Loading @@ -370,8 +343,7 @@ public class AggregationSuggestionEngine extends HandlerThread { final ArrayList<Long> newIds = new ArrayList<Long>(count); while (cursor.moveToNext()) { final long contactId = cursor.getLong(0); if (!changed && Arrays.binarySearch(mSuggestedContactIds, contactId) < 0) { if (!changed && Arrays.binarySearch(mSuggestedContactIds, contactId) < 0) { changed = true; } newIds.add(contactId); Loading Loading @@ -404,110 +376,59 @@ public class AggregationSuggestionEngine extends HandlerThread { } public List<Suggestion> getSuggestions() { final ArrayList<Long> visibleContacts = new ArrayList<>(); if (mPruneInvisibleContacts) { final Uri contactFilterUri = Data.CONTENT_URI.buildUpon() .appendQueryParameter(Data.VISIBLE_CONTACTS_ONLY, "true") .build(); final ContentResolver contentResolver = mContext.getContentResolver(); final Cursor contactCursor = contentResolver.query(contactFilterUri, new String[]{Data.CONTACT_ID}, null, null, null); try { if (contactCursor != null) { while (contactCursor.moveToNext()) { final long contactId = contactCursor.getLong(0); visibleContacts.add(contactId); } } } finally { contactCursor.close(); } } final ArrayList<Suggestion> list = Lists.newArrayList(); ArrayList<Suggestion> list = Lists.newArrayList(); if (mDataCursor != null) { if (mDataCursor != null && mAccountFilter != null) { Suggestion suggestion = null; long currentContactId = -1; long currentRawContactId = -1; mDataCursor.moveToPosition(-1); while (mDataCursor.moveToNext()) { long contactId = mDataCursor.getLong(DataQuery.CONTACT_ID); if (mPruneInvisibleContacts && !visibleContacts.contains(contactId)) { continue; } if (contactId != currentContactId) { final long rawContactId = mDataCursor.getLong(DataQuery.RAW_CONTACT_ID); if (rawContactId != currentRawContactId) { suggestion = new Suggestion(); suggestion.contactId = contactId; suggestion.name = mDataCursor.getString(DataQuery.DISPLAY_NAME); suggestion.lookupKey = mDataCursor.getString(DataQuery.LOOKUP_KEY); suggestion.rawContacts = Lists.newArrayList(); // No restriction, add all suggestions. if (mAccountFilter == null) { list.add(suggestion); } currentContactId = contactId; } long rawContactId = mDataCursor.getLong(DataQuery.RAW_CONTACT_ID); if (!containsRawContact(suggestion, rawContactId)) { RawContact rawContact = new RawContact(); rawContact.rawContactId = rawContactId; rawContact.accountName = mDataCursor.getString(DataQuery.ACCOUNT_NAME); rawContact.accountType = mDataCursor.getString(DataQuery.ACCOUNT_TYPE); rawContact.dataSet = mDataCursor.getString(DataQuery.DATA_SET); suggestion.rawContactId = rawContactId; suggestion.contactId = mDataCursor.getLong(DataQuery.CONTACT_ID); suggestion.contactLookupKey = mDataCursor.getString(DataQuery.LOOKUP_KEY); final String accountName = mDataCursor.getString(DataQuery.ACCOUNT_NAME); final String accountType = mDataCursor.getString(DataQuery.ACCOUNT_TYPE); final String dataSet = mDataCursor.getString(DataQuery.DATA_SET); final AccountWithDataSet account = new AccountWithDataSet( rawContact.accountName, rawContact.accountType, rawContact.dataSet); // If we're restricting to a certain account, only add the suggestion if // it has a raw contact from that account. if (mAccountFilter != null && mAccountFilter.equals(account) && !list.contains(suggestion)) { accountName, accountType, dataSet); if (mAccountFilter.equals(account)) { list.add(suggestion); } suggestion.rawContacts.add(rawContact); currentRawContactId = rawContactId; } String mimetype = mDataCursor.getString(DataQuery.MIMETYPE); final String mimetype = mDataCursor.getString(DataQuery.MIMETYPE); if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); final String data = mDataCursor.getString(DataQuery.DATA1); int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.phoneNumber == null)) { suggestion.phoneNumber = data; } } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); final String data = mDataCursor.getString(DataQuery.DATA1); int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.emailAddress == null)) { suggestion.emailAddress = data; } } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); final String data = mDataCursor.getString(DataQuery.DATA1); if (!TextUtils.isEmpty(data)) { suggestion.nickname = data; } } else if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) { long dataId = mDataCursor.getLong(DataQuery.ID); long photoId = mDataCursor.getLong(DataQuery.PHOTO_ID); if (dataId == photoId && !mDataCursor.isNull(DataQuery.PHOTO)) { suggestion.photo = mDataCursor.getBlob(DataQuery.PHOTO); suggestion.photoId = photoId; } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) { // DATA1 stores the display name for the raw contact. final String data = mDataCursor.getString(DataQuery.DATA1); if (!TextUtils.isEmpty(data) && suggestion.name == null) { suggestion.name = data; } } } } return list; } public boolean containsRawContact(Suggestion suggestion, long rawContactId) { if (suggestion.rawContacts != null) { int count = suggestion.rawContacts.size(); for (int i = 0; i < count; i++) { if (suggestion.rawContacts.get(i).rawContactId == rawContactId) { return true; } } } return false; } }
src/com/android/contacts/editor/AggregationSuggestionView.java +26 −74 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ package com.android.contacts.editor; import android.content.ContentUris; import android.content.Context; import android.graphics.BitmapFactory; import android.net.Uri; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; import android.text.TextUtils; import android.util.AttributeSet; Loading @@ -28,16 +29,8 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.android.contacts.R; import com.android.contacts.editor.AggregationSuggestionEngine.RawContact; import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.account.AccountType; import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; /** * A view that contains a name, picture and other data for a contact aggregation suggestion. Loading @@ -45,25 +38,15 @@ import java.util.List; public class AggregationSuggestionView extends LinearLayout { public interface Listener { /** * Callback that passes the contact ID to join with and, for convenience, * also the list of constituent raw contact IDs to avoid a separate query * for those. */ public void onJoinAction(long contactId, List<Long> rawContacIds); /** * Callback that passes the contact ID to edit instead of the current contact. * Callback that passes the contact URI and raw contact ID to edit instead of the * current contact. */ public void onEditAction(Uri contactLookupUri); void onEditAction(Uri contactLookupUri, long rawContactId); } private Listener mListener; private long mContactId; private String mLookupKey; private List<RawContact> mRawContacts = Lists.newArrayList(); private boolean mNewContact; private Suggestion mSuggestion; public AggregationSuggestionView(Context context) { super(context); Loading @@ -77,22 +60,21 @@ public class AggregationSuggestionView extends LinearLayout { super(context, attrs, defStyle); } public void setNewContact(boolean flag) { mNewContact = flag; } public void bindSuggestion(Suggestion suggestion) { mContactId = suggestion.contactId; mLookupKey = suggestion.lookupKey; mRawContacts = suggestion.rawContacts; ImageView photo = (ImageView) findViewById(R.id.aggregation_suggestion_photo); if (suggestion.photo != null) { photo.setImageBitmap(BitmapFactory.decodeByteArray( suggestion.photo, 0, suggestion.photo.length)); } else { photo.setImageDrawable(ContactPhotoManager.getDefaultAvatarDrawableForContact( getResources(), false, null)); } mSuggestion = suggestion; final ContactPhotoManager.DefaultImageRequest request = new ContactPhotoManager.DefaultImageRequest( suggestion.name, String.valueOf(suggestion.rawContactId), /* isCircular = */ false); final Uri photoUri = Uri.withAppendedPath(ContentUris.withAppendedId( ContactsContract.RawContacts.CONTENT_URI, suggestion.rawContactId), ContactsContract.RawContacts.DisplayPhoto.CONTENT_DIRECTORY); final ImageView photoView = (ImageView) findViewById( R.id.aggregation_suggestion_photo); ContactPhotoManager.getInstance(getContext()).loadDirectoryPhoto(photoView, photoUri, /* darkTheme = */ false, /* isCircular = */ false, request); TextView name = (TextView) findViewById(R.id.aggregation_suggestion_name); name.setText(suggestion.name); Loading @@ -111,48 +93,18 @@ public class AggregationSuggestionView extends LinearLayout { data.setText(dataText); } /** * Returns true if the suggested contact can be edited. */ private boolean canEditSuggestedContact() { if (!mNewContact) { return false; } AccountTypeManager accountTypes = AccountTypeManager.getInstance(getContext()); for (RawContact rawContact : mRawContacts) { String accountType = rawContact.accountType; String dataSet = rawContact.dataSet; if (accountType == null) { return true; } AccountType type = accountTypes.getAccountType(accountType, dataSet); if (type.areContactsWritable()) { return true; } } return false; } public void setListener(Listener listener) { mListener = listener; } public boolean handleItemClickEvent() { if (mListener != null && isEnabled()) { if (canEditSuggestedContact()) { if (TextUtils.isEmpty(mLookupKey)) { if (TextUtils.isEmpty(mSuggestion.contactLookupKey)) { return false; } mListener.onEditAction(Contacts.getLookupUri(mContactId, mLookupKey)); } else { ArrayList<Long> rawContactIds = Lists.newArrayList(); for (RawContact rawContact : mRawContacts) { rawContactIds.add(rawContact.rawContactId); } mListener.onJoinAction(mContactId, rawContactIds); } mListener.onEditAction( Contacts.getLookupUri(mSuggestion.contactId, mSuggestion.contactLookupKey), mSuggestion.rawContactId); return true; } return false; Loading