SuggestedMemberListAdapter.java revision 2b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbc
1c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan/* 2c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * Copyright (C) 2011 The Android Open Source Project 3c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * 4c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * Licensed under the Apache License, Version 2.0 (the "License"); 5c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * you may not use this file except in compliance with the License. 6c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * You may obtain a copy of the License at 7c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * 8c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * http://www.apache.org/licenses/LICENSE-2.0 9c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * 10c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * Unless required by applicable law or agreed to in writing, software 11c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * distributed under the License is distributed on an "AS IS" BASIS, 12c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * See the License for the specific language governing permissions and 14c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * limitations under the License. 15c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan */ 16c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanpackage com.android.contacts.group; 17c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 18c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport com.android.contacts.R; 19c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember; 20c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 21c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.content.ContentResolver; 22c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.content.Context; 23c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.database.Cursor; 24c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.graphics.Bitmap; 25c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.graphics.BitmapFactory; 26c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Email; 27c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Phone; 28c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Photo; 29c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.provider.ContactsContract.Contacts.Data; 30c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.provider.ContactsContract.RawContacts; 31c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.provider.ContactsContract.RawContactsEntity; 32c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.text.TextUtils; 33c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.view.LayoutInflater; 34c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.view.View; 35c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.view.ViewGroup; 36c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.widget.ArrayAdapter; 37c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.widget.AutoCompleteTextView; 38c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.widget.Filter; 39c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.widget.ImageView; 40c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport android.widget.TextView; 41c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 42c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport java.util.ArrayList; 43c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport java.util.Arrays; 44c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport java.util.HashMap; 45c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanimport java.util.List; 46c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 47c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan/** 48c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * This adapter provides suggested contacts that can be added to a group for an 49c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * {@link AutoCompleteTextView} within the group editor. 50c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan */ 51c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuanpublic class SuggestedMemberListAdapter extends ArrayAdapter<SuggestedMember> { 52c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 53c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final String[] PROJECTION_FILTERED_MEMBERS = new String[] { 54c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts._ID, // 0 55c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts.CONTACT_ID, // 1 56c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts.DISPLAY_NAME_PRIMARY // 2 57c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan }; 58c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 59c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final int RAW_CONTACT_ID_COLUMN_INDEX = 0; 60c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final int CONTACT_ID_COLUMN_INDEX = 1; 61c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final int DISPLAY_NAME_PRIMARY_COLUMN_INDEX = 2; 62c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 63c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final String[] PROJECTION_MEMBER_DATA = new String[] { 64c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts._ID, // 0 65c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts.CONTACT_ID, // 1 66c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Data.MIMETYPE, // 2 67c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Data.DATA1, // 3 68c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Photo.PHOTO, // 4 69c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan }; 70c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 71c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final int MIMETYPE_COLUMN_INDEX = 2; 72c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final int DATA_COLUMN_INDEX = 3; 73c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final int PHOTO_COLUMN_INDEX = 4; 74c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 75c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private Filter mFilter; 76c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private ContentResolver mContentResolver; 77c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private LayoutInflater mInflater; 78c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 79c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private String mAccountType = ""; 80c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private String mAccountName = ""; 812b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private String mDataSet = ""; 82c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 832d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan // TODO: Make this a Map for better performance when we check if a new contact is in the list 842d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan // or not 85c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private List<Long> mExistingMemberContactIds = new ArrayList<Long>(); 86c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 87c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private static final int SUGGESTIONS_LIMIT = 5; 88c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 89c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public SuggestedMemberListAdapter(Context context, int textViewResourceId) { 90c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan super(context, textViewResourceId); 91c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 92c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 93c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 94c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void setAccountType(String accountType) { 95c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mAccountType = accountType; 96c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 97c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 98c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void setAccountName(String accountName) { 99c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mAccountName = accountName; 100c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 101c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 1022b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public void setDataSet(String dataSet) { 1032b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mDataSet = dataSet; 1042b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 1052b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro 106c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void setContentResolver(ContentResolver resolver) { 107c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mContentResolver = resolver; 108c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 109c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 110c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void updateExistingMembersList(List<Long> listContactIds) { 111c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mExistingMemberContactIds = listContactIds; 112c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 113c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 114c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void addNewMember(long contactId) { 115c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mExistingMemberContactIds.add(contactId); 116c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 117c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 118c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void removeMember(long contactId) { 119c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (mExistingMemberContactIds.contains(contactId)) { 120c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mExistingMemberContactIds.remove(contactId); 121c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 122c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 123c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 124c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan @Override 125c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public View getView(int position, View convertView, ViewGroup parent) { 126c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan View result = convertView; 127c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (result == null) { 128c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan result = mInflater.inflate(R.layout.group_member_suggestion, parent, false); 129c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 130c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // TODO: Use a viewholder 131c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan SuggestedMember member = getItem(position); 132c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan TextView text1 = (TextView) result.findViewById(R.id.text1); 133c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan TextView text2 = (TextView) result.findViewById(R.id.text2); 134c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan ImageView icon = (ImageView) result.findViewById(R.id.icon); 135c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan text1.setText(member.getDisplayName()); 136c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (member.hasExtraInfo()) { 137c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan text2.setText(member.getExtraInfo()); 138c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } else { 139c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan text2.setVisibility(View.GONE); 140c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 141c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan byte[] byteArray = member.getPhotoByteArray(); 142c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (byteArray == null) { 143c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan icon.setImageResource(R.drawable.ic_contact_picture); 144c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 145c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan else { 146c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 147c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan icon.setImageBitmap(bitmap); 148c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 149c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return result; 150c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 151c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 152c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan @Override 153c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public Filter getFilter() { 154c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (mFilter == null) { 155c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mFilter = new SuggestedMemberFilter(); 156c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 157c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return mFilter; 158c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 159c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 160c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan /** 161c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * This filter queries for raw contacts that match the given account name and account type, 162c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * as well as the search query. 163c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan */ 164c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public class SuggestedMemberFilter extends Filter { 165c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 166c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan @Override 167c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan protected FilterResults performFiltering(CharSequence prefix) { 168c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan FilterResults results = new FilterResults(); 169c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (mContentResolver == null || TextUtils.isEmpty(prefix)) { 170c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return results; 171c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 172c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 173c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Map of raw contact IDs to {@link SuggestedMember} objects 174c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan HashMap<Long, SuggestedMember> suggestionsMap = new HashMap<Long, SuggestedMember>(); 175c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 176c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // First query for all the raw contacts that match the given search query 177c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // and have the same account name and type as specified in this adapter 178c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan String searchQuery = prefix.toString() + "%"; 1792b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String accountClause = RawContacts.ACCOUNT_NAME + "=? AND " + 1802b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro RawContacts.ACCOUNT_TYPE + "=?"; 1812b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String[] args; 1822b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro if (mDataSet == null) { 1832b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro accountClause += " AND " + RawContacts.DATA_SET + " IS NULL"; 1842b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro args = new String[] {mAccountName, mAccountType, searchQuery, searchQuery}; 1852b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } else { 1862b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro accountClause += " AND " + RawContacts.DATA_SET + "=?"; 1872b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro args = new String[] { 1882b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mAccountName, mAccountType, mDataSet, searchQuery, searchQuery 1892b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro }; 1902b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 1912b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro 192c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Cursor cursor = mContentResolver.query( 193c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts.CONTENT_URI, PROJECTION_FILTERED_MEMBERS, 1942b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro accountClause + " AND (" + 195c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts.DISPLAY_NAME_PRIMARY + " LIKE ? OR " + 196c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContacts.DISPLAY_NAME_ALTERNATIVE + " LIKE ? )", 1972b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro args, null); 198c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 199c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (cursor == null) { 200c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return results; 201c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 202c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 203c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Read back the results from the cursor and filter out existing group members. 204c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // For valid suggestions, add them to the hash map of suggested members. 205c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan try { 206c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan cursor.moveToPosition(-1); 207c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan while (cursor.moveToNext() && suggestionsMap.keySet().size() < SUGGESTIONS_LIMIT) { 2082d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan long rawContactId = cursor.getLong(RAW_CONTACT_ID_COLUMN_INDEX); 209c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan long contactId = cursor.getLong(CONTACT_ID_COLUMN_INDEX); 210c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Filter out contacts that have already been added to this group 211c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (mExistingMemberContactIds.contains(contactId)) { 212c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan continue; 213c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 214c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Otherwise, add the contact as a suggested new group member 215c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan String displayName = cursor.getString(DISPLAY_NAME_PRIMARY_COLUMN_INDEX); 2162d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan suggestionsMap.put(rawContactId, new SuggestedMember(rawContactId, 2172d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan displayName, contactId)); 218c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 219c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } finally { 220c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan cursor.close(); 221c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 222c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 223c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan int numSuggestions = suggestionsMap.keySet().size(); 224c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (numSuggestions == 0) { 225c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return results; 226c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 227c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 228c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Create a part of the selection string for the next query with the pattern (?, ?, ?) 229c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // where the number of comma-separated question marks represent the number of raw 230c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // contact IDs found in the previous query (while respective the SUGGESTION_LIMIT) 231c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan final StringBuilder rawContactIdSelectionBuilder = new StringBuilder(); 232c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan final String[] questionMarks = new String[numSuggestions]; 233c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Arrays.fill(questionMarks, "?"); 234c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan rawContactIdSelectionBuilder.append(RawContacts._ID + " IN (") 235c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan .append(TextUtils.join(",", questionMarks)) 236c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan .append(")"); 237c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 238c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Construct the selection args based on the raw contact IDs we're interested in 239c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // (as well as the photo, email, and phone mimetypes) 240c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan List<String> selectionArgs = new ArrayList<String>(); 241c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan selectionArgs.add(Photo.CONTENT_ITEM_TYPE); 242c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan selectionArgs.add(Email.CONTENT_ITEM_TYPE); 243c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan selectionArgs.add(Phone.CONTENT_ITEM_TYPE); 244c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan for (Long rawContactId : suggestionsMap.keySet()) { 245c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan selectionArgs.add(String.valueOf(rawContactId)); 246c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 247c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 248c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Perform a second query to retrieve a photo and possibly a phone number or email 249c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // address for the suggested contact 250c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Cursor memberDataCursor = mContentResolver.query( 251c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan RawContactsEntity.CONTENT_URI, PROJECTION_MEMBER_DATA, 252c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan "(" + Data.MIMETYPE + "=? OR " + Data.MIMETYPE + "=? OR " + Data.MIMETYPE + 253c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan "=?) AND " + rawContactIdSelectionBuilder.toString(), 254c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan selectionArgs.toArray(new String[0]), null); 255c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 256c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan try { 257c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan memberDataCursor.moveToPosition(-1); 258c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan while (memberDataCursor.moveToNext()) { 259c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan long rawContactId = memberDataCursor.getLong(RAW_CONTACT_ID_COLUMN_INDEX); 260c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan SuggestedMember member = suggestionsMap.get(rawContactId); 261c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (member == null) { 262c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan continue; 263c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 264c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan String mimetype = memberDataCursor.getString(MIMETYPE_COLUMN_INDEX); 265c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) { 266c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Set photo 267c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan byte[] bitmapArray = memberDataCursor.getBlob(PHOTO_COLUMN_INDEX); 268c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan member.setPhotoByteArray(bitmapArray); 269c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype) || 270c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { 271c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Set at most 1 extra piece of contact info that can be a phone number or 272c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // email 273c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (!member.hasExtraInfo()) { 274c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan String info = memberDataCursor.getString(DATA_COLUMN_INDEX); 275c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan member.setExtraInfo(info); 276c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 277c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 278c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 279c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } finally { 280c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan memberDataCursor.close(); 281c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 282c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan results.values = suggestionsMap; 283c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return results; 284c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 285c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 286c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan @Override 287c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan protected void publishResults(CharSequence constraint, FilterResults results) { 288c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan HashMap<Long, SuggestedMember> map = (HashMap<Long, SuggestedMember>) results.values; 289c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan if (map == null || map.keySet() == null) { 290c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return; 291c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 292c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 293c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Clear out the existing suggestions in this adapter 294c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan clear(); 295c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 296c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // Add all the suggested members to this adapter 297c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan for (SuggestedMember member : map.values()) { 298c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan add(member); 299c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 300c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 301c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan notifyDataSetChanged(); 302c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 303c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 304c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 305c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan /** 306c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * This represents a single contact that is a suggestion for the user to add to a group. 307c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan */ 3082d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan // TODO: Merge this with the {@link GroupEditorFragment} Member class once we can find the 3092d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan // lookup URI for this contact using the autocomplete filter queries 310c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public class SuggestedMember { 311c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 3122d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan private long mRawContactId; 313c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private long mContactId; 314c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private String mDisplayName; 315c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private String mExtraInfo; 316c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan private byte[] mPhoto; 317c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 3182d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan public SuggestedMember(long rawContactId, String displayName, long contactId) { 3192d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan mRawContactId = rawContactId; 320c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mDisplayName = displayName; 321c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mContactId = contactId; 322c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 323c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 324c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public String getDisplayName() { 325c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return mDisplayName; 326c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 327c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 328c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public String getExtraInfo() { 329c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return mExtraInfo; 330c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 331c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 3322d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan public long getRawContactId() { 3332d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan return mRawContactId; 3342d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan } 3352d851cc895ffc7afd322298c7d4391ca5bea1a2dKatherine Kuan 336c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public long getContactId() { 337c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return mContactId; 338c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 339c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 340c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public byte[] getPhotoByteArray() { 341c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return mPhoto; 342c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 343c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 344c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public boolean hasExtraInfo() { 345c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan return mExtraInfo != null; 346c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 347c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 348c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan /** 349c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan * Set a phone number or email to distinguish this contact 350c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan */ 351c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void setExtraInfo(String info) { 352c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mExtraInfo = info; 353c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 354c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan 355c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan public void setPhotoByteArray(byte[] photo) { 356c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan mPhoto = photo; 357c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 358c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan } 359c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan} 360