Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2006 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.contacts; |
| 18 | |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 19 | import android.content.Context; |
| 20 | import android.database.Cursor; |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 21 | import android.graphics.drawable.Drawable; |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 22 | import android.net.Uri; |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 23 | import android.provider.ContactsContract.CommonDataKinds.Email; |
| 24 | import android.provider.ContactsContract.CommonDataKinds.Nickname; |
| 25 | import android.provider.ContactsContract.CommonDataKinds.Phone; |
| 26 | import android.provider.ContactsContract.CommonDataKinds.StructuredName; |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 27 | import android.provider.ContactsContract.Contacts.Data; |
Chiao Cheng | e0b2f1e | 2012-06-12 13:07:56 -0700 | [diff] [blame] | 28 | import android.provider.ContactsContract.RawContacts; |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 29 | import android.view.LayoutInflater; |
| 30 | import android.view.View; |
| 31 | import android.view.ViewGroup; |
| 32 | import android.widget.AdapterView; |
| 33 | import android.widget.ArrayAdapter; |
| 34 | import android.widget.ImageView; |
| 35 | import android.widget.ListView; |
| 36 | import android.widget.TextView; |
| 37 | |
Gary Mai | 69c182a | 2016-12-05 13:07:03 -0800 | [diff] [blame] | 38 | import com.android.contacts.model.AccountTypeManager; |
| 39 | import com.android.contacts.model.account.AccountType; |
Chiao Cheng | e0b2f1e | 2012-06-12 13:07:56 -0700 | [diff] [blame] | 40 | |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 41 | import java.util.ArrayList; |
| 42 | import java.util.Collections; |
| 43 | import java.util.HashMap; |
| 44 | import java.util.List; |
| 45 | |
| 46 | /** |
| 47 | * A list view for constituent contacts of an aggregate. Shows the contact name, source icon |
| 48 | * and additional data such as a nickname, email address or phone number, whichever |
| 49 | * is available. |
| 50 | */ |
| 51 | public class SplitAggregateView extends ListView { |
| 52 | |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 53 | private static final String TAG = "SplitAggregateView"; |
| 54 | |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 55 | private interface SplitQuery { |
| 56 | String[] COLUMNS = new String[] { |
Dave Santoro | 2b3f3c5 | 2011-07-26 17:35:42 -0700 | [diff] [blame] | 57 | Data.MIMETYPE, RawContacts.ACCOUNT_TYPE, RawContacts.DATA_SET, Data.RAW_CONTACT_ID, |
| 58 | Data.IS_PRIMARY, StructuredName.DISPLAY_NAME, Nickname.NAME, Email.DATA, |
| 59 | Phone.NUMBER |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 60 | }; |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 61 | |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 62 | int MIMETYPE = 0; |
| 63 | int ACCOUNT_TYPE = 1; |
Dave Santoro | 2b3f3c5 | 2011-07-26 17:35:42 -0700 | [diff] [blame] | 64 | int DATA_SET = 2; |
| 65 | int RAW_CONTACT_ID = 3; |
| 66 | int IS_PRIMARY = 4; |
| 67 | int DISPLAY_NAME = 5; |
| 68 | int NICKNAME = 6; |
| 69 | int EMAIL = 7; |
| 70 | int PHONE = 8; |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 71 | } |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 72 | |
| 73 | private final Uri mAggregateUri; |
| 74 | private OnContactSelectedListener mListener; |
Dmitri Plotnikov | a07fa5f | 2011-01-09 11:56:50 -0800 | [diff] [blame] | 75 | private AccountTypeManager mAccountTypes; |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 76 | |
| 77 | /** |
| 78 | * Listener interface that gets the contact ID of the user-selected contact. |
| 79 | */ |
| 80 | public interface OnContactSelectedListener { |
Dmitri Plotnikov | 99eafe7 | 2009-09-03 14:09:45 -0700 | [diff] [blame] | 81 | void onContactSelected(long rawContactId); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | /** |
| 85 | * Constructor. |
| 86 | */ |
| 87 | public SplitAggregateView(Context context, Uri aggregateUri) { |
| 88 | super(context); |
| 89 | |
| 90 | mAggregateUri = aggregateUri; |
| 91 | |
Dmitri Plotnikov | a07fa5f | 2011-01-09 11:56:50 -0800 | [diff] [blame] | 92 | mAccountTypes = AccountTypeManager.getInstance(context); |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 93 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 94 | final List<RawContactInfo> list = loadData(); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 95 | |
| 96 | setAdapter(new SplitAggregateAdapter(context, list)); |
| 97 | setOnItemClickListener(new OnItemClickListener() { |
| 98 | |
| 99 | public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
Dmitri Plotnikov | 99eafe7 | 2009-09-03 14:09:45 -0700 | [diff] [blame] | 100 | mListener.onContactSelected(list.get(position).rawContactId); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 101 | } |
| 102 | }); |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Sets a contact selection listener. |
| 107 | */ |
| 108 | public void setOnContactSelectedListener(OnContactSelectedListener listener) { |
| 109 | mListener = listener; |
| 110 | } |
| 111 | |
| 112 | /** |
| 113 | * Contact information loaded from the content provider. |
| 114 | */ |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 115 | private static class RawContactInfo implements Comparable<RawContactInfo> { |
Dmitri Plotnikov | 99eafe7 | 2009-09-03 14:09:45 -0700 | [diff] [blame] | 116 | final long rawContactId; |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 117 | String accountType; |
Dave Santoro | 2b3f3c5 | 2011-07-26 17:35:42 -0700 | [diff] [blame] | 118 | String dataSet; |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 119 | String name; |
| 120 | String phone; |
| 121 | String email; |
| 122 | String nickname; |
| 123 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 124 | public RawContactInfo(long rawContactId) { |
Dmitri Plotnikov | 99eafe7 | 2009-09-03 14:09:45 -0700 | [diff] [blame] | 125 | this.rawContactId = rawContactId; |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | public String getAdditionalData() { |
| 129 | if (nickname != null) { |
| 130 | return nickname; |
| 131 | } |
| 132 | |
| 133 | if (email != null) { |
| 134 | return email; |
| 135 | } |
| 136 | |
| 137 | if (phone != null) { |
| 138 | return phone; |
| 139 | } |
| 140 | |
| 141 | return ""; |
| 142 | } |
| 143 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 144 | public int compareTo(RawContactInfo another) { |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 145 | String thisAccount = accountType != null ? accountType : ""; |
| 146 | String thatAccount = another.accountType != null ? another.accountType : ""; |
| 147 | return thisAccount.compareTo(thatAccount); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 148 | } |
| 149 | } |
| 150 | |
| 151 | /** |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 152 | * Loads data from the content provider, organizes it into {@link RawContactInfo} objects |
| 153 | * and returns a sorted list of {@link RawContactInfo}'s. |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 154 | */ |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 155 | private List<RawContactInfo> loadData() { |
| 156 | HashMap<Long, RawContactInfo> rawContactInfos = new HashMap<Long, RawContactInfo>(); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 157 | Uri dataUri = Uri.withAppendedPath(mAggregateUri, Data.CONTENT_DIRECTORY); |
| 158 | Cursor cursor = getContext().getContentResolver().query(dataUri, |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 159 | SplitQuery.COLUMNS, null, null, null); |
Jay Shrauner | 13c42f4 | 2014-01-27 17:06:27 -0800 | [diff] [blame] | 160 | if (cursor == null) { |
| 161 | return Collections.emptyList(); |
| 162 | } |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 163 | try { |
| 164 | while (cursor.moveToNext()) { |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 165 | long rawContactId = cursor.getLong(SplitQuery.RAW_CONTACT_ID); |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 166 | RawContactInfo info = rawContactInfos.get(rawContactId); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 167 | if (info == null) { |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 168 | info = new RawContactInfo(rawContactId); |
| 169 | rawContactInfos.put(rawContactId, info); |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 170 | info.accountType = cursor.getString(SplitQuery.ACCOUNT_TYPE); |
Dave Santoro | 2b3f3c5 | 2011-07-26 17:35:42 -0700 | [diff] [blame] | 171 | info.dataSet = cursor.getString(SplitQuery.DATA_SET); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 172 | } |
| 173 | |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 174 | String mimetype = cursor.getString(SplitQuery.MIMETYPE); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 175 | if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) { |
| 176 | loadStructuredName(cursor, info); |
| 177 | } else if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { |
| 178 | loadPhoneNumber(cursor, info); |
| 179 | } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) { |
| 180 | loadEmail(cursor, info); |
| 181 | } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) { |
| 182 | loadNickname(cursor, info); |
| 183 | } |
| 184 | } |
| 185 | } finally { |
| 186 | cursor.close(); |
| 187 | } |
| 188 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 189 | List<RawContactInfo> list = new ArrayList<RawContactInfo>(rawContactInfos.values()); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 190 | Collections.sort(list); |
| 191 | return list; |
| 192 | } |
| 193 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 194 | private void loadStructuredName(Cursor cursor, RawContactInfo info) { |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 195 | info.name = cursor.getString(SplitQuery.DISPLAY_NAME); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 196 | } |
| 197 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 198 | private void loadNickname(Cursor cursor, RawContactInfo info) { |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 199 | if (info.nickname == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) { |
| 200 | info.nickname = cursor.getString(SplitQuery.NICKNAME); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 201 | } |
| 202 | } |
| 203 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 204 | private void loadEmail(Cursor cursor, RawContactInfo info) { |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 205 | if (info.email == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) { |
| 206 | info.email = cursor.getString(SplitQuery.EMAIL); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 207 | } |
| 208 | } |
| 209 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 210 | private void loadPhoneNumber(Cursor cursor, RawContactInfo info) { |
Dmitri Plotnikov | b902a46 | 2009-09-21 10:25:54 -0700 | [diff] [blame] | 211 | if (info.phone == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) { |
| 212 | info.phone = cursor.getString(SplitQuery.PHONE); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 213 | } |
| 214 | } |
| 215 | |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 216 | private static class SplitAggregateItemCache { |
| 217 | TextView name; |
| 218 | TextView additionalData; |
| 219 | ImageView sourceIcon; |
| 220 | } |
| 221 | |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 222 | /** |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 223 | * List adapter for the list of {@link RawContactInfo} objects. |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 224 | */ |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 225 | private class SplitAggregateAdapter extends ArrayAdapter<RawContactInfo> { |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 226 | |
| 227 | private LayoutInflater mInflater; |
| 228 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 229 | public SplitAggregateAdapter(Context context, List<RawContactInfo> sources) { |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 230 | super(context, 0, sources); |
| 231 | mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| 232 | } |
| 233 | |
| 234 | @Override |
| 235 | public View getView(int position, View convertView, ViewGroup parent) { |
| 236 | if (convertView == null) { |
| 237 | convertView = mInflater.inflate(R.layout.split_aggregate_list_item, parent, false); |
| 238 | } |
| 239 | |
| 240 | SplitAggregateItemCache cache = (SplitAggregateItemCache)convertView.getTag(); |
| 241 | if (cache == null) { |
| 242 | cache = new SplitAggregateItemCache(); |
| 243 | cache.name = (TextView)convertView.findViewById(R.id.name); |
| 244 | cache.additionalData = (TextView)convertView.findViewById(R.id.additionalData); |
| 245 | cache.sourceIcon = (ImageView)convertView.findViewById(R.id.sourceIcon); |
| 246 | convertView.setTag(cache); |
| 247 | } |
| 248 | |
Dmitri Plotnikov | ac86cde | 2009-09-17 18:55:08 -0700 | [diff] [blame] | 249 | final RawContactInfo info = getItem(position); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 250 | cache.name.setText(info.name); |
| 251 | cache.additionalData.setText(info.getAdditionalData()); |
| 252 | |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 253 | Drawable icon = null; |
Dave Santoro | 2b3f3c5 | 2011-07-26 17:35:42 -0700 | [diff] [blame] | 254 | AccountType accountType = mAccountTypes.getAccountType(info.accountType, info.dataSet); |
Dmitri Plotnikov | 69f9e6f | 2011-01-03 15:47:24 -0800 | [diff] [blame] | 255 | if (accountType != null) { |
| 256 | icon = accountType.getDisplayIcon(getContext()); |
Dmitri Plotnikov | 6698cf2 | 2009-08-19 18:03:00 -0700 | [diff] [blame] | 257 | } |
| 258 | if (icon != null) { |
| 259 | cache.sourceIcon.setImageDrawable(icon); |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 260 | } else { |
| 261 | cache.sourceIcon.setImageResource(R.drawable.unknown_source); |
| 262 | } |
| 263 | return convertView; |
| 264 | } |
Dmitri Plotnikov | b4491ee | 2009-06-15 09:31:02 -0700 | [diff] [blame] | 265 | } |
| 266 | } |