RecipientAlternatesAdapter.java revision a11c2b0e1ea043aa4d8745285f2dcbe20448b417
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.ex.chips; 18 19import com.android.ex.chips.BaseRecipientAdapter.EmailQuery; 20 21import android.content.Context; 22import android.database.Cursor; 23import android.provider.ContactsContract.CommonDataKinds.Email; 24import android.text.util.Rfc822Token; 25import android.text.util.Rfc822Tokenizer; 26import android.util.Log; 27import android.view.LayoutInflater; 28import android.view.View; 29import android.view.ViewGroup; 30import android.widget.CursorAdapter; 31import android.widget.ImageView; 32import android.widget.TextView; 33 34import java.util.HashMap; 35 36public class RecipientAlternatesAdapter extends CursorAdapter { 37 static final int MAX_LOOKUPS = 50; 38 private final LayoutInflater mLayoutInflater; 39 40 private final long mCurrentId; 41 42 private int mCheckedItemPosition = -1; 43 44 private OnCheckedItemChangedListener mCheckedItemChangedListener; 45 46 private static final String TAG = "RecipAlternates"; 47 48 /** 49 * Get a HashMap of address to RecipientEntry that contains all contact 50 * information for a contact with the provided address, if one exists. This 51 * may block the UI, so run it in an async task. 52 * 53 * @param context Context. 54 * @param inAddresses Array of addresses on which to perform the lookup. 55 * @return HashMap<String,RecipientEntry> 56 */ 57 public static HashMap<String, RecipientEntry> getMatchingRecipients(Context context, 58 String[] inAddresses) { 59 int addressesSize = Math.min(MAX_LOOKUPS, inAddresses.length); 60 String[] addresses = new String[addressesSize]; 61 StringBuilder bindString = new StringBuilder(); 62 // Create the "?" string and set up arguments. 63 for (int i = 0; i < addressesSize; i++) { 64 Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses[i].toLowerCase()); 65 addresses[i] = (tokens.length > 0 ? tokens[0].getAddress() : inAddresses[i]); 66 bindString.append("?"); 67 if (i < addressesSize - 1) { 68 bindString.append(","); 69 } 70 } 71 72 if (Log.isLoggable(TAG, Log.DEBUG)) { 73 Log.d(TAG, "Doing reverse lookup for " + addresses.toString()); 74 } 75 76 HashMap<String, RecipientEntry> recipientEntries = new HashMap<String, RecipientEntry>(); 77 Cursor c = context.getContentResolver().query(Email.CONTENT_URI, EmailQuery.PROJECTION, 78 Email.ADDRESS + " IN (" + bindString.toString() + ")", addresses, null); 79 if (c != null) { 80 try { 81 if (c.moveToFirst()) { 82 do { 83 String address = c.getString(EmailQuery.ADDRESS); 84 recipientEntries.put(address, RecipientEntry.constructTopLevelEntry( 85 c.getString(EmailQuery.NAME), 86 c.getString(EmailQuery.ADDRESS), 87 c.getInt(EmailQuery.ADDRESS_TYPE), 88 c.getString(EmailQuery.ADDRESS_LABEL), 89 c.getLong(EmailQuery.CONTACT_ID), 90 c.getLong(EmailQuery.DATA_ID), 91 c.getString(EmailQuery.PHOTO_THUMBNAIL_URI))); 92 if (Log.isLoggable(TAG, Log.DEBUG)) { 93 Log.d(TAG, "Received reverse look up information for " + address 94 + " RESULTS: " 95 + " NAME : " + c.getString(EmailQuery.NAME) 96 + " CONTACT ID : " + c.getLong(EmailQuery.CONTACT_ID) 97 + " ADDRESS :" + c.getString(EmailQuery.ADDRESS)); 98 } 99 } while (c.moveToNext()); 100 } 101 } finally { 102 c.close(); 103 } 104 } 105 return recipientEntries; 106 } 107 108 public RecipientAlternatesAdapter(Context context, long contactId, long currentId, int viewId, 109 OnCheckedItemChangedListener listener) { 110 super(context, context.getContentResolver().query(Email.CONTENT_URI, EmailQuery.PROJECTION, 111 Email.CONTACT_ID + " =?", new String[] { 112 String.valueOf(contactId) 113 }, null), 0); 114 mLayoutInflater = LayoutInflater.from(context); 115 mCurrentId = currentId; 116 mCheckedItemChangedListener = listener; 117 } 118 119 @Override 120 public long getItemId(int position) { 121 Cursor c = getCursor(); 122 if (c.moveToPosition(position)) { 123 c.getLong(EmailQuery.DATA_ID); 124 } 125 return -1; 126 } 127 128 public RecipientEntry getRecipientEntry(int position) { 129 Cursor c = getCursor(); 130 c.moveToPosition(position); 131 return RecipientEntry.constructTopLevelEntry(c.getString(EmailQuery.NAME), 132 c.getString(EmailQuery.ADDRESS), c.getInt(EmailQuery.ADDRESS_TYPE), 133 c.getString(EmailQuery.ADDRESS_LABEL), 134 c.getLong(EmailQuery.CONTACT_ID), c.getLong(EmailQuery.DATA_ID), 135 c.getString(EmailQuery.PHOTO_THUMBNAIL_URI)); 136 } 137 138 @Override 139 public View getView(int position, View convertView, ViewGroup parent) { 140 Cursor cursor = getCursor(); 141 cursor.moveToPosition(position); 142 if (convertView == null) { 143 convertView = newView(); 144 } 145 if (cursor.getLong(EmailQuery.DATA_ID) == mCurrentId) { 146 mCheckedItemPosition = position; 147 if (mCheckedItemChangedListener != null) { 148 mCheckedItemChangedListener.onCheckedItemChanged(mCheckedItemPosition); 149 } 150 } 151 bindView(convertView, convertView.getContext(), cursor); 152 return convertView; 153 } 154 155 // TODO: this is VERY similar to the BaseRecipientAdapter. Can we combine 156 // somehow? 157 @Override 158 public void bindView(View view, Context context, Cursor cursor) { 159 int position = cursor.getPosition(); 160 161 TextView display = (TextView) view.findViewById(android.R.id.title); 162 ImageView imageView = (ImageView) view.findViewById(android.R.id.icon); 163 RecipientEntry entry = getRecipientEntry(position); 164 if (position == 0) { 165 display.setText(cursor.getString(EmailQuery.NAME)); 166 display.setVisibility(View.VISIBLE); 167 // TODO: see if this needs to be done outside the main thread 168 // as it may be too slow to get immediately. 169 imageView.setImageURI(entry.getPhotoThumbnailUri()); 170 imageView.setVisibility(View.VISIBLE); 171 } else { 172 display.setVisibility(View.GONE); 173 imageView.setVisibility(View.GONE); 174 } 175 TextView destination = (TextView) view.findViewById(android.R.id.text1); 176 destination.setText(cursor.getString(EmailQuery.ADDRESS)); 177 178 TextView destinationType = (TextView) view.findViewById(android.R.id.text2); 179 if (destinationType != null) { 180 destinationType.setText(Email.getTypeLabel(context.getResources(), 181 cursor.getInt(EmailQuery.ADDRESS_TYPE), 182 cursor.getString(EmailQuery.ADDRESS_LABEL)).toString().toUpperCase()); 183 } 184 } 185 186 @Override 187 public View newView(Context context, Cursor cursor, ViewGroup parent) { 188 return newView(); 189 } 190 191 private View newView() { 192 return mLayoutInflater.inflate(R.layout.chips_recipient_dropdown_item, null); 193 } 194 195 /*package*/ static interface OnCheckedItemChangedListener { 196 public void onCheckedItemChanged(int position); 197 } 198} 199