BaseRecipientAdapter.java revision df4457285cf0a54d957f1fad3bbc07112f750818
16ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa/* 26ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Copyright (C) 2011 The Android Open Source Project 36ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * 46ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); 56ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * you may not use this file except in compliance with the License. 66ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * You may obtain a copy of the License at 76ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * 86ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0 96ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * 106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software 116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, 126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * See the License for the specific language governing permissions and 146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * limitations under the License. 156ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 166ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawapackage com.android.ex.chips; 186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 196ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.accounts.Account; 206ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.content.ContentResolver; 216ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.content.Context; 226ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.content.pm.PackageManager; 236ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.content.pm.PackageManager.NameNotFoundException; 246ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.content.res.Resources; 256ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.database.Cursor; 266ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.graphics.Bitmap; 276ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.graphics.BitmapFactory; 286ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.net.Uri; 296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.os.Handler; 3074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawaimport android.os.HandlerThread; 316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.provider.ContactsContract; 326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email; 33d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Phone; 3474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Photo; 356ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.provider.ContactsContract.Contacts; 366ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.provider.ContactsContract.Directory; 376ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.text.TextUtils; 386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.text.util.Rfc822Token; 396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.util.Log; 4074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawaimport android.util.LruCache; 41d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawaimport android.view.LayoutInflater; 426ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.view.View; 436ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.view.ViewGroup; 446ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.widget.AutoCompleteTextView; 456ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.widget.BaseAdapter; 466ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.widget.Filter; 476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.widget.Filterable; 486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.widget.ImageView; 496ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport android.widget.TextView; 506ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 516ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport java.util.ArrayList; 5274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawaimport java.util.HashSet; 53cf9337aa4b2d844f4941d75832f52266c4fc3fa7Daisuke Miyakawaimport java.util.LinkedHashMap; 546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport java.util.List; 556ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawaimport java.util.Map; 5674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawaimport java.util.Set; 576ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa/** 596ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Adapter for showing a recipient list. 606ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 61df4457285cf0a54d957f1fad3bbc07112f750818Mindy Pereirapublic abstract class BaseRecipientAdapter extends BaseAdapter implements Filterable, 62df4457285cf0a54d957f1fad3bbc07112f750818Mindy Pereira AccountSpecificAdapter { 636ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static final String TAG = "BaseRecipientAdapter"; 6474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private static final boolean DEBUG = false; 656ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * The preferred number of results to be retrieved. This number may be 686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * exceeded if there are several directories configured, because we will use 696ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * the same limit for all directories. 706ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 716ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static final int DEFAULT_PREFERRED_MAX_RESULT_COUNT = 10; 726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * The number of extra entries requested to allow for duplicates. Duplicates 756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * are removed from the overall result. 766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static final int ALLOWANCE_FOR_DUPLICATES = 5; 786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 797537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa // This is ContactsContract.PRIMARY_ACCOUNT_NAME. Available from ICS as hidden 807537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa private static final String PRIMARY_ACCOUNT_NAME = "name_for_primary_account"; 817537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa // This is ContactsContract.PRIMARY_ACCOUNT_TYPE. Available from ICS as hidden 827537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa private static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account"; 837537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa 8474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa /** The number of photos cached in this Adapter. */ 8574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private static final int PHOTO_CACHE_SIZE = 20; 8674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 87d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int QUERY_TYPE_EMAIL = 0; 88d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int QUERY_TYPE_PHONE = 1; 89d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Model object for a {@link Directory} row. 926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public final static class DirectorySearchParams { 946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public long directoryId; 956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String directoryType; 966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String displayName; 976ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String accountName; 986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String accountType; 996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public CharSequence constraint; 1006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public DirectoryFilter filter; 1016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1026ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 10384dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira /* package */ static class EmailQuery { 1046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final String[] PROJECTION = { 1056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Contacts.DISPLAY_NAME, // 0 1066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Email.DATA, // 1 1076ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Email.CONTACT_ID, // 2 1087537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Email._ID, // 3 1097537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Contacts.PHOTO_THUMBNAIL_URI // 4 1106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }; 1116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int NAME = 0; 1136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ADDRESS = 1; 1146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int CONTACT_ID = 2; 1157537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa public static final int DATA_ID = 3; 1167537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa public static final int PHOTO_THUMBNAIL_URI = 4; 1176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 119d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private static class PhoneQuery { 120d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final String[] PROJECTION = { 121d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa Contacts.DISPLAY_NAME, // 0 122d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa Phone.DATA, // 1 123d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa Phone.CONTACT_ID, // 2 1247537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Phone._ID, // 3 1257537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Contacts.PHOTO_THUMBNAIL_URI // 4 126d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa }; 127d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int NAME = 0; 128d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int NUMBER = 1; 129d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int CONTACT_ID = 2; 1307537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa public static final int DATA_ID = 3; 131d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int PHOTO_THUMBNAIL_URI = 3; 132d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 1336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 13474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private static class PhotoQuery { 13574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public static final String[] PROJECTION = { 13674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Photo.PHOTO 13774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa }; 13874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 13974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public static final int PHOTO = 0; 14074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 14174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 1426ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static class DirectoryListQuery { 1436ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1446ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final Uri URI = 1456ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, "directories"); 1466ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final String[] PROJECTION = { 1476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory._ID, // 0 1486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.ACCOUNT_NAME, // 1 1496ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.ACCOUNT_TYPE, // 2 1506ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.DISPLAY_NAME, // 3 1516ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.PACKAGE_NAME, // 4 1526ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.TYPE_RESOURCE_ID, // 5 1536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }; 1546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1556ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ID = 0; 1566ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ACCOUNT_NAME = 1; 1576ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ACCOUNT_TYPE = 2; 1586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int DISPLAY_NAME = 3; 1596ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int PACKAGE_NAME = 4; 1606ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int TYPE_RESOURCE_ID = 5; 1616ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1626ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1636ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 1646ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * An asynchronous filter used for loading two data sets: email rows from the local 1656ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * contact provider and the list of {@link Directory}'s. 1666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 1676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final class DefaultFilter extends Filter { 1686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1696ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 1706ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected FilterResults performFiltering(CharSequence constraint) { 17174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final FilterResults results = new FilterResults(); 1726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Cursor cursor = null; 1736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (!TextUtils.isEmpty(constraint)) { 174d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = doQuery(constraint, mPreferredMaxResultCount, null); 1756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (cursor != null) { 1766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.count = cursor.getCount(); 1776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1796ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1806ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // TODO: implement group feature 1816ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1826ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Cursor directoryCursor = mContentResolver.query( 1836ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa DirectoryListQuery.URI, DirectoryListQuery.PROJECTION, null, null, null); 1846ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 18574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (DEBUG && cursor == null) { 18674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.w(TAG, "null cursor returned for default Email filter query."); 18774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 1886ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.values = new Cursor[] { directoryCursor, cursor }; 1896ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return results; 1906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 1936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected void publishResults(final CharSequence constraint, FilterResults results) { 1946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (results.values != null) { 1956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Cursor[] cursors = (Cursor[]) results.values; 1966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // Run on one thread. 1976ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mHandler.post(new Runnable() { 1986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 1996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void run() { 2006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa onFirstDirectoryLoadFinished(constraint, cursors[0], cursors[1]); 2016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2026ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }); 2036ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.count = getCount(); 2056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2076ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2086ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public CharSequence convertResultToString(Object resultValue) { 209f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final RecipientEntry entry = (RecipientEntry)resultValue; 2106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final String displayName = entry.getDisplayName(); 2116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final String emailAddress = entry.getDestination(); 2126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (TextUtils.isEmpty(displayName) || TextUtils.equals(displayName, emailAddress)) { 2136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return emailAddress; 2146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 2156ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return new Rfc822Token(displayName, emailAddress, null).toString(); 2166ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2196ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2206ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 2216ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * An asynchronous filter that performs search in a particular directory. 2226ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 2236ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final class DirectoryFilter extends Filter { 22474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final DirectorySearchParams mParams; 2256ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private int mLimit; 2266ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 22774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public DirectoryFilter(DirectorySearchParams params) { 22874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa this.mParams = params; 2296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public synchronized void setLimit(int limit) { 2326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa this.mLimit = limit; 2336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2346ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2356ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public synchronized int getLimit() { 2366ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return this.mLimit; 2376ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2406ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected FilterResults performFiltering(CharSequence constraint) { 24174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final FilterResults results = new FilterResults(); 2426ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (!TextUtils.isEmpty(constraint)) { 243d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Cursor cursor = doQuery(constraint, getLimit(), mParams.directoryId); 24474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (cursor != null) { 24574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa results.values = cursor; 24674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 2476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2496ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // TODO: implement group feature 2506ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2516ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return results; 2526ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2556ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected void publishResults(final CharSequence constraint, FilterResults results) { 2566ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Cursor cursor = (Cursor) results.values; 2576ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mHandler.post(new Runnable() { 2586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2596ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void run() { 26074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa onDirectoryLoadFinished(constraint, mParams, cursor); 2616ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2626ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }); 2636ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.count = getCount(); 2646ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2656ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 26774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final Context mContext; 2686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final ContentResolver mContentResolver; 269d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private final LayoutInflater mInflater; 270d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private final int mQueryType; 2716ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private Account mAccount; 27274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final int mPreferredMaxResultCount; 2736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final Handler mHandler = new Handler(); 2746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 27674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Each destination (an email address or a phone number) with a valid contactId is first 27774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * inserted into {@link #mEntryMap} and grouped by the contactId. 27874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Destinations without valid contactId (possible if they aren't in local storage) are stored 27974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * in {@link #mNonAggregatedEntries}. 28074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Duplicates are removed using {@link #mExistingDestinations}. 28174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * 28274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * After having all results from ContentResolver, all elements in mEntryMap are copied to 28374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * mEntry, which will be used to find items in this Adapter. If the number of contacts in 28474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * mEntries are less than mPreferredMaxResultCount, contacts in 28574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * mNonAggregatedEntries are also used. 2866ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 287f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa private final LinkedHashMap<Long, List<RecipientEntry>> mEntryMap; 288f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private final List<RecipientEntry> mNonAggregatedEntries; 289f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private final List<RecipientEntry> mEntries; 29074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final Set<String> mExistingDestinations; 2916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 29274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa /** 29374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Used to ignore asynchronous queries with a different constraint, which may appear when 29474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * users type characters quickly. 29574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa */ 29674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private CharSequence mCurrentConstraint; 29774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 29874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final HandlerThread mPhotoHandlerThread; 29974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final Handler mPhotoHandler; 30074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final LruCache<Uri, byte[]> mPhotoCacheMap; 3016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 302d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 303d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Constructor for email queries. 304d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 3056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public BaseRecipientAdapter(Context context) { 306d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa this(context, QUERY_TYPE_EMAIL, DEFAULT_PREFERRED_MAX_RESULT_COUNT); 307d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 308d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 309d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public BaseRecipientAdapter(Context context, int queryType) { 310d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa this(context, queryType, DEFAULT_PREFERRED_MAX_RESULT_COUNT); 3116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 313d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public BaseRecipientAdapter(Context context, int queryType, int preferredMaxResultCount) { 3146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mContext = context; 3156ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mContentResolver = context.getContentResolver(); 316d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa mInflater = LayoutInflater.from(context); 317d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa mQueryType = queryType; 3186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mPreferredMaxResultCount = preferredMaxResultCount; 319f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa mEntryMap = new LinkedHashMap<Long, List<RecipientEntry>>(); 320f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mNonAggregatedEntries = new ArrayList<RecipientEntry>(); 321f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries = new ArrayList<RecipientEntry>(); 32274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations = new HashSet<String>(); 32374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandlerThread = new HandlerThread("photo_handler"); 32474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandlerThread.start(); 32574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandler = new Handler(mPhotoHandlerThread.getLooper()); 32674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoCacheMap = new LruCache<Uri, byte[]>(PHOTO_CACHE_SIZE); 3276ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3286ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 3306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Set the account when known. Causes the search to prioritize contacts from that account. 3316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 3326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void setAccount(Account account) { 3336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mAccount = account; 3346ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3356ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3366ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** Will be called from {@link AutoCompleteTextView} to prepare auto-complete list. */ 3376ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 3386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public Filter getFilter() { 3396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return new DefaultFilter(); 3406ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3416ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3426ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 3436ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Handles the result of the initial call, which brings back the list of directories as well 3446ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * as the search results for the local directories. 34574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * 34674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Must be inside a default Looper thread to avoid synchronization problem. 3476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 3486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected void onFirstDirectoryLoadFinished( 3496ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa CharSequence constraint, Cursor directoryCursor, Cursor defaultDirectoryCursor) { 35074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mCurrentConstraint = constraint; 35174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 3526ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa try { 35374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final List<DirectorySearchParams> paramsList; 3546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (directoryCursor != null) { 35574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList = setupOtherDirectories(directoryCursor); 35674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else { 35774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList = null; 3586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3596ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3606ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa int limit = 0; 3616ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 36274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (defaultDirectoryCursor != null) { 3636ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntryMap.clear(); 36474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mNonAggregatedEntries.clear(); 36574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations.clear(); 36674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa putEntriesWithCursor(defaultDirectoryCursor, true); 3676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa constructEntryList(); 3686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa limit = mPreferredMaxResultCount - getCount(); 3696ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3706ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 37174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (limit > 0 && paramsList != null) { 37274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa searchOtherDirectories(constraint, paramsList, limit); 3736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } finally { 3756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (directoryCursor != null) { 3766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa directoryCursor.close(); 3776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (defaultDirectoryCursor != null) { 3796ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa defaultDirectoryCursor.close(); 3806ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3816ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3826ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3836ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 38474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private List<DirectorySearchParams> setupOtherDirectories(Cursor directoryCursor) { 3856ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final PackageManager packageManager = mContext.getPackageManager(); 38674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final List<DirectorySearchParams> paramsList = new ArrayList<DirectorySearchParams>(); 3876ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa DirectorySearchParams preferredDirectory = null; 3886ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa while (directoryCursor.moveToNext()) { 3896ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final long id = directoryCursor.getLong(DirectoryListQuery.ID); 3906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // Skip the local invisible directory, because the default directory already includes 3926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // all local results. 3936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (id == Directory.LOCAL_INVISIBLE) { 3946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa continue; 3956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3976ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final DirectorySearchParams params = new DirectorySearchParams(); 3986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final String packageName = directoryCursor.getString(DirectoryListQuery.PACKAGE_NAME); 3996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final int resourceId = directoryCursor.getInt(DirectoryListQuery.TYPE_RESOURCE_ID); 4006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.directoryId = id; 4016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.displayName = directoryCursor.getString(DirectoryListQuery.DISPLAY_NAME); 4026ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.accountName = directoryCursor.getString(DirectoryListQuery.ACCOUNT_NAME); 4036ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.accountType = directoryCursor.getString(DirectoryListQuery.ACCOUNT_TYPE); 4046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (packageName != null && resourceId != 0) { 4056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa try { 4066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Resources resources = 4076ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa packageManager.getResourcesForApplication(packageName); 4086ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.directoryType = resources.getString(resourceId); 4096ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (params.directoryType == null) { 4106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Log.e(TAG, "Cannot resolve directory name: " 4116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa + resourceId + "@" + packageName); 4126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } catch (NameNotFoundException e) { 4146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Log.e(TAG, "Cannot resolve directory name: " 4156ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa + resourceId + "@" + packageName, e); 4166ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4196ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // If an account has been provided and we found a directory that 4206ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // corresponds to that account, place that directory second, directly 4216ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // underneath the local contacts. 4226ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (mAccount != null && mAccount.name.equals(params.accountName) && 4236ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mAccount.type.equals(params.accountType)) { 4246ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa preferredDirectory = params; 4256ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 42674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList.add(params); 4276ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4286ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (preferredDirectory != null) { 43174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList.add(1, preferredDirectory); 4326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 43474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return paramsList; 4356ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4366ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4376ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 4386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Starts search in other directories 4396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 44074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private void searchOtherDirectories( 44174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa CharSequence constraint, List<DirectorySearchParams> paramsList, int limit) { 44274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final int count = paramsList.size(); 4436ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // Note: skipping the default partition (index 0), which has already been loaded 4446ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa for (int i = 1; i < count; i++) { 44574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final DirectorySearchParams params = paramsList.get(i); 44674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.constraint = constraint; 44774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (params.filter == null) { 44874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.filter = new DirectoryFilter(params); 44974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 45074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.filter.setLimit(limit); 45174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.filter.filter(constraint); 45274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 45374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 45474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 45574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa /** Must be inside a default Looper thread to avoid synchronization problem. */ 45674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public void onDirectoryLoadFinished( 45774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa CharSequence constraint, DirectorySearchParams params, Cursor cursor) { 45874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (cursor != null) { 45974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa try { 46074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (DEBUG) { 46174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.v(TAG, "finished loading directory \"" + params.displayName + "\"" + 46274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa " with query " + constraint); 46374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 46474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 46574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // Check if the received result matches the current constraint 46674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // If not - the user must have continued typing after the request was issued 46774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final boolean usesSameConstraint; 46874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa usesSameConstraint = TextUtils.equals(constraint, mCurrentConstraint); 46974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (usesSameConstraint) { 47074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa putEntriesWithCursor(cursor, params.directoryId == Directory.DEFAULT); 47174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa constructEntryList(); 47274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 47374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } finally { 47474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa cursor.close(); 4756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4796ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 4806ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Stores each contact information to {@link #mEntryMap}. {@link #mEntries} isn't touched here. 4816ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * 4826ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * In order to make the new information available from outside Adapter, 4836ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * call {@link #constructEntryList()} after this method. 4846ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 48574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private void putEntriesWithCursor(Cursor cursor, boolean validContactId) { 4866ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa cursor.move(-1); 4876ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa while (cursor.moveToNext()) { 488d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final String displayName; 489d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final String destination; 490f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa final long contactId; 491f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa final long dataId; 492d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final String thumbnailUriString; 493d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (mQueryType == QUERY_TYPE_EMAIL) { 494d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa displayName = cursor.getString(EmailQuery.NAME); 495d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa destination = cursor.getString(EmailQuery.ADDRESS); 496f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa contactId = cursor.getLong(EmailQuery.CONTACT_ID); 497f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa dataId = cursor.getLong(EmailQuery.DATA_ID); 498d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa thumbnailUriString = cursor.getString(EmailQuery.PHOTO_THUMBNAIL_URI); 499d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else if (mQueryType == QUERY_TYPE_PHONE) { 500d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa displayName = cursor.getString(PhoneQuery.NAME); 501d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa destination = cursor.getString(PhoneQuery.NUMBER); 502f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa contactId = cursor.getLong(PhoneQuery.CONTACT_ID); 503f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa dataId = cursor.getLong(PhoneQuery.DATA_ID); 504d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa thumbnailUriString = cursor.getString(PhoneQuery.PHOTO_THUMBNAIL_URI); 505d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else { 506d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa throw new IndexOutOfBoundsException("Unexpected query type: " + mQueryType); 507d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 50874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 50974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // Note: At this point each entry doesn't contain have any photo (thus getPhotoBytes() 51074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // returns null). 51174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 51274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (mExistingDestinations.contains(destination)) { 51374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa continue; 51474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 51574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations.add(destination); 5166ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 51774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (!validContactId) { 518f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mNonAggregatedEntries.add(RecipientEntry.constructTopLevelEntry( 5197537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa displayName, destination, contactId, dataId, thumbnailUriString)); 52074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else if (mEntryMap.containsKey(contactId)) { 5216ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // We already have a section for the person. 522f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final List<RecipientEntry> entryList = mEntryMap.get(contactId); 523f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira entryList.add(RecipientEntry.constructSecondLevelEntry( 5246b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira displayName, destination, contactId, dataId, thumbnailUriString)); 5256ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 526f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final List<RecipientEntry> entryList = new ArrayList<RecipientEntry>(); 527f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira entryList.add(RecipientEntry.constructTopLevelEntry( 5287537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa displayName, destination, contactId, dataId, thumbnailUriString)); 5296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntryMap.put(contactId, entryList); 5306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 5346ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 53574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Constructs an actual list for this Adapter using {@link #mEntryMap}. Also tries to 53674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * fetch a cached photo for each contact entry (other than separators), or request another 53774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * thread to get one from directories. The thread ({@link #mPhotoHandlerThread}) will 53874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * request {@link #notifyDataSetChanged()} after having the photo asynchronously. 5396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 5406ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private void constructEntryList() { 54174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntries.clear(); 54274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa int validEntryCount = 0; 543f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa for (Map.Entry<Long, List<RecipientEntry>> mapEntry : mEntryMap.entrySet()) { 544f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final List<RecipientEntry> entryList = mapEntry.getValue(); 5456ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final int size = entryList.size(); 5466ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa for (int i = 0; i < size; i++) { 547f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira RecipientEntry entry = entryList.get(i); 5486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntries.add(entry); 54974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa tryFetchPhoto(entry); 55074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa validEntryCount++; 5516ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (i < size - 1) { 552f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries.add(RecipientEntry.SEP_WITHIN_GROUP); 5536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 555f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries.add(RecipientEntry.SEP_NORMAL); 55674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (validEntryCount > mPreferredMaxResultCount) { 55774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa break; 55874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 5596ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 56074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (validEntryCount <= mPreferredMaxResultCount) { 561f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira for (RecipientEntry entry : mNonAggregatedEntries) { 56274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (validEntryCount > mPreferredMaxResultCount) { 56374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa break; 56474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 56574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntries.add(entry); 56674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa tryFetchPhoto(entry); 56774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 568f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries.add(RecipientEntry.SEP_NORMAL); 56974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa validEntryCount++; 57074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 57174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 57274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 57374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // Remove last divider 5746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (mEntries.size() > 1) { 5756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntries.remove(mEntries.size() - 1); 5766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa notifyDataSetChanged(); 5786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5796ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 580f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private void tryFetchPhoto(final RecipientEntry entry) { 58174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final Uri photoThumbnailUri = entry.getPhotoThumbnailUri(); 58274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoThumbnailUri != null) { 58374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final byte[] photoBytes = mPhotoCacheMap.get(photoThumbnailUri); 58474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoBytes != null) { 58574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa entry.setPhotoBytes(photoBytes); 58674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // notifyDataSetChanged() should be called by a caller. 58774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else { 58874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (DEBUG) { 58974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.d(TAG, "No photo cache for " + entry.getDisplayName() 59074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa + ". Fetch one asynchronously"); 5916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 59274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa fetchPhotoAsync(entry, photoThumbnailUri); 5936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 597f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private void fetchPhotoAsync(final RecipientEntry entry, final Uri photoThumbnailUri) { 59874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandler.post(new Runnable() { 59974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 60074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public void run() { 60174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final Cursor photoCursor = mContentResolver.query( 60274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa photoThumbnailUri, PhotoQuery.PROJECTION, null, null, null); 60374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoCursor != null) { 60474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa try { 60574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoCursor.moveToFirst()) { 60674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final byte[] photoBytes = photoCursor.getBlob(PhotoQuery.PHOTO); 60774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa entry.setPhotoBytes(photoBytes); 60874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 60974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mHandler.post(new Runnable() { 61074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 61174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public void run() { 61274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoCacheMap.put(photoThumbnailUri, photoBytes); 61374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa notifyDataSetChanged(); 61474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 61574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa }); 61674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 61774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } finally { 61874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa photoCursor.close(); 61974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 62074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 62174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 62274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa }); 62374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 62474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 6256b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira protected void fetchPhoto(final RecipientEntry entry, final Uri photoThumbnailUri) { 6266b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira byte[] photoBytes = mPhotoCacheMap.get(photoThumbnailUri); 6276b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira if (photoBytes != null) { 6286b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira entry.setPhotoBytes(photoBytes); 6296b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira return; 6306b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6316b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira final Cursor photoCursor = mContentResolver.query(photoThumbnailUri, PhotoQuery.PROJECTION, 6326b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira null, null, null); 6336b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira if (photoCursor != null) { 6346b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira try { 6356b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira if (photoCursor.moveToFirst()) { 6366b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira photoBytes = photoCursor.getBlob(PhotoQuery.PHOTO); 6376b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira entry.setPhotoBytes(photoBytes); 6386b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira mPhotoCacheMap.put(photoThumbnailUri, photoBytes); 6396b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6406b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } finally { 6416b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira photoCursor.close(); 6426b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6436b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6446b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6456b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira 646d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private Cursor doQuery(CharSequence constraint, int limit, Long directoryId) { 647d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Cursor cursor; 648d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (mQueryType == QUERY_TYPE_EMAIL) { 649d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Uri.Builder builder = Email.CONTENT_FILTER_URI.buildUpon() 650d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendPath(constraint.toString()) 651d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, 652d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(limit + ALLOWANCE_FOR_DUPLICATES)); 653d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (directoryId != null) { 654d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, 655d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(directoryId)); 656d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 6577537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa if (mAccount != null) { 6587537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_NAME, mAccount.name); 6597537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_TYPE, mAccount.type); 6607537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa } 661d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = mContentResolver.query( 662d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.build(), EmailQuery.PROJECTION, null, null, null); 663d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else if (mQueryType == QUERY_TYPE_PHONE){ 664d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Uri.Builder builder = Phone.CONTENT_FILTER_URI.buildUpon() 665d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendPath(constraint.toString()) 666d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, 667d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(limit + ALLOWANCE_FOR_DUPLICATES)); 668d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (directoryId != null) { 669d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, 670d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(directoryId)); 671d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 6727537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa if (mAccount != null) { 6737537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_NAME, mAccount.name); 6747537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_TYPE, mAccount.type); 6757537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa } 676d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = mContentResolver.query( 677d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.build(), PhoneQuery.PROJECTION, null, null, null); 678d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else { 679d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = null; 680d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 681d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return cursor; 682d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 683d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 6846ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void close() { 68574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntryMap.clear(); 68674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mNonAggregatedEntries.clear(); 68774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations.clear(); 68874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntries.clear(); 68974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoCacheMap.evictAll(); 69074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (!mPhotoHandlerThread.quit()) { 69174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.w(TAG, "Failed to quit photo handler thread, ignoring it."); 69274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 6936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 6946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 6956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 6966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public int getCount() { 69774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return mEntries.size(); 6986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 6996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 7016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public Object getItem(int position) { 70274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return mEntries.get(position); 7036ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 7066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public long getItemId(int position) { 7076ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return position; 7086ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7096ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 71174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public int getViewTypeCount() { 712f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira return RecipientEntry.ENTRY_TYPE_SIZE; 71374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 71474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 71574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 71674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public int getItemViewType(int position) { 71774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return mEntries.get(position).getEntryType(); 71874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7196ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 72074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 72174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public View getView(int position, View convertView, ViewGroup parent) { 722f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final RecipientEntry entry = mEntries.get(position); 72374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa switch (entry.getEntryType()) { 724f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira case RecipientEntry.ENTRY_TYPE_SEP_NORMAL: { 725d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return convertView != null ? convertView 726d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa : mInflater.inflate(getSeparatorLayout(), parent, false); 7276ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 728f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira case RecipientEntry.ENTRY_TYPE_SEP_WITHIN_GROUP: { 72974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return convertView != null ? convertView 730d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa : mInflater.inflate(getSeparatorWithinGroupLayout(), parent, false); 7316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 73274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa default: { 73374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa String displayName = entry.getDisplayName(); 73474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa String emailAddress = entry.getDestination(); 73574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (TextUtils.isEmpty(displayName) 73674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa || TextUtils.equals(displayName, emailAddress)) { 73774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa displayName = emailAddress; 73874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa emailAddress = null; 73974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7406ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 741d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final View itemView = convertView != null ? convertView 742d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa : mInflater.inflate(getItemLayout(), parent, false); 743d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final TextView displayNameView = 744d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa (TextView)itemView.findViewById(getDisplayNameId()); 745d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final TextView emailAddressView = 746d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa (TextView)itemView.findViewById(getDestinationId()); 747d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final ImageView imageView = (ImageView)itemView.findViewById(getPhotoId()); 74874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa displayNameView.setText(displayName); 74974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (!TextUtils.isEmpty(emailAddress)) { 75074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa emailAddressView.setText(emailAddress); 751e3a7365ee50e5df8d7935143bb88c65644be4b59Daisuke Miyakawa } else { 752e3a7365ee50e5df8d7935143bb88c65644be4b59Daisuke Miyakawa emailAddressView.setText(null); 75374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (entry.isFirstLevel()) { 75574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa displayNameView.setVisibility(View.VISIBLE); 75674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (imageView != null) { 757d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa imageView.setVisibility(View.VISIBLE); 75874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final byte[] photoBytes = entry.getPhotoBytes(); 75974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoBytes != null && imageView != null) { 76074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final Bitmap photo = BitmapFactory.decodeByteArray( 76174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa photoBytes, 0, photoBytes.length); 76274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa imageView.setImageBitmap(photo); 76374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else { 76474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa imageView.setImageResource(getDefaultPhotoResource()); 76574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 7686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa displayNameView.setVisibility(View.GONE); 769d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (imageView != null) imageView.setVisibility(View.GONE); 7706ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 77174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return itemView; 7726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 777d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns a layout id for each item inside auto-complete list. 778d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * 779d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Each View must contain two TextViews (for display name and destination) and one ImageView 780d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * (for photo). Ids for those should be available via {@link #getDisplayNameId()}, 781d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * {@link #getDestinationId()}, and {@link #getPhotoId()}. 7826ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 783efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getItemLayout(); 784d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** Returns a layout id for a separator dividing two person or groups. */ 785efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getSeparatorLayout(); 7866ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 787d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns a layout id for a separator dividing two destinations for a same person or group. 7886ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 789efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getSeparatorWithinGroupLayout(); 7906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 7926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Returns a resource ID representing an image which should be shown when ther's no relevant 7936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * photo is available. 7946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 795efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getDefaultPhotoResource(); 796d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 797d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 798d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns an id for TextView in an item View for showing a display name. In default 799d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * {@link android.R.id#text1} is returned. 800d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 801d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa protected int getDisplayNameId() { 802d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return android.R.id.text1; 803d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 804d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 805d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 806d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns an id for TextView in an item View for showing a destination 807d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * (an email address or a phone number). 808d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * In default {@link android.R.id#text2} is returned. 809d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 810d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa protected int getDestinationId() { 811d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return android.R.id.text2; 812d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 813d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 814d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 815d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns an id for ImageView in an item View for showing photo image for a person. In default 816d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * {@link android.R.id#icon} is returned. 817d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 818d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa protected int getPhotoId() { 819d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return android.R.id.icon; 820d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 8216ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa} 822