BaseEmailAddressAdapter.java revision 22cb78016de447ec1a1b270a6fc22352c3186929
15cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov/* 25cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project 35cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * 45cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 55cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * you may not use this file except in compliance with the License. 65cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * You may obtain a copy of the License at 75cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * 85cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 95cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * 105cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 115cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 125cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * See the License for the specific language governing permissions and 145cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * limitations under the License. 155cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 165cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 175cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovpackage com.android.common.contacts; 185cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 195cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport com.android.common.widget.CompositeCursorAdapter; 205cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 215cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.accounts.Account; 225cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.content.ContentResolver; 235cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.content.Context; 245cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.content.pm.PackageManager; 255cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.content.pm.PackageManager.NameNotFoundException; 265cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.content.res.Resources; 275cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.database.Cursor; 285cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.database.MatrixCursor; 295cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.net.Uri; 305cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.provider.ContactsContract; 315cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 325cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 335cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.text.TextUtils; 345cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.text.util.Rfc822Token; 355cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.util.Log; 365cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.view.View; 375cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.view.ViewGroup; 385cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.widget.Filter; 395cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport android.widget.Filterable; 405cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 415cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport java.util.ArrayList; 425cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovimport java.util.List; 435cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 445cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov/** 455cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * A base class for email address autocomplete adapters. It uses 465cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * {@link Email#CONTENT_FILTER_URI} to search for data rows by email address 475cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * and/or contact name. It also searches registered {@link Directory}'s. 485cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 495cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikovpublic abstract class BaseEmailAddressAdapter extends CompositeCursorAdapter implements Filterable { 505cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 515cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private static final String TAG = "BaseEmailAddressAdapter"; 525cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 5322cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov // TODO: revert to references to the Directory class as soon as the 5422cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov // issue with the dependency on SDK 8 is resolved 5522cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov 5622cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov // This is Directory.LOCAL_INVISIBLE 5722cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final long DIRECTORY_LOCAL_INVISIBLE = 1; 5822cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov 5922cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov // This is ContactsContract.DIRECTORY_PARAM_KEY 6022cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final String DIRECTORY_PARAM_KEY = "directory"; 6122cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov 625cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 635cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Model object for a {@link Directory} row. There is a partition in the 645cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * {@link CompositeCursorAdapter} for every directory (except 655cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * {@link Directory#LOCAL_INVISIBLE}. 665cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 675cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public final static class DirectoryPartition extends CompositeCursorAdapter.Partition { 685cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public long directoryId; 695cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public String directoryType; 705cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public String displayName; 715cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public String accountName; 725cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public String accountType; 735cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public boolean loading; 745cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public CharSequence constraint; 755cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public DirectoryPartitionFilter filter; 765cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 775cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public DirectoryPartition() { 785cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov super(false, false); 795cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 805cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 815cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 825cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private static class EmailQuery { 835cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final String[] PROJECTION = { 845cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Contacts.DISPLAY_NAME, // 0 8522cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov Email.DATA // 1 865cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov }; 875cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 885cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int NAME = 0; 895cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int ADDRESS = 1; 905cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 915cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 925cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private static class DirectoryListQuery { 9322cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov 9422cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov // TODO: revert to references to the Directory class as soon as the 9522cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov // issue with the dependency on SDK 8 is resolved 9622cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov public static final Uri URI = 9722cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, "directories"); 9822cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final String DIRECTORY_ID = "_id"; 9922cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final String DIRECTORY_ACCOUNT_NAME = "accountName"; 10022cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final String DIRECTORY_ACCOUNT_TYPE = "accountType"; 10122cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final String DIRECTORY_DISPLAY_NAME = "displayName"; 10222cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final String DIRECTORY_PACKAGE_NAME = "packageName"; 10322cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov private static final String DIRECTORY_TYPE_RESOURCE_ID = "typeResourceId"; 10422cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov 1055cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final String[] PROJECTION = { 10622cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov DIRECTORY_ID, // 0 10722cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov DIRECTORY_ACCOUNT_NAME, // 1 10822cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov DIRECTORY_ACCOUNT_TYPE, // 2 10922cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov DIRECTORY_DISPLAY_NAME, // 3 11022cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov DIRECTORY_PACKAGE_NAME, // 4 11122cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov DIRECTORY_TYPE_RESOURCE_ID, // 5 1125cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov }; 1135cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1145cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int ID = 0; 1155cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int ACCOUNT_NAME = 1; 1165cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int ACCOUNT_TYPE = 2; 1175cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int DISPLAY_NAME = 3; 1185cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int PACKAGE_NAME = 4; 1195cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public static final int TYPE_RESOURCE_ID = 5; 1205cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1215cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1225cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 1235cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * A fake column name that indicates a "Searching..." item in the list. 1245cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 1255cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private static final String SEARCHING_CURSOR_MARKER = "searching"; 1265cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1275cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 1285cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * An asynchronous filter used for loading two data sets: email rows from the local 1295cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * contact provider and the list of {@link Directory}'s. 1305cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 1315cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private final class DefaultPartitionFilter extends Filter { 1325cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 1335cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected FilterResults performFiltering(CharSequence constraint) { 1345cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Cursor directoryCursor = null; 1355cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (!mDirectoriesLoaded) { 1365cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov directoryCursor = mContentResolver.query( 13722cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov DirectoryListQuery.URI, DirectoryListQuery.PROJECTION, null, null, null); 1385cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov mDirectoriesLoaded = true; 1395cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1405cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1415cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov FilterResults results = new FilterResults(); 1425cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Cursor cursor = null; 1435cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (!TextUtils.isEmpty(constraint)) { 1445cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Uri uri = Uri.withAppendedPath( 1455cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Email.CONTENT_FILTER_URI, Uri.encode(constraint.toString())); 1465cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov cursor = mContentResolver.query(uri, EmailQuery.PROJECTION, null, null, null); 1475cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov results.count = cursor.getCount(); 1485cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1495cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov results.values = new Cursor[] { directoryCursor, cursor }; 1505cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return results; 1515cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1525cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1535cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 1545cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected void publishResults(CharSequence constraint, FilterResults results) { 1555cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (results.values != null) { 1565cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Cursor[] cursors = (Cursor[]) results.values; 1575cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov onDirectoryLoadFinished(constraint, cursors[0], cursors[1]); 1585cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1595cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov results.count = getCount(); 1605cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1615cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1625cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 1635cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public CharSequence convertResultToString(Object resultValue) { 1645cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return makeDisplayString((Cursor) resultValue); 1655cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1665cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1675cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1685cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 1695cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * An asynchronous filter that performs search in a particular directory. 1705cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 1715cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private final class DirectoryPartitionFilter extends Filter { 1725cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1735cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private final int mPartitionIndex; 1745cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private final long mDirectoryId; 1755cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1765cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public DirectoryPartitionFilter(int partitionIndex, long directoryId) { 1775cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov this.mPartitionIndex = partitionIndex; 1785cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov this.mDirectoryId = directoryId; 1795cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1805cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1815cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 1825cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected FilterResults performFiltering(CharSequence constraint) { 1835cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov FilterResults results = new FilterResults(); 1845cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (!TextUtils.isEmpty(constraint)) { 1855cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Uri uri = Email.CONTENT_FILTER_URI.buildUpon() 1865cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov .appendPath(constraint.toString()) 18722cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov .appendQueryParameter(DIRECTORY_PARAM_KEY, String.valueOf(mDirectoryId)) 1885cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov .build(); 1895cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Cursor cursor = mContentResolver.query( 1905cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov uri, EmailQuery.PROJECTION, null, null, null); 1915cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov results.values = cursor; 1925cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1935cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return results; 1945cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 1955cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 1965cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 1975cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected void publishResults(CharSequence constraint, FilterResults results) { 1985cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Cursor cursor = (Cursor) results.values; 1995cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov onPartitionLoadFinished(constraint, mPartitionIndex, cursor); 2005cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov results.count = getCount(); 2015cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2025cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2035cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2045cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected final ContentResolver mContentResolver; 2055cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private boolean mDirectoriesLoaded; 2065cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private Account mAccount; 2075cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2085cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public BaseEmailAddressAdapter(Context context) { 2095cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov super(context); 2105cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov mContentResolver = context.getContentResolver(); 2115cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2125cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2135cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 2145cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Set the account when known. Causes the search to prioritize contacts from 2155cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * that account. 2165cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 2175cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public void setAccount(Account account) { 2185cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov mAccount = account; 2195cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2205cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2215cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 2225cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Override to create a view for line item in the autocomplete suggestion list UI. 2235cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 2245cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected abstract View inflateItemView(ViewGroup parent); 2255cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2265cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 2275cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Override to populate the autocomplete suggestion line item UI with data. 2285cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 2295cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected abstract void bindView(View view, String directoryType, String directoryName, 2305cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String displayName, String emailAddress); 2315cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2325cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 2335cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Override to create a view for a "Searching directory" line item, which is 2345cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * displayed temporarily while the corresponding filter is running. 2355cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 2365cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected abstract View inflateItemViewLoading(ViewGroup parent); 2375cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2385cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 2395cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Override to populate the "Searching directory" line item UI with data. 2405cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 2415cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected abstract void bindViewLoading(View view, String directoryType, String directoryName); 2425cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2435cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 2445cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected int getItemViewType(int partitionIndex, int position) { 2455cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov DirectoryPartition partition = (DirectoryPartition)getPartition(partitionIndex); 2465cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return partition.loading ? 1 : 0; 2475cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2485cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2495cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 2505cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected View newView(Context context, int partitionIndex, Cursor cursor, 2515cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov int position, ViewGroup parent) { 2525cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov DirectoryPartition partition = (DirectoryPartition)getPartition(partitionIndex); 2535cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (partition.loading) { 2545cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return inflateItemViewLoading(parent); 2555cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } else { 2565cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return inflateItemView(parent); 2575cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2585cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2595cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2605cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 2615cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected void bindView(View v, int partition, Cursor cursor, int position) { 2625cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov DirectoryPartition directoryPartition = (DirectoryPartition)getPartition(partition); 2635cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String directoryType = directoryPartition.directoryType; 2645cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String directoryName = directoryPartition.displayName; 2655cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (directoryPartition.loading) { 2665cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov bindViewLoading(v, directoryType, directoryName); 2675cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } else { 2685cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String displayName = cursor.getString(EmailQuery.NAME); 2695cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String emailAddress = cursor.getString(EmailQuery.ADDRESS); 2705cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov bindView(v, directoryType, directoryName, displayName, emailAddress); 2715cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2725cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2735cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2745cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 2755cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public boolean areAllItemsEnabled() { 2765cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return false; 2775cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2785cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2795cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 2805cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected boolean isEnabled(int partitionIndex, int position) { 2815cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // The "Searching..." item should not be selectable 2825cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return !((DirectoryPartition)getPartition(partitionIndex)).loading; 2835cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2845cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2855cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov @Override 2865cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public Filter getFilter() { 2875cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return new DefaultPartitionFilter(); 2885cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 2895cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 2905cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 2915cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Handles the result of the initial call, which brings back the list of 2925cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * directories as well as the search results for the local directories. 2935cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 2945cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov protected void onDirectoryLoadFinished( 2955cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov CharSequence constraint, Cursor directoryCursor, Cursor defaultPartitionCursor) { 2965cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (directoryCursor != null) { 2975cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov PackageManager packageManager = getContext().getPackageManager(); 2985cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov DirectoryPartition preferredDirectory = null; 2995cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov List<DirectoryPartition> directories = new ArrayList<DirectoryPartition>(); 3005cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov while (directoryCursor.moveToNext()) { 3015cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov long id = directoryCursor.getLong(DirectoryListQuery.ID); 3025cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3035cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // Skip the local invisible directory, because the default directory 3045cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // already includes all local results. 30522cb78016de447ec1a1b270a6fc22352c3186929Dmitri Plotnikov if (id == DIRECTORY_LOCAL_INVISIBLE) { 3065cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov continue; 3075cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3085cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3095cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov DirectoryPartition partition = new DirectoryPartition(); 3105cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.directoryId = id; 3115cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.displayName = directoryCursor.getString(DirectoryListQuery.DISPLAY_NAME); 3125cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.accountName = directoryCursor.getString(DirectoryListQuery.ACCOUNT_NAME); 3135cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.accountType = directoryCursor.getString(DirectoryListQuery.ACCOUNT_TYPE); 3145cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String packageName = directoryCursor.getString(DirectoryListQuery.PACKAGE_NAME); 3155cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov int resourceId = directoryCursor.getInt(DirectoryListQuery.TYPE_RESOURCE_ID); 3165cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (packageName != null && resourceId != 0) { 3175cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov try { 3185cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Resources resources = 3195cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov packageManager.getResourcesForApplication(packageName); 3205cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.directoryType = resources.getString(resourceId); 3215cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (partition.directoryType == null) { 3225cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Log.e(TAG, "Cannot resolve directory name: " 3235cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov + resourceId + "@" + packageName); 3245cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3255cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } catch (NameNotFoundException e) { 3265cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov Log.e(TAG, "Cannot resolve directory name: " 3275cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov + resourceId + "@" + packageName, e); 3285cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3295cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3305cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3315cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // If an account has been provided and we found a directory that 3325cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // corresponds to that account, place that directory second, directly 3335cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // underneath the local contacts. 3345cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (mAccount != null && mAccount.name.equals(partition.accountName) && 3355cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov mAccount.type.equals(partition.accountType)) { 3365cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov preferredDirectory = partition; 3375cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } else { 3385cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov directories.add(partition); 3395cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3405cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3415cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3425cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (preferredDirectory != null) { 3435cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov directories.add(1, preferredDirectory); 3445cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3455cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3465cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov for (DirectoryPartition partition : directories) { 3475cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov addPartition(partition); 3485cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3495cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3505cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3515cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // The filter has loaded results for the default partition too. 3525cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (defaultPartitionCursor != null && getPartitionCount() > 0) { 3535cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov changeCursor(0, defaultPartitionCursor); 3545cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3555cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3565cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // Start search in other directories 3575cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov int count = getPartitionCount(); 3585cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // Note: skipping the default partition (index 0), which has already been loaded 3595cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov for (int i = 1; i < count; i++) { 3605cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov DirectoryPartition partition = (DirectoryPartition) getPartition(i); 3615cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.constraint = constraint; 3625cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3635cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (!partition.loading) { 3645cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.loading = true; 3655cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov changeCursor(i, createLoadingCursor()); 3665cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3675cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3685cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (partition.filter == null) { 3695cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.filter = new DirectoryPartitionFilter(i, partition.directoryId); 3705cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3715cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.filter.filter(constraint); 3725cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3735cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3745cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3755cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov /** 3765cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov * Creates a dummy cursor to represent the "Searching directory..." item. 3775cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov */ 3785cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private Cursor createLoadingCursor() { 3795cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(new String[]{SEARCHING_CURSOR_MARKER}); 3805cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov cursor.addRow(new Object[]{""}); 3815cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return cursor; 3825cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 3835cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 3845cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov public void onPartitionLoadFinished( 3855cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov CharSequence constraint, int partitionIndex, Cursor cursor) { 3865cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (partitionIndex < getPartitionCount()) { 3875cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov DirectoryPartition partition = (DirectoryPartition) getPartition(partitionIndex); 3885cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // Check if the received result matches the current constraint 3895cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // If not - the user must have continued typing after the request 3905cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // was issued 3915cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (TextUtils.equals(constraint, partition.constraint)) { 3925cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov partition.loading = false; 3935cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov changeCursor(partitionIndex, cursor); 3945cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } else { 3955cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // We got the result for an unexpected query (the user is still typing) 3965cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov // Just ignore this result 3975cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (cursor != null) { 3985cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov cursor.close(); 3995cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 4005cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 4015cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } else if (cursor != null) { 4025cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov cursor.close(); 4035cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 4045cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 4055cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 4065cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov private final String makeDisplayString(Cursor cursor) { 4075cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov if (cursor.getColumnName(0).equals(SEARCHING_CURSOR_MARKER)) { 4085cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return ""; 4095cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 4105cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov 4115cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String name = cursor.getString(EmailQuery.NAME); 4125cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov String address = cursor.getString(EmailQuery.ADDRESS); 4135cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov return new Rfc822Token(name, address, null).toString(); 4145cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov } 4155cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov} 416