Loading src/com/android/contacts/T9Search.java +143 −45 Original line number Diff line number Diff line Loading @@ -33,10 +33,14 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.preference.PreferenceManager; import android.provider.ContactsContract.CommonDataKinds.Nickname; import android.provider.ContactsContract.CommonDataKinds.Organization; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.telephony.PhoneNumberUtils; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; Loading @@ -58,25 +62,33 @@ class T9Search { private static final int NAME_FIRST = 1; private static final int NUMBER_FIRST = 2; // Phone number queries private static final String[] PHONE_PROJECTION = new String[] { // Phone number, nickname, organization query private static final String[] DATA_PROJECTION = new String[] { Data.CONTACT_ID, Data.MIMETYPE, Phone.NUMBER, Phone.CONTACT_ID, Phone.IS_SUPER_PRIMARY, Phone.TYPE, Phone.LABEL Phone.LABEL, Organization.COMPANY, Nickname.NAME }; private static final int PHONE_COLUMN_NUMBER = 0; private static final int PHONE_COLUMN_CONTACT = 1; private static final int PHONE_COLUMN_PRIMARY = 2; private static final int PHONE_COLUMN_TYPE = 3; private static final int PHONE_COLUMN_LABEL = 4; private static final String PHONE_ID_SELECTION = Contacts.Data.MIMETYPE + " = ? "; private static final String[] PHONE_ID_SELECTION_ARGS = new String[] { Phone.CONTENT_ITEM_TYPE private static final int DATA_COLUMN_CONTACT = 0; private static final int DATA_COLUMN_MIMETYPE = 1; private static final int DATA_COLUMN_PHONENUMBER = 2; private static final int DATA_COLUMN_PRIMARY = 3; private static final int DATA_COLUMN_PHONETYPE = 4; private static final int DATA_COLUMN_PHONELABEL = 5; private static final int DATA_COLUMN_ORGANIZATION = 6; private static final int DATA_COLUMN_NICKNAME = 7; private static final String DATA_SELECTION = Data.MIMETYPE + " = ? or " + Data.MIMETYPE + " = ? or " + Data.MIMETYPE + " = ?"; private static final String[] DATA_SELECTION_ARGS = new String[] { Phone.CONTENT_ITEM_TYPE, Organization.CONTENT_ITEM_TYPE, Nickname.CONTENT_ITEM_TYPE }; private static final String PHONE_SORT = Phone.CONTACT_ID + " ASC"; private static final String DATA_SORT = Data.CONTACT_ID + " ASC"; private static final String[] CONTACT_PROJECTION = new String[] { Contacts._ID, Loading Loading @@ -125,37 +137,62 @@ class T9Search { Cursor contact = mContext.getContentResolver().query( Contacts.CONTENT_URI, CONTACT_PROJECTION, CONTACT_QUERY, null, CONTACT_SORT); Cursor phone = mContext.getContentResolver().query( Phone.CONTENT_URI, PHONE_PROJECTION, PHONE_ID_SELECTION, PHONE_ID_SELECTION_ARGS, PHONE_SORT); Cursor data = mContext.getContentResolver().query( Data.CONTENT_URI, DATA_PROJECTION, DATA_SELECTION, DATA_SELECTION_ARGS, DATA_SORT); phone.moveToFirst(); data.moveToFirst(); while (contact.moveToNext()) { long contactId = contact.getLong(CONTACT_COLUMN_ID); String contactName = contact.getString(CONTACT_COLUMN_NAME); String nickName = null, organization = null; int contactContactedCount = contact.getInt(CONTACT_COLUMN_CONTACTED); ArrayList<ContactItem> contactItems = new ArrayList<ContactItem>(); while (!phone.isAfterLast() && phone.getLong(PHONE_COLUMN_CONTACT) == contactId) { String num = phone.getString(PHONE_COLUMN_NUMBER); while (!data.isAfterLast() && data.getLong(DATA_COLUMN_CONTACT) < contactId) { data.moveToNext(); } while (!data.isAfterLast() && data.getLong(DATA_COLUMN_CONTACT) == contactId) { final String mimeType = data.getString(DATA_COLUMN_MIMETYPE); if (TextUtils.equals(mimeType, Phone.CONTENT_ITEM_TYPE)) { String num = data.getString(DATA_COLUMN_PHONENUMBER); ContactItem contactInfo = new BitmapContactItem(); contactInfo.id = contactId; contactInfo.name = contactName; contactInfo.number = PhoneNumberUtils.formatNumber(num); contactInfo.normalNumber = removeNonDigits(num); contactInfo.normalName = nameToNumber(contactName); contactInfo.timesContacted = contactContactedCount; contactInfo.isSuperPrimary = phone.getInt(PHONE_COLUMN_PRIMARY) > 0; contactInfo.isSuperPrimary = data.getInt(DATA_COLUMN_PRIMARY) > 0; contactInfo.groupType = Phone.getTypeLabel(mContext.getResources(), phone.getInt(PHONE_COLUMN_TYPE), phone.getString(PHONE_COLUMN_LABEL)); mContacts.add(contactInfo); phone.moveToNext(); data.getInt(DATA_COLUMN_PHONETYPE), data.getString(DATA_COLUMN_PHONELABEL)); contactItems.add(contactInfo); } else if (TextUtils.equals(mimeType, Organization.CONTENT_ITEM_TYPE)) { organization = data.getString(DATA_COLUMN_ORGANIZATION); } else if (TextUtils.equals(mimeType, Nickname.CONTENT_ITEM_TYPE)) { nickName = data.getString(DATA_COLUMN_NICKNAME); } data.moveToNext(); } String contactName = contact.getString(CONTACT_COLUMN_NAME); String normalName = nameToNumber(contactName); String normalNickName = nickName != null ? nameToNumber(nickName) : null; String normalOrganization = organization != null ? nameToNumber(organization) : null; for (ContactItem item : contactItems) { item.name = contactName; item.normalName = normalName; item.nickName = nickName; item.normalNickName = normalNickName; item.organization = organization; item.normalOrganization = normalOrganization; mContacts.add(item); } } contact.close(); phone.close(); data.close(); return null; } Loading Loading @@ -193,11 +230,17 @@ class T9Search { public static class ContactItem { String name; String nickName; String organization; String number; String normalNumber; String normalName; String normalNickName; String normalOrganization; int timesContacted; int nameMatchId; int nickNameMatchId; int organizationMatchId; int numberMatchId; CharSequence groupType; long id; Loading Loading @@ -241,6 +284,9 @@ class T9Search { for (ContactItem item : (newQuery ? mContacts : mAllResults)) { item.numberMatchId = -1; item.nameMatchId = -1; item.nickNameMatchId = -1; item.organizationMatchId = -1; pos = item.normalNumber.indexOf(number); if (pos != -1) { item.numberMatchId = pos; Loading @@ -253,6 +299,28 @@ class T9Search { lastSpace = 0; } item.nameMatchId = pos - lastSpace; } if (item.normalNickName != null) { pos = item.normalNickName.indexOf(number); if (pos != -1) { int lastSpace = item.normalNickName.lastIndexOf("0", pos); if (lastSpace == -1) { lastSpace = 0; } item.nickNameMatchId = pos - lastSpace; } } if (item.normalOrganization != null) { pos = item.normalOrganization.indexOf(number); if (pos != -1) { int lastSpace = item.normalOrganization.lastIndexOf("0", pos); if (lastSpace == -1) { lastSpace = 0; } item.organizationMatchId = pos - lastSpace; } } if (item.nameMatchId >= 0 || item.nickNameMatchId >= 0 || item.organizationMatchId >= 0) { nameResults.add(item); } } Loading Loading @@ -290,6 +358,8 @@ class T9Search { @Override public int compare(ContactItem lhs, ContactItem rhs) { int ret = compareInt(lhs.nameMatchId, rhs.nameMatchId); if (ret == 0) ret = compareInt(lhs.nickNameMatchId, rhs.nickNameMatchId); if (ret == 0) ret = compareInt(lhs.organizationMatchId, rhs.organizationMatchId); if (ret == 0) ret = compareInt(rhs.timesContacted, lhs.timesContacted); if (ret == 0) ret = compareBool(rhs.isSuperPrimary, lhs.isSuperPrimary); return ret; Loading Loading @@ -394,26 +464,54 @@ class T9Search { holder.icon.setImageResource(R.drawable.sym_action_add); holder.icon.assignContactFromPhone(o.number, true); } else { holder.name.setText(o.name, TextView.BufferType.SPANNABLE); holder.number.setText(o.normalNumber + " (" + o.groupType + ")", TextView.BufferType.SPANNABLE); holder.number.setVisibility(View.VISIBLE); SpannableStringBuilder nameBuilder = new SpannableStringBuilder(); nameBuilder.append(o.name); if (o.nameMatchId != -1) { Spannable s = (Spannable) holder.name.getText(); int nameStart = o.normalName.indexOf(mPrevInput); s.setSpan(new ForegroundColorSpan(Color.WHITE), nameBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), nameStart, nameStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); holder.name.setText(s); } if (!TextUtils.isEmpty(o.nickName)) { nameBuilder.append(" ("); nameBuilder.append(o.nickName); nameBuilder.append(")"); if (o.nickNameMatchId != -1) { int nickNameStart = o.normalNickName.indexOf(mPrevInput) + nameBuilder.length() - o.nickName.length() - 1; nameBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), nickNameStart, nickNameStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } } if (!TextUtils.isEmpty(o.organization)) { nameBuilder.append(" - "); nameBuilder.append(o.organization); if (o.organizationMatchId != -1) { int organizationStart = o.normalOrganization.indexOf(mPrevInput) + nameBuilder.length() - o.organization.length(); nameBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), organizationStart, organizationStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } } SpannableStringBuilder numberBuilder = new SpannableStringBuilder(); numberBuilder.append(o.normalNumber); numberBuilder.append(" ("); numberBuilder.append(o.groupType); numberBuilder.append(")"); if (o.numberMatchId != -1) { Spannable s = (Spannable) holder.number.getText(); int numberStart = o.numberMatchId; s.setSpan(new ForegroundColorSpan(Color.WHITE), numberBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), numberStart, numberStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); holder.number.setText(s); } holder.name.setText(nameBuilder); holder.number.setText(numberBuilder); holder.number.setVisibility(View.VISIBLE); Bitmap photo = o.getPhoto(); if (photo != null) { holder.icon.setImageBitmap(photo); Loading Loading
src/com/android/contacts/T9Search.java +143 −45 Original line number Diff line number Diff line Loading @@ -33,10 +33,14 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.preference.PreferenceManager; import android.provider.ContactsContract.CommonDataKinds.Nickname; import android.provider.ContactsContract.CommonDataKinds.Organization; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.telephony.PhoneNumberUtils; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; Loading @@ -58,25 +62,33 @@ class T9Search { private static final int NAME_FIRST = 1; private static final int NUMBER_FIRST = 2; // Phone number queries private static final String[] PHONE_PROJECTION = new String[] { // Phone number, nickname, organization query private static final String[] DATA_PROJECTION = new String[] { Data.CONTACT_ID, Data.MIMETYPE, Phone.NUMBER, Phone.CONTACT_ID, Phone.IS_SUPER_PRIMARY, Phone.TYPE, Phone.LABEL Phone.LABEL, Organization.COMPANY, Nickname.NAME }; private static final int PHONE_COLUMN_NUMBER = 0; private static final int PHONE_COLUMN_CONTACT = 1; private static final int PHONE_COLUMN_PRIMARY = 2; private static final int PHONE_COLUMN_TYPE = 3; private static final int PHONE_COLUMN_LABEL = 4; private static final String PHONE_ID_SELECTION = Contacts.Data.MIMETYPE + " = ? "; private static final String[] PHONE_ID_SELECTION_ARGS = new String[] { Phone.CONTENT_ITEM_TYPE private static final int DATA_COLUMN_CONTACT = 0; private static final int DATA_COLUMN_MIMETYPE = 1; private static final int DATA_COLUMN_PHONENUMBER = 2; private static final int DATA_COLUMN_PRIMARY = 3; private static final int DATA_COLUMN_PHONETYPE = 4; private static final int DATA_COLUMN_PHONELABEL = 5; private static final int DATA_COLUMN_ORGANIZATION = 6; private static final int DATA_COLUMN_NICKNAME = 7; private static final String DATA_SELECTION = Data.MIMETYPE + " = ? or " + Data.MIMETYPE + " = ? or " + Data.MIMETYPE + " = ?"; private static final String[] DATA_SELECTION_ARGS = new String[] { Phone.CONTENT_ITEM_TYPE, Organization.CONTENT_ITEM_TYPE, Nickname.CONTENT_ITEM_TYPE }; private static final String PHONE_SORT = Phone.CONTACT_ID + " ASC"; private static final String DATA_SORT = Data.CONTACT_ID + " ASC"; private static final String[] CONTACT_PROJECTION = new String[] { Contacts._ID, Loading Loading @@ -125,37 +137,62 @@ class T9Search { Cursor contact = mContext.getContentResolver().query( Contacts.CONTENT_URI, CONTACT_PROJECTION, CONTACT_QUERY, null, CONTACT_SORT); Cursor phone = mContext.getContentResolver().query( Phone.CONTENT_URI, PHONE_PROJECTION, PHONE_ID_SELECTION, PHONE_ID_SELECTION_ARGS, PHONE_SORT); Cursor data = mContext.getContentResolver().query( Data.CONTENT_URI, DATA_PROJECTION, DATA_SELECTION, DATA_SELECTION_ARGS, DATA_SORT); phone.moveToFirst(); data.moveToFirst(); while (contact.moveToNext()) { long contactId = contact.getLong(CONTACT_COLUMN_ID); String contactName = contact.getString(CONTACT_COLUMN_NAME); String nickName = null, organization = null; int contactContactedCount = contact.getInt(CONTACT_COLUMN_CONTACTED); ArrayList<ContactItem> contactItems = new ArrayList<ContactItem>(); while (!phone.isAfterLast() && phone.getLong(PHONE_COLUMN_CONTACT) == contactId) { String num = phone.getString(PHONE_COLUMN_NUMBER); while (!data.isAfterLast() && data.getLong(DATA_COLUMN_CONTACT) < contactId) { data.moveToNext(); } while (!data.isAfterLast() && data.getLong(DATA_COLUMN_CONTACT) == contactId) { final String mimeType = data.getString(DATA_COLUMN_MIMETYPE); if (TextUtils.equals(mimeType, Phone.CONTENT_ITEM_TYPE)) { String num = data.getString(DATA_COLUMN_PHONENUMBER); ContactItem contactInfo = new BitmapContactItem(); contactInfo.id = contactId; contactInfo.name = contactName; contactInfo.number = PhoneNumberUtils.formatNumber(num); contactInfo.normalNumber = removeNonDigits(num); contactInfo.normalName = nameToNumber(contactName); contactInfo.timesContacted = contactContactedCount; contactInfo.isSuperPrimary = phone.getInt(PHONE_COLUMN_PRIMARY) > 0; contactInfo.isSuperPrimary = data.getInt(DATA_COLUMN_PRIMARY) > 0; contactInfo.groupType = Phone.getTypeLabel(mContext.getResources(), phone.getInt(PHONE_COLUMN_TYPE), phone.getString(PHONE_COLUMN_LABEL)); mContacts.add(contactInfo); phone.moveToNext(); data.getInt(DATA_COLUMN_PHONETYPE), data.getString(DATA_COLUMN_PHONELABEL)); contactItems.add(contactInfo); } else if (TextUtils.equals(mimeType, Organization.CONTENT_ITEM_TYPE)) { organization = data.getString(DATA_COLUMN_ORGANIZATION); } else if (TextUtils.equals(mimeType, Nickname.CONTENT_ITEM_TYPE)) { nickName = data.getString(DATA_COLUMN_NICKNAME); } data.moveToNext(); } String contactName = contact.getString(CONTACT_COLUMN_NAME); String normalName = nameToNumber(contactName); String normalNickName = nickName != null ? nameToNumber(nickName) : null; String normalOrganization = organization != null ? nameToNumber(organization) : null; for (ContactItem item : contactItems) { item.name = contactName; item.normalName = normalName; item.nickName = nickName; item.normalNickName = normalNickName; item.organization = organization; item.normalOrganization = normalOrganization; mContacts.add(item); } } contact.close(); phone.close(); data.close(); return null; } Loading Loading @@ -193,11 +230,17 @@ class T9Search { public static class ContactItem { String name; String nickName; String organization; String number; String normalNumber; String normalName; String normalNickName; String normalOrganization; int timesContacted; int nameMatchId; int nickNameMatchId; int organizationMatchId; int numberMatchId; CharSequence groupType; long id; Loading Loading @@ -241,6 +284,9 @@ class T9Search { for (ContactItem item : (newQuery ? mContacts : mAllResults)) { item.numberMatchId = -1; item.nameMatchId = -1; item.nickNameMatchId = -1; item.organizationMatchId = -1; pos = item.normalNumber.indexOf(number); if (pos != -1) { item.numberMatchId = pos; Loading @@ -253,6 +299,28 @@ class T9Search { lastSpace = 0; } item.nameMatchId = pos - lastSpace; } if (item.normalNickName != null) { pos = item.normalNickName.indexOf(number); if (pos != -1) { int lastSpace = item.normalNickName.lastIndexOf("0", pos); if (lastSpace == -1) { lastSpace = 0; } item.nickNameMatchId = pos - lastSpace; } } if (item.normalOrganization != null) { pos = item.normalOrganization.indexOf(number); if (pos != -1) { int lastSpace = item.normalOrganization.lastIndexOf("0", pos); if (lastSpace == -1) { lastSpace = 0; } item.organizationMatchId = pos - lastSpace; } } if (item.nameMatchId >= 0 || item.nickNameMatchId >= 0 || item.organizationMatchId >= 0) { nameResults.add(item); } } Loading Loading @@ -290,6 +358,8 @@ class T9Search { @Override public int compare(ContactItem lhs, ContactItem rhs) { int ret = compareInt(lhs.nameMatchId, rhs.nameMatchId); if (ret == 0) ret = compareInt(lhs.nickNameMatchId, rhs.nickNameMatchId); if (ret == 0) ret = compareInt(lhs.organizationMatchId, rhs.organizationMatchId); if (ret == 0) ret = compareInt(rhs.timesContacted, lhs.timesContacted); if (ret == 0) ret = compareBool(rhs.isSuperPrimary, lhs.isSuperPrimary); return ret; Loading Loading @@ -394,26 +464,54 @@ class T9Search { holder.icon.setImageResource(R.drawable.sym_action_add); holder.icon.assignContactFromPhone(o.number, true); } else { holder.name.setText(o.name, TextView.BufferType.SPANNABLE); holder.number.setText(o.normalNumber + " (" + o.groupType + ")", TextView.BufferType.SPANNABLE); holder.number.setVisibility(View.VISIBLE); SpannableStringBuilder nameBuilder = new SpannableStringBuilder(); nameBuilder.append(o.name); if (o.nameMatchId != -1) { Spannable s = (Spannable) holder.name.getText(); int nameStart = o.normalName.indexOf(mPrevInput); s.setSpan(new ForegroundColorSpan(Color.WHITE), nameBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), nameStart, nameStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); holder.name.setText(s); } if (!TextUtils.isEmpty(o.nickName)) { nameBuilder.append(" ("); nameBuilder.append(o.nickName); nameBuilder.append(")"); if (o.nickNameMatchId != -1) { int nickNameStart = o.normalNickName.indexOf(mPrevInput) + nameBuilder.length() - o.nickName.length() - 1; nameBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), nickNameStart, nickNameStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } } if (!TextUtils.isEmpty(o.organization)) { nameBuilder.append(" - "); nameBuilder.append(o.organization); if (o.organizationMatchId != -1) { int organizationStart = o.normalOrganization.indexOf(mPrevInput) + nameBuilder.length() - o.organization.length(); nameBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), organizationStart, organizationStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } } SpannableStringBuilder numberBuilder = new SpannableStringBuilder(); numberBuilder.append(o.normalNumber); numberBuilder.append(" ("); numberBuilder.append(o.groupType); numberBuilder.append(")"); if (o.numberMatchId != -1) { Spannable s = (Spannable) holder.number.getText(); int numberStart = o.numberMatchId; s.setSpan(new ForegroundColorSpan(Color.WHITE), numberBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), numberStart, numberStart + mPrevInput.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); holder.number.setText(s); } holder.name.setText(nameBuilder); holder.number.setText(numberBuilder); holder.number.setVisibility(View.VISIBLE); Bitmap photo = o.getPhoto(); if (photo != null) { holder.icon.setImageBitmap(photo); Loading