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