BaseRecipientAdapter.java revision 6b6de6266d3bede33728cf995f1fd5c59ec5a55d
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 */ 61efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereirapublic abstract class BaseRecipientAdapter extends BaseAdapter implements Filterable { 626ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static final String TAG = "BaseRecipientAdapter"; 6374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private static final boolean DEBUG = false; 646ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 656ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * The preferred number of results to be retrieved. This number may be 676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * exceeded if there are several directories configured, because we will use 686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * the same limit for all directories. 696ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 706ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static final int DEFAULT_PREFERRED_MAX_RESULT_COUNT = 10; 716ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * The number of extra entries requested to allow for duplicates. Duplicates 746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * are removed from the overall result. 756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static final int ALLOWANCE_FOR_DUPLICATES = 5; 776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 787537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa // This is ContactsContract.PRIMARY_ACCOUNT_NAME. Available from ICS as hidden 797537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa private static final String PRIMARY_ACCOUNT_NAME = "name_for_primary_account"; 807537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa // This is ContactsContract.PRIMARY_ACCOUNT_TYPE. Available from ICS as hidden 817537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa private static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account"; 827537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa 8374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa /** The number of photos cached in this Adapter. */ 8474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private static final int PHOTO_CACHE_SIZE = 20; 8574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 86d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int QUERY_TYPE_EMAIL = 0; 87d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int QUERY_TYPE_PHONE = 1; 88d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 896ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Model object for a {@link Directory} row. 916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public final static class DirectorySearchParams { 936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public long directoryId; 946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String directoryType; 956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String displayName; 966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String accountName; 976ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public String accountType; 986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public CharSequence constraint; 996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public DirectoryFilter filter; 1006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 10284dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira /* package */ static class EmailQuery { 1036ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final String[] PROJECTION = { 1046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Contacts.DISPLAY_NAME, // 0 1056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Email.DATA, // 1 1066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Email.CONTACT_ID, // 2 1077537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Email._ID, // 3 1087537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Contacts.PHOTO_THUMBNAIL_URI // 4 1096ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }; 1106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int NAME = 0; 1126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ADDRESS = 1; 1136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int CONTACT_ID = 2; 1147537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa public static final int DATA_ID = 3; 1157537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa public static final int PHOTO_THUMBNAIL_URI = 4; 1166ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 118d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private static class PhoneQuery { 119d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final String[] PROJECTION = { 120d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa Contacts.DISPLAY_NAME, // 0 121d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa Phone.DATA, // 1 122d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa Phone.CONTACT_ID, // 2 1237537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Phone._ID, // 3 1247537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa Contacts.PHOTO_THUMBNAIL_URI // 4 125d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa }; 126d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int NAME = 0; 127d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int NUMBER = 1; 128d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int CONTACT_ID = 2; 1297537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa public static final int DATA_ID = 3; 130d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public static final int PHOTO_THUMBNAIL_URI = 3; 131d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 1326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 13374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private static class PhotoQuery { 13474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public static final String[] PROJECTION = { 13574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Photo.PHOTO 13674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa }; 13774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 13874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public static final int PHOTO = 0; 13974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 14074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 1416ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private static class DirectoryListQuery { 1426ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1436ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final Uri URI = 1446ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, "directories"); 1456ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final String[] PROJECTION = { 1466ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory._ID, // 0 1476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.ACCOUNT_NAME, // 1 1486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.ACCOUNT_TYPE, // 2 1496ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.DISPLAY_NAME, // 3 1506ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.PACKAGE_NAME, // 4 1516ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Directory.TYPE_RESOURCE_ID, // 5 1526ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }; 1536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ID = 0; 1556ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ACCOUNT_NAME = 1; 1566ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int ACCOUNT_TYPE = 2; 1576ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int DISPLAY_NAME = 3; 1586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int PACKAGE_NAME = 4; 1596ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public static final int TYPE_RESOURCE_ID = 5; 1606ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1616ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1626ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 1636ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * An asynchronous filter used for loading two data sets: email rows from the local 1646ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * contact provider and the list of {@link Directory}'s. 1656ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 1666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final class DefaultFilter extends Filter { 1676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 1696ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected FilterResults performFiltering(CharSequence constraint) { 17074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final FilterResults results = new FilterResults(); 1716ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Cursor cursor = null; 1726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (!TextUtils.isEmpty(constraint)) { 173d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = doQuery(constraint, mPreferredMaxResultCount, null); 1746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (cursor != null) { 1756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.count = cursor.getCount(); 1766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1796ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // TODO: implement group feature 1806ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1816ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Cursor directoryCursor = mContentResolver.query( 1826ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa DirectoryListQuery.URI, DirectoryListQuery.PROJECTION, null, null, null); 1836ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 18474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (DEBUG && cursor == null) { 18574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.w(TAG, "null cursor returned for default Email filter query."); 18674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 1876ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.values = new Cursor[] { directoryCursor, cursor }; 1886ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return results; 1896ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 1906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 1916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 1926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected void publishResults(final CharSequence constraint, FilterResults results) { 1936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (results.values != null) { 1946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Cursor[] cursors = (Cursor[]) results.values; 1956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // Run on one thread. 1966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mHandler.post(new Runnable() { 1976ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 1986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void run() { 1996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa onFirstDirectoryLoadFinished(constraint, cursors[0], cursors[1]); 2006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }); 2026ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2036ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.count = getCount(); 2046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2076ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public CharSequence convertResultToString(Object resultValue) { 208f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final RecipientEntry entry = (RecipientEntry)resultValue; 2096ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final String displayName = entry.getDisplayName(); 2106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final String emailAddress = entry.getDestination(); 2116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (TextUtils.isEmpty(displayName) || TextUtils.equals(displayName, emailAddress)) { 2126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return emailAddress; 2136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 2146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return new Rfc822Token(displayName, emailAddress, null).toString(); 2156ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2166ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2196ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 2206ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * An asynchronous filter that performs search in a particular directory. 2216ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 2226ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final class DirectoryFilter extends Filter { 22374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final DirectorySearchParams mParams; 2246ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private int mLimit; 2256ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 22674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public DirectoryFilter(DirectorySearchParams params) { 22774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa this.mParams = params; 2286ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public synchronized void setLimit(int limit) { 2316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa this.mLimit = limit; 2326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2346ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public synchronized int getLimit() { 2356ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return this.mLimit; 2366ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2376ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected FilterResults performFiltering(CharSequence constraint) { 24074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final FilterResults results = new FilterResults(); 2416ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (!TextUtils.isEmpty(constraint)) { 242d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Cursor cursor = doQuery(constraint, getLimit(), mParams.directoryId); 24374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (cursor != null) { 24474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa results.values = cursor; 24574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 2466ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // TODO: implement group feature 2496ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2506ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return results; 2516ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2526ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2546ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected void publishResults(final CharSequence constraint, FilterResults results) { 2556ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Cursor cursor = (Cursor) results.values; 2566ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mHandler.post(new Runnable() { 2576ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 2586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void run() { 25974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa onDirectoryLoadFinished(constraint, mParams, cursor); 2606ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2616ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa }); 2626ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa results.count = getCount(); 2636ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2646ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 2656ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 26674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final Context mContext; 2676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final ContentResolver mContentResolver; 268d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private final LayoutInflater mInflater; 269d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private final int mQueryType; 2706ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private Account mAccount; 27174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final int mPreferredMaxResultCount; 2726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private final Handler mHandler = new Handler(); 2736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 2746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 27574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Each destination (an email address or a phone number) with a valid contactId is first 27674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * inserted into {@link #mEntryMap} and grouped by the contactId. 27774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Destinations without valid contactId (possible if they aren't in local storage) are stored 27874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * in {@link #mNonAggregatedEntries}. 27974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Duplicates are removed using {@link #mExistingDestinations}. 28074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * 28174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * After having all results from ContentResolver, all elements in mEntryMap are copied to 28274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * mEntry, which will be used to find items in this Adapter. If the number of contacts in 28374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * mEntries are less than mPreferredMaxResultCount, contacts in 28474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * mNonAggregatedEntries are also used. 2856ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 286f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa private final LinkedHashMap<Long, List<RecipientEntry>> mEntryMap; 287f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private final List<RecipientEntry> mNonAggregatedEntries; 288f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private final List<RecipientEntry> mEntries; 28974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final Set<String> mExistingDestinations; 2906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 29174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa /** 29274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Used to ignore asynchronous queries with a different constraint, which may appear when 29374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * users type characters quickly. 29474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa */ 29574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private CharSequence mCurrentConstraint; 29674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 29774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final HandlerThread mPhotoHandlerThread; 29874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final Handler mPhotoHandler; 29974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private final LruCache<Uri, byte[]> mPhotoCacheMap; 3006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 301d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 302d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Constructor for email queries. 303d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 3046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public BaseRecipientAdapter(Context context) { 305d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa this(context, QUERY_TYPE_EMAIL, DEFAULT_PREFERRED_MAX_RESULT_COUNT); 306d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 307d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 308d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public BaseRecipientAdapter(Context context, int queryType) { 309d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa this(context, queryType, DEFAULT_PREFERRED_MAX_RESULT_COUNT); 3106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 312d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa public BaseRecipientAdapter(Context context, int queryType, int preferredMaxResultCount) { 3136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mContext = context; 3146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mContentResolver = context.getContentResolver(); 315d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa mInflater = LayoutInflater.from(context); 316d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa mQueryType = queryType; 3176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mPreferredMaxResultCount = preferredMaxResultCount; 318f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa mEntryMap = new LinkedHashMap<Long, List<RecipientEntry>>(); 319f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mNonAggregatedEntries = new ArrayList<RecipientEntry>(); 320f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries = new ArrayList<RecipientEntry>(); 32174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations = new HashSet<String>(); 32274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandlerThread = new HandlerThread("photo_handler"); 32374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandlerThread.start(); 32474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandler = new Handler(mPhotoHandlerThread.getLooper()); 32574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoCacheMap = new LruCache<Uri, byte[]>(PHOTO_CACHE_SIZE); 3266ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3276ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3286ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 3296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Set the account when known. Causes the search to prioritize contacts from that account. 3306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 3316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void setAccount(Account account) { 3326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mAccount = account; 3336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3346ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3356ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** Will be called from {@link AutoCompleteTextView} to prepare auto-complete list. */ 3366ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 3376ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public Filter getFilter() { 3386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return new DefaultFilter(); 3396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3406ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3416ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 3426ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Handles the result of the initial call, which brings back the list of directories as well 3436ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * as the search results for the local directories. 34474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * 34574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Must be inside a default Looper thread to avoid synchronization problem. 3466ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 3476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa protected void onFirstDirectoryLoadFinished( 3486ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa CharSequence constraint, Cursor directoryCursor, Cursor defaultDirectoryCursor) { 34974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mCurrentConstraint = constraint; 35074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 3516ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa try { 35274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final List<DirectorySearchParams> paramsList; 3536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (directoryCursor != null) { 35474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList = setupOtherDirectories(directoryCursor); 35574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else { 35674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList = null; 3576ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3596ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa int limit = 0; 3606ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 36174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (defaultDirectoryCursor != null) { 3626ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntryMap.clear(); 36374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mNonAggregatedEntries.clear(); 36474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations.clear(); 36574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa putEntriesWithCursor(defaultDirectoryCursor, true); 3666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa constructEntryList(); 3676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa limit = mPreferredMaxResultCount - getCount(); 3686ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3696ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 37074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (limit > 0 && paramsList != null) { 37174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa searchOtherDirectories(constraint, paramsList, limit); 3726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } finally { 3746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (directoryCursor != null) { 3756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa directoryCursor.close(); 3766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (defaultDirectoryCursor != null) { 3786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa defaultDirectoryCursor.close(); 3796ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3806ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3816ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3826ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 38374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private List<DirectorySearchParams> setupOtherDirectories(Cursor directoryCursor) { 3846ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final PackageManager packageManager = mContext.getPackageManager(); 38574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final List<DirectorySearchParams> paramsList = new ArrayList<DirectorySearchParams>(); 3866ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa DirectorySearchParams preferredDirectory = null; 3876ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa while (directoryCursor.moveToNext()) { 3886ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final long id = directoryCursor.getLong(DirectoryListQuery.ID); 3896ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // Skip the local invisible directory, because the default directory already includes 3916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // all local results. 3926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (id == Directory.LOCAL_INVISIBLE) { 3936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa continue; 3946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 3956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 3966ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final DirectorySearchParams params = new DirectorySearchParams(); 3976ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final String packageName = directoryCursor.getString(DirectoryListQuery.PACKAGE_NAME); 3986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final int resourceId = directoryCursor.getInt(DirectoryListQuery.TYPE_RESOURCE_ID); 3996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.directoryId = id; 4006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.displayName = directoryCursor.getString(DirectoryListQuery.DISPLAY_NAME); 4016ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.accountName = directoryCursor.getString(DirectoryListQuery.ACCOUNT_NAME); 4026ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.accountType = directoryCursor.getString(DirectoryListQuery.ACCOUNT_TYPE); 4036ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (packageName != null && resourceId != 0) { 4046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa try { 4056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final Resources resources = 4066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa packageManager.getResourcesForApplication(packageName); 4076ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa params.directoryType = resources.getString(resourceId); 4086ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (params.directoryType == null) { 4096ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Log.e(TAG, "Cannot resolve directory name: " 4106ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa + resourceId + "@" + packageName); 4116ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4126ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } catch (NameNotFoundException e) { 4136ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa Log.e(TAG, "Cannot resolve directory name: " 4146ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa + resourceId + "@" + packageName, e); 4156ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4166ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4176ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // If an account has been provided and we found a directory that 4196ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // corresponds to that account, place that directory second, directly 4206ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // underneath the local contacts. 4216ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (mAccount != null && mAccount.name.equals(params.accountName) && 4226ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mAccount.type.equals(params.accountType)) { 4236ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa preferredDirectory = params; 4246ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 42574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList.add(params); 4266ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4276ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4286ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (preferredDirectory != null) { 43074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa paramsList.add(1, preferredDirectory); 4316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 43374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return paramsList; 4346ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4356ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4366ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 4376ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Starts search in other directories 4386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 43974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private void searchOtherDirectories( 44074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa CharSequence constraint, List<DirectorySearchParams> paramsList, int limit) { 44174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final int count = paramsList.size(); 4426ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // Note: skipping the default partition (index 0), which has already been loaded 4436ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa for (int i = 1; i < count; i++) { 44474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final DirectorySearchParams params = paramsList.get(i); 44574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.constraint = constraint; 44674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (params.filter == null) { 44774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.filter = new DirectoryFilter(params); 44874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 44974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.filter.setLimit(limit); 45074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa params.filter.filter(constraint); 45174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 45274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 45374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 45474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa /** Must be inside a default Looper thread to avoid synchronization problem. */ 45574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public void onDirectoryLoadFinished( 45674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa CharSequence constraint, DirectorySearchParams params, Cursor cursor) { 45774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (cursor != null) { 45874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa try { 45974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (DEBUG) { 46074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.v(TAG, "finished loading directory \"" + params.displayName + "\"" + 46174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa " with query " + constraint); 46274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 46374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 46474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // Check if the received result matches the current constraint 46574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // If not - the user must have continued typing after the request was issued 46674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final boolean usesSameConstraint; 46774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa usesSameConstraint = TextUtils.equals(constraint, mCurrentConstraint); 46874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (usesSameConstraint) { 46974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa putEntriesWithCursor(cursor, params.directoryId == Directory.DEFAULT); 47074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa constructEntryList(); 47174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 47274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } finally { 47374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa cursor.close(); 4746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 4776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 4786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 4796ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Stores each contact information to {@link #mEntryMap}. {@link #mEntries} isn't touched here. 4806ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * 4816ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * In order to make the new information available from outside Adapter, 4826ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * call {@link #constructEntryList()} after this method. 4836ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 48474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa private void putEntriesWithCursor(Cursor cursor, boolean validContactId) { 4856ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa cursor.move(-1); 4866ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa while (cursor.moveToNext()) { 487d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final String displayName; 488d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final String destination; 489f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa final long contactId; 490f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa final long dataId; 491d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final String thumbnailUriString; 492d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (mQueryType == QUERY_TYPE_EMAIL) { 493d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa displayName = cursor.getString(EmailQuery.NAME); 494d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa destination = cursor.getString(EmailQuery.ADDRESS); 495f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa contactId = cursor.getLong(EmailQuery.CONTACT_ID); 496f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa dataId = cursor.getLong(EmailQuery.DATA_ID); 497d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa thumbnailUriString = cursor.getString(EmailQuery.PHOTO_THUMBNAIL_URI); 498d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else if (mQueryType == QUERY_TYPE_PHONE) { 499d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa displayName = cursor.getString(PhoneQuery.NAME); 500d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa destination = cursor.getString(PhoneQuery.NUMBER); 501f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa contactId = cursor.getLong(PhoneQuery.CONTACT_ID); 502f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa dataId = cursor.getLong(PhoneQuery.DATA_ID); 503d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa thumbnailUriString = cursor.getString(PhoneQuery.PHOTO_THUMBNAIL_URI); 504d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else { 505d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa throw new IndexOutOfBoundsException("Unexpected query type: " + mQueryType); 506d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 50774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 50874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // Note: At this point each entry doesn't contain have any photo (thus getPhotoBytes() 50974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // returns null). 51074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 51174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (mExistingDestinations.contains(destination)) { 51274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa continue; 51374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 51474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations.add(destination); 5156ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 51674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (!validContactId) { 517f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mNonAggregatedEntries.add(RecipientEntry.constructTopLevelEntry( 5187537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa displayName, destination, contactId, dataId, thumbnailUriString)); 51974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else if (mEntryMap.containsKey(contactId)) { 5206ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa // We already have a section for the person. 521f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final List<RecipientEntry> entryList = mEntryMap.get(contactId); 522f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira entryList.add(RecipientEntry.constructSecondLevelEntry( 5236b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira displayName, destination, contactId, dataId, thumbnailUriString)); 5246ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 525f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final List<RecipientEntry> entryList = new ArrayList<RecipientEntry>(); 526f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira entryList.add(RecipientEntry.constructTopLevelEntry( 5277537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa displayName, destination, contactId, dataId, thumbnailUriString)); 5286ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntryMap.put(contactId, entryList); 5296ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5316ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5326ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 5336ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 53474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * Constructs an actual list for this Adapter using {@link #mEntryMap}. Also tries to 53574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * fetch a cached photo for each contact entry (other than separators), or request another 53674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * thread to get one from directories. The thread ({@link #mPhotoHandlerThread}) will 53774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa * request {@link #notifyDataSetChanged()} after having the photo asynchronously. 5386ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 5396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa private void constructEntryList() { 54074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntries.clear(); 54174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa int validEntryCount = 0; 542f15b448bb9fd41ec7aea7cd95104ab3d82355a06Daisuke Miyakawa for (Map.Entry<Long, List<RecipientEntry>> mapEntry : mEntryMap.entrySet()) { 543f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final List<RecipientEntry> entryList = mapEntry.getValue(); 5446ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa final int size = entryList.size(); 5456ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa for (int i = 0; i < size; i++) { 546f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira RecipientEntry entry = entryList.get(i); 5476ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntries.add(entry); 54874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa tryFetchPhoto(entry); 54974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa validEntryCount++; 5506ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (i < size - 1) { 551f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries.add(RecipientEntry.SEP_WITHIN_GROUP); 5526ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 554f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries.add(RecipientEntry.SEP_NORMAL); 55574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (validEntryCount > mPreferredMaxResultCount) { 55674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa break; 55774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 5586ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 55974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (validEntryCount <= mPreferredMaxResultCount) { 560f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira for (RecipientEntry entry : mNonAggregatedEntries) { 56174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (validEntryCount > mPreferredMaxResultCount) { 56274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa break; 56374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 56474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntries.add(entry); 56574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa tryFetchPhoto(entry); 56674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 567f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira mEntries.add(RecipientEntry.SEP_NORMAL); 56874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa validEntryCount++; 56974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 57074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 57174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 57274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // Remove last divider 5736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (mEntries.size() > 1) { 5746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa mEntries.remove(mEntries.size() - 1); 5756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5766ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa notifyDataSetChanged(); 5776ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5786ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 579f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private void tryFetchPhoto(final RecipientEntry entry) { 58074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final Uri photoThumbnailUri = entry.getPhotoThumbnailUri(); 58174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoThumbnailUri != null) { 58274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final byte[] photoBytes = mPhotoCacheMap.get(photoThumbnailUri); 58374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoBytes != null) { 58474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa entry.setPhotoBytes(photoBytes); 58574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa // notifyDataSetChanged() should be called by a caller. 58674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else { 58774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (DEBUG) { 58874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.d(TAG, "No photo cache for " + entry.getDisplayName() 58974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa + ". Fetch one asynchronously"); 5906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 59174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa fetchPhotoAsync(entry, photoThumbnailUri); 5926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 5956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 596f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira private void fetchPhotoAsync(final RecipientEntry entry, final Uri photoThumbnailUri) { 59774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoHandler.post(new Runnable() { 59874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 59974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public void run() { 60074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final Cursor photoCursor = mContentResolver.query( 60174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa photoThumbnailUri, PhotoQuery.PROJECTION, null, null, null); 60274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoCursor != null) { 60374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa try { 60474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoCursor.moveToFirst()) { 60574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final byte[] photoBytes = photoCursor.getBlob(PhotoQuery.PHOTO); 60674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa entry.setPhotoBytes(photoBytes); 60774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 60874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mHandler.post(new Runnable() { 60974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 61074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public void run() { 61174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoCacheMap.put(photoThumbnailUri, photoBytes); 61274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa notifyDataSetChanged(); 61374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 61474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa }); 61574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 61674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } finally { 61774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa photoCursor.close(); 61874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 61974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 62074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 62174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa }); 62274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 62374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 6246b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira protected void fetchPhoto(final RecipientEntry entry, final Uri photoThumbnailUri) { 6256b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira byte[] photoBytes = mPhotoCacheMap.get(photoThumbnailUri); 6266b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira if (photoBytes != null) { 6276b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira entry.setPhotoBytes(photoBytes); 6286b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira return; 6296b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6306b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira final Cursor photoCursor = mContentResolver.query(photoThumbnailUri, PhotoQuery.PROJECTION, 6316b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira null, null, null); 6326b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira if (photoCursor != null) { 6336b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira try { 6346b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira if (photoCursor.moveToFirst()) { 6356b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira photoBytes = photoCursor.getBlob(PhotoQuery.PHOTO); 6366b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira entry.setPhotoBytes(photoBytes); 6376b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira mPhotoCacheMap.put(photoThumbnailUri, photoBytes); 6386b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6396b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } finally { 6406b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira photoCursor.close(); 6416b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6426b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6436b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira } 6446b6de6266d3bede33728cf995f1fd5c59ec5a55dMindy Pereira 645d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa private Cursor doQuery(CharSequence constraint, int limit, Long directoryId) { 646d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Cursor cursor; 647d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (mQueryType == QUERY_TYPE_EMAIL) { 648d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Uri.Builder builder = Email.CONTENT_FILTER_URI.buildUpon() 649d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendPath(constraint.toString()) 650d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, 651d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(limit + ALLOWANCE_FOR_DUPLICATES)); 652d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (directoryId != null) { 653d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, 654d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(directoryId)); 655d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 6567537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa if (mAccount != null) { 6577537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_NAME, mAccount.name); 6587537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_TYPE, mAccount.type); 6597537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa } 660d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = mContentResolver.query( 661d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.build(), EmailQuery.PROJECTION, null, null, null); 662d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else if (mQueryType == QUERY_TYPE_PHONE){ 663d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final Uri.Builder builder = Phone.CONTENT_FILTER_URI.buildUpon() 664d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendPath(constraint.toString()) 665d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, 666d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(limit + ALLOWANCE_FOR_DUPLICATES)); 667d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (directoryId != null) { 668d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, 669d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa String.valueOf(directoryId)); 670d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 6717537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa if (mAccount != null) { 6727537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_NAME, mAccount.name); 6737537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa builder.appendQueryParameter(PRIMARY_ACCOUNT_TYPE, mAccount.type); 6747537f840506bcb642bed9dc1c2bdcf6d31c6b2a7Daisuke Miyakawa } 675d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = mContentResolver.query( 676d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa builder.build(), PhoneQuery.PROJECTION, null, null, null); 677d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } else { 678d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa cursor = null; 679d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 680d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return cursor; 681d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 682d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 6836ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public void close() { 68474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntryMap.clear(); 68574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mNonAggregatedEntries.clear(); 68674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mExistingDestinations.clear(); 68774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mEntries.clear(); 68874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa mPhotoCacheMap.evictAll(); 68974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (!mPhotoHandlerThread.quit()) { 69074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa Log.w(TAG, "Failed to quit photo handler thread, ignoring it."); 69174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 6926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 6936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 6946ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 6956ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public int getCount() { 69674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return mEntries.size(); 6976ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 6986ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 6996ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 7006ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public Object getItem(int position) { 70174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return mEntries.get(position); 7026ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7036ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7046ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 7056ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa public long getItemId(int position) { 7066ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa return position; 7076ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7086ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7096ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa @Override 71074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public int getViewTypeCount() { 711f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira return RecipientEntry.ENTRY_TYPE_SIZE; 71274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 71374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa 71474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 71574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public int getItemViewType(int position) { 71674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return mEntries.get(position).getEntryType(); 71774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7186ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 71974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa @Override 72074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa public View getView(int position, View convertView, ViewGroup parent) { 721f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira final RecipientEntry entry = mEntries.get(position); 72274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa switch (entry.getEntryType()) { 723f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira case RecipientEntry.ENTRY_TYPE_SEP_NORMAL: { 724d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return convertView != null ? convertView 725d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa : mInflater.inflate(getSeparatorLayout(), parent, false); 7266ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 727f621a601e1f966c89b7aadbcca384021e14d668dMindy Pereira case RecipientEntry.ENTRY_TYPE_SEP_WITHIN_GROUP: { 72874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return convertView != null ? convertView 729d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa : mInflater.inflate(getSeparatorWithinGroupLayout(), parent, false); 7306ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 73174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa default: { 73274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa String displayName = entry.getDisplayName(); 73374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa String emailAddress = entry.getDestination(); 73474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (TextUtils.isEmpty(displayName) 73574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa || TextUtils.equals(displayName, emailAddress)) { 73674a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa displayName = emailAddress; 73774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa emailAddress = null; 73874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7396ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 740d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final View itemView = convertView != null ? convertView 741d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa : mInflater.inflate(getItemLayout(), parent, false); 742d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final TextView displayNameView = 743d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa (TextView)itemView.findViewById(getDisplayNameId()); 744d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final TextView emailAddressView = 745d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa (TextView)itemView.findViewById(getDestinationId()); 746d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa final ImageView imageView = (ImageView)itemView.findViewById(getPhotoId()); 74774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa displayNameView.setText(displayName); 74874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (!TextUtils.isEmpty(emailAddress)) { 74974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa emailAddressView.setText(emailAddress); 750e3a7365ee50e5df8d7935143bb88c65644be4b59Daisuke Miyakawa } else { 751e3a7365ee50e5df8d7935143bb88c65644be4b59Daisuke Miyakawa emailAddressView.setText(null); 75274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7536ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa if (entry.isFirstLevel()) { 75474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa displayNameView.setVisibility(View.VISIBLE); 75574a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (imageView != null) { 756d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa imageView.setVisibility(View.VISIBLE); 75774a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final byte[] photoBytes = entry.getPhotoBytes(); 75874a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa if (photoBytes != null && imageView != null) { 75974a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa final Bitmap photo = BitmapFactory.decodeByteArray( 76074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa photoBytes, 0, photoBytes.length); 76174a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa imageView.setImageBitmap(photo); 76274a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } else { 76374a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa imageView.setImageResource(getDefaultPhotoResource()); 76474a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa } 7656ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7666ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } else { 7676ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa displayNameView.setVisibility(View.GONE); 768d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa if (imageView != null) imageView.setVisibility(View.GONE); 7696ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 77074a977cbc35413866ca039d509801fe0b02e1901Daisuke Miyakawa return itemView; 7716ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7726ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7736ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa } 7746ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7756ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 776d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns a layout id for each item inside auto-complete list. 777d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * 778d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Each View must contain two TextViews (for display name and destination) and one ImageView 779d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * (for photo). Ids for those should be available via {@link #getDisplayNameId()}, 780d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * {@link #getDestinationId()}, and {@link #getPhotoId()}. 7816ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 782efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getItemLayout(); 783d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** Returns a layout id for a separator dividing two person or groups. */ 784efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getSeparatorLayout(); 7856ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 786d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns a layout id for a separator dividing two destinations for a same person or group. 7876ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 788efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getSeparatorWithinGroupLayout(); 7896ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa 7906ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa /** 7916ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * Returns a resource ID representing an image which should be shown when ther's no relevant 7926ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa * photo is available. 7936ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa */ 794efcac0cbb3efc645cd6cf1cb1e2431e1bd2b2d2aMindy Pereira protected abstract int getDefaultPhotoResource(); 795d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 796d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 797d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns an id for TextView in an item View for showing a display name. In default 798d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * {@link android.R.id#text1} is returned. 799d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 800d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa protected int getDisplayNameId() { 801d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return android.R.id.text1; 802d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 803d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 804d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 805d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns an id for TextView in an item View for showing a destination 806d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * (an email address or a phone number). 807d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * In default {@link android.R.id#text2} is returned. 808d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 809d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa protected int getDestinationId() { 810d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return android.R.id.text2; 811d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 812d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa 813d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa /** 814d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * Returns an id for ImageView in an item View for showing photo image for a person. In default 815d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa * {@link android.R.id#icon} is returned. 816d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa */ 817d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa protected int getPhotoId() { 818d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa return android.R.id.icon; 819d4baa3f2d02f1e52d325de3402e0999ac5ca65d2Daisuke Miyakawa } 8206ac7d0c6f6db2f5af06f9f2c73f24760d4df7b84Daisuke Miyakawa} 821