/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.contacts; import com.android.contacts.model.AccountType; import com.android.contacts.model.AccountTypeManager; import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.ContactsContract.RawContacts; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.Nickname; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Contacts.Data; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; /** * A list view for constituent contacts of an aggregate. Shows the contact name, source icon * and additional data such as a nickname, email address or phone number, whichever * is available. */ public class SplitAggregateView extends ListView { private static final String TAG = "SplitAggregateView"; private interface SplitQuery { String[] COLUMNS = new String[] { Data.MIMETYPE, RawContacts.ACCOUNT_TYPE, RawContacts.DATA_SET, Data.RAW_CONTACT_ID, Data.IS_PRIMARY, StructuredName.DISPLAY_NAME, Nickname.NAME, Email.DATA, Phone.NUMBER }; int MIMETYPE = 0; int ACCOUNT_TYPE = 1; int DATA_SET = 2; int RAW_CONTACT_ID = 3; int IS_PRIMARY = 4; int DISPLAY_NAME = 5; int NICKNAME = 6; int EMAIL = 7; int PHONE = 8; } private final Uri mAggregateUri; private OnContactSelectedListener mListener; private AccountTypeManager mAccountTypes; /** * Listener interface that gets the contact ID of the user-selected contact. */ public interface OnContactSelectedListener { void onContactSelected(long rawContactId); } /** * Constructor. */ public SplitAggregateView(Context context, Uri aggregateUri) { super(context); mAggregateUri = aggregateUri; mAccountTypes = AccountTypeManager.getInstance(context); final List<RawContactInfo> list = loadData(); setAdapter(new SplitAggregateAdapter(context, list)); setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mListener.onContactSelected(list.get(position).rawContactId); } }); } /** * Sets a contact selection listener. */ public void setOnContactSelectedListener(OnContactSelectedListener listener) { mListener = listener; } /** * Contact information loaded from the content provider. */ private static class RawContactInfo implements Comparable<RawContactInfo> { final long rawContactId; String accountType; String dataSet; String name; String phone; String email; String nickname; public RawContactInfo(long rawContactId) { this.rawContactId = rawContactId; } public String getAdditionalData() { if (nickname != null) { return nickname; } if (email != null) { return email; } if (phone != null) { return phone; } return ""; } public int compareTo(RawContactInfo another) { String thisAccount = accountType != null ? accountType : ""; String thatAccount = another.accountType != null ? another.accountType : ""; return thisAccount.compareTo(thatAccount); } } /** * Loads data from the content provider, organizes it into {@link RawContactInfo} objects * and returns a sorted list of {@link RawContactInfo}'s. */ private List<RawContactInfo> loadData() { HashMap<Long, RawContactInfo> rawContactInfos = new HashMap<Long, RawContactInfo>(); Uri dataUri = Uri.withAppendedPath(mAggregateUri, Data.CONTENT_DIRECTORY); Cursor cursor = getContext().getContentResolver().query(dataUri, SplitQuery.COLUMNS, null, null, null); try { while (cursor.moveToNext()) { long rawContactId = cursor.getLong(SplitQuery.RAW_CONTACT_ID); RawContactInfo info = rawContactInfos.get(rawContactId); if (info == null) { info = new RawContactInfo(rawContactId); rawContactInfos.put(rawContactId, info); info.accountType = cursor.getString(SplitQuery.ACCOUNT_TYPE); info.dataSet = cursor.getString(SplitQuery.DATA_SET); } String mimetype = cursor.getString(SplitQuery.MIMETYPE); if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) { loadStructuredName(cursor, info); } else if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { loadPhoneNumber(cursor, info); } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) { loadEmail(cursor, info); } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) { loadNickname(cursor, info); } } } finally { cursor.close(); } List<RawContactInfo> list = new ArrayList<RawContactInfo>(rawContactInfos.values()); Collections.sort(list); return list; } private void loadStructuredName(Cursor cursor, RawContactInfo info) { info.name = cursor.getString(SplitQuery.DISPLAY_NAME); } private void loadNickname(Cursor cursor, RawContactInfo info) { if (info.nickname == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) { info.nickname = cursor.getString(SplitQuery.NICKNAME); } } private void loadEmail(Cursor cursor, RawContactInfo info) { if (info.email == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) { info.email = cursor.getString(SplitQuery.EMAIL); } } private void loadPhoneNumber(Cursor cursor, RawContactInfo info) { if (info.phone == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) { info.phone = cursor.getString(SplitQuery.PHONE); } } private static class SplitAggregateItemCache { TextView name; TextView additionalData; ImageView sourceIcon; } /** * List adapter for the list of {@link RawContactInfo} objects. */ private class SplitAggregateAdapter extends ArrayAdapter<RawContactInfo> { private LayoutInflater mInflater; public SplitAggregateAdapter(Context context, List<RawContactInfo> sources) { super(context, 0, sources); mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.split_aggregate_list_item, parent, false); } SplitAggregateItemCache cache = (SplitAggregateItemCache)convertView.getTag(); if (cache == null) { cache = new SplitAggregateItemCache(); cache.name = (TextView)convertView.findViewById(R.id.name); cache.additionalData = (TextView)convertView.findViewById(R.id.additionalData); cache.sourceIcon = (ImageView)convertView.findViewById(R.id.sourceIcon); convertView.setTag(cache); } final RawContactInfo info = getItem(position); cache.name.setText(info.name); cache.additionalData.setText(info.getAdditionalData()); Drawable icon = null; AccountType accountType = mAccountTypes.getAccountType(info.accountType, info.dataSet); if (accountType != null) { icon = accountType.getDisplayIcon(getContext()); } if (icon != null) { cache.sourceIcon.setImageDrawable(icon); } else { cache.sourceIcon.setImageResource(R.drawable.unknown_source); } return convertView; } } }