184dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira/* 284dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * Copyright (C) 2011 The Android Open Source Project 384dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * 484dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 584dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * you may not use this file except in compliance with the License. 684dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * You may obtain a copy of the License at 784dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * 884dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 984dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * 1084dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * Unless required by applicable law or agreed to in writing, software 1184dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 1284dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1384dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * See the License for the specific language governing permissions and 1484dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * limitations under the License. 1584dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira */ 1697d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 1797d7768576ff27d779d68f77e23925b69f3290bcMindy Pereirapackage com.android.ex.chips; 1897d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 1916923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport android.accounts.Account; 2097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.content.Context; 2197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.database.Cursor; 22a5d37c8a968edf94755215617b593d3f61738a92Makoto Onukiimport android.database.MatrixCursor; 234db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Caoimport android.graphics.drawable.StateListDrawable; 2416923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport android.net.Uri; 2516923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport android.provider.ContactsContract; 267a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedyimport android.provider.ContactsContract.Contacts; 27ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedyimport android.text.TextUtils; 281852931de1e24e77cb708f4ba010eaa269426657Mindy Pereiraimport android.text.util.Rfc822Token; 291852931de1e24e77cb708f4ba010eaa269426657Mindy Pereiraimport android.text.util.Rfc822Tokenizer; 3018987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereiraimport android.util.Log; 3197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.view.View; 3297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.view.ViewGroup; 3397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.widget.CursorAdapter; 3497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 3516923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport com.android.ex.chips.BaseRecipientAdapter.DirectoryListQuery; 3616923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport com.android.ex.chips.BaseRecipientAdapter.DirectorySearchParams; 37b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport com.android.ex.chips.DropdownChipLayouter.AdapterType; 3880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylorimport com.android.ex.chips.Queries.Query; 39a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki 4003cfe3eee5635e419ab1d70d463b2b8beac72f00Mindy Pereiraimport java.util.ArrayList; 411852931de1e24e77cb708f4ba010eaa269426657Mindy Pereiraimport java.util.HashMap; 42a5d37c8a968edf94755215617b593d3f61738a92Makoto Onukiimport java.util.HashSet; 4316923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport java.util.List; 4494fa301de71cc110671802eba8376c275b4055a4Scott Kennedyimport java.util.Map; 4594fa301de71cc110671802eba8376c275b4055a4Scott Kennedyimport java.util.Set; 461852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira 4780f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor/** 4880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor * RecipientAlternatesAdapter backs the RecipientEditTextView for managing contacts 4980f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor * queried by email or by phone number. 5080f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor */ 5197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereirapublic class RecipientAlternatesAdapter extends CursorAdapter { 528af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein public static final int MAX_LOOKUPS = 50; 5397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 5497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira private final long mCurrentId; 5597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 56007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira private int mCheckedItemPosition = -1; 57007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira 585086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira private OnCheckedItemChangedListener mCheckedItemChangedListener; 595086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira 6018987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira private static final String TAG = "RecipAlternates"; 6118987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira 6280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor public static final int QUERY_TYPE_EMAIL = 0; 6380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor public static final int QUERY_TYPE_PHONE = 1; 647a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy private final Long mDirectoryId; 65b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin private DropdownChipLayouter mDropdownChipLayouter; 664db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao private final StateListDrawable mDeleteDrawable; 6780f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor 687a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy private static final Map<String, String> sCorrectedPhotoUris = new HashMap<String, String>(); 697a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 7016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp public interface RecipientMatchCallback { 7194fa301de71cc110671802eba8376c275b4055a4Scott Kennedy public void matchesFound(Map<String, RecipientEntry> results); 7294fa301de71cc110671802eba8376c275b4055a4Scott Kennedy /** 7394fa301de71cc110671802eba8376c275b4055a4Scott Kennedy * Called with all addresses that could not be resolved to valid recipients. 7494fa301de71cc110671802eba8376c275b4055a4Scott Kennedy */ 75f7e202d8b83bfbd73ca47ba7843ebc4dd57c2fa4Scott Kennedy public void matchesNotFound(Set<String> unfoundAddresses); 7616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 7716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp 7876f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter, 794b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ArrayList<String> inAddresses, Account account, RecipientMatchCallback callback, 804b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 814b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic getMatchingRecipients(context, adapter, inAddresses, QUERY_TYPE_EMAIL, account, callback, 824b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic permissionsCheckListener); 8380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor } 8480f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor 851852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira /** 861852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira * Get a HashMap of address to RecipientEntry that contains all contact 871852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira * information for a contact with the provided address, if one exists. This 881852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira * may block the UI, so run it in an async task. 891852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira * 901852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira * @param context Context. 917211747e51623ae1305053f533c09dd335e013a2Daisuke Miyakawa * @param inAddresses Array of addresses on which to perform the lookup. 9216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp * @param callback RecipientMatchCallback called when a match or matches are found. 931852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira */ 9476f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter, 9576f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert ArrayList<String> inAddresses, int addressType, Account account, 964b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic RecipientMatchCallback callback, 974b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 9880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor Queries.Query query; 9980f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor if (addressType == QUERY_TYPE_EMAIL) { 10080f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor query = Queries.EMAIL; 10180f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor } else { 10280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor query = Queries.PHONE; 10380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor } 10403cfe3eee5635e419ab1d70d463b2b8beac72f00Mindy Pereira int addressesSize = Math.min(MAX_LOOKUPS, inAddresses.size()); 10516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp HashSet<String> addresses = new HashSet<String>(); 1061852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira StringBuilder bindString = new StringBuilder(); 1071852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira // Create the "?" string and set up arguments. 1081852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira for (int i = 0; i < addressesSize; i++) { 10903cfe3eee5635e419ab1d70d463b2b8beac72f00Mindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses.get(i).toLowerCase()); 11016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp addresses.add(tokens.length > 0 ? tokens[0].getAddress() : inAddresses.get(i)); 1111852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira bindString.append("?"); 1121852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira if (i < addressesSize - 1) { 1131852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira bindString.append(","); 1141852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira } 1151852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira } 1161852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira 11718987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira if (Log.isLoggable(TAG, Log.DEBUG)) { 11818987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira Log.d(TAG, "Doing reverse lookup for " + addresses.toString()); 11918987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira } 12018987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira 12116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp String[] addressArray = new String[addresses.size()]; 12216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp addresses.toArray(addressArray); 12316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp HashMap<String, RecipientEntry> recipientEntries = null; 12416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp Cursor c = null; 12516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp 12616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp try { 1274b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) { 128f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic c = context.getContentResolver().query( 129f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic query.getContentUri(), 130f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic query.getProjection(), 131f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic query.getProjection()[Queries.Query.DESTINATION] + " IN (" 132f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic + bindString.toString() + ")", addressArray, null); 133f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 1347a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy recipientEntries = processContactEntries(c, null /* directoryId */); 13516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp callback.matchesFound(recipientEntries); 13616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } finally { 13716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp if (c != null) { 13816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.close(); 13916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 14016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 1418af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein 1428af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein final Set<String> matchesNotFound = new HashSet<String>(); 1438af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein 1448af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein getMatchingRecipientsFromDirectoryQueries(context, recipientEntries, 1454b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic addresses, account, matchesNotFound, query, callback, permissionsCheckListener); 1468af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein 1478af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein getMatchingRecipientsFromExtensionMatcher(adapter, matchesNotFound, callback); 1488af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein } 1498af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein 1508af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein public static void getMatchingRecipientsFromDirectoryQueries(Context context, 1518af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein Map<String, RecipientEntry> recipientEntries, Set<String> addresses, 1528af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein Account account, Set<String> matchesNotFound, 1534b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic RecipientMatchCallback callback, 1544b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 1558af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein getMatchingRecipientsFromDirectoryQueries( 1568af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein context, recipientEntries, addresses, account, 1574b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic matchesNotFound, Queries.EMAIL, callback, permissionsCheckListener); 1588af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein } 1598af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein 1608af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein private static void getMatchingRecipientsFromDirectoryQueries(Context context, 1618af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein Map<String, RecipientEntry> recipientEntries, Set<String> addresses, 1628af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein Account account, Set<String> matchesNotFound, Queries.Query query, 1634b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic RecipientMatchCallback callback, 1644b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 16516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp // See if any entries did not resolve; if so, we need to check other 16616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp // directories 1678af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein 16816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp if (recipientEntries.size() < addresses.size()) { 169f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic // Run a directory query for each unmatched recipient. 170f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic HashSet<String> unresolvedAddresses = new HashSet<String>(); 171f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic for (String address : addresses) { 172f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic if (!recipientEntries.containsKey(address)) { 173f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic unresolvedAddresses.add(address); 174f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 175f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 176f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic matchesNotFound.addAll(unresolvedAddresses); 177f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic 17816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp final List<DirectorySearchParams> paramsList; 179539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy Cursor directoryCursor = null; 180539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy try { 1814b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) { 182f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic directoryCursor = context.getContentResolver().query( 183f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic DirectoryListQuery.URI, DirectoryListQuery.PROJECTION, 184f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic null, null, null); 185f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 186771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy if (directoryCursor == null) { 187f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic return; 188771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy } 189f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic paramsList = BaseRecipientAdapter.setupOtherDirectories( 190f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic context, directoryCursor, account); 191539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy } finally { 192539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy if (directoryCursor != null) { 193539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy directoryCursor.close(); 194539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy } 195539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy } 19694fa301de71cc110671802eba8376c275b4055a4Scott Kennedy 197771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy if (paramsList != null) { 198771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy Cursor directoryContactsCursor = null; 199771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy for (String unresolvedAddress : unresolvedAddresses) { 200771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy for (int i = 0; i < paramsList.size(); i++) { 201f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic final long directoryId = paramsList.get(i).directoryId; 202771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy try { 203f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic directoryContactsCursor = doQuery(unresolvedAddress, 1 /* limit */, 2044b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic directoryId, account, context, query, permissionsCheckListener); 205771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy if (directoryContactsCursor != null 206f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic && directoryContactsCursor.getCount() != 0) { 207f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic // We found the directory with at least one contact 208f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic final Map<String, RecipientEntry> entries = 209f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic processContactEntries(directoryContactsCursor, directoryId); 21094fa301de71cc110671802eba8376c275b4055a4Scott Kennedy 211f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic for (final String address : entries.keySet()) { 212f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic matchesNotFound.remove(address); 213f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 21494fa301de71cc110671802eba8376c275b4055a4Scott Kennedy 215f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic callback.matchesFound(entries); 216f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic break; 217f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 218771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy } finally { 219f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic if (directoryContactsCursor != null) { 220f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic directoryContactsCursor.close(); 221f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic directoryContactsCursor = null; 222f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 223771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy } 22416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 2251852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira } 2261852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira } 2271852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira } 2288af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein } 22994fa301de71cc110671802eba8376c275b4055a4Scott Kennedy 2308af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein public static void getMatchingRecipientsFromExtensionMatcher(BaseRecipientAdapter adapter, 2318af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein Set<String> matchesNotFound, RecipientMatchCallback callback) { 23276f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert // If no matches found in contact provider or the directories, try the extension 23376f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert // matcher. 23476f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert // todo (aalbert): This whole method needs to be in the adapter? 23576f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert if (adapter != null) { 23676f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert final Map<String, RecipientEntry> entries = 23776f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert adapter.getMatchingRecipients(matchesNotFound); 23876f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert if (entries != null && entries.size() > 0) { 23976f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert callback.matchesFound(entries); 24076f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert for (final String address : entries.keySet()) { 24176f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert matchesNotFound.remove(address); 24276f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert } 24376f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert } 24476f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert } 24594fa301de71cc110671802eba8376c275b4055a4Scott Kennedy callback.matchesNotFound(matchesNotFound); 24616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 24716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp 2487a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy private static HashMap<String, RecipientEntry> processContactEntries(Cursor c, 2497a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy Long directoryId) { 25016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp HashMap<String, RecipientEntry> recipientEntries = new HashMap<String, RecipientEntry>(); 25116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp if (c != null && c.moveToFirst()) { 25216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp do { 25316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp String address = c.getString(Queries.Query.DESTINATION); 254ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 255ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy final RecipientEntry newRecipientEntry = RecipientEntry.constructTopLevelEntry( 25616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getString(Queries.Query.NAME), 25716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getInt(Queries.Query.DISPLAY_NAME_SOURCE), 25816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getString(Queries.Query.DESTINATION), 25916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getInt(Queries.Query.DESTINATION_TYPE), 26016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getString(Queries.Query.DESTINATION_LABEL), 26116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getLong(Queries.Query.CONTACT_ID), 2627a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy directoryId, 26316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getLong(Queries.Query.DATA_ID), 26416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp c.getString(Queries.Query.PHOTO_THUMBNAIL_URI), 265514f8a75f72fa2e735418ffb5d6e30aa914fbe7bScott Kennedy true, 2667a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy c.getString(Queries.Query.LOOKUP_KEY)); 267ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 268ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy /* 269ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy * In certain situations, we may have two results for one address, where one of the 270ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy * results is just the email address, and the other has a name and photo, so we want 271ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy * to use the better one. 272ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy */ 273ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy final RecipientEntry recipientEntry = 274ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy getBetterRecipient(recipientEntries.get(address), newRecipientEntry); 275ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 276ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy recipientEntries.put(address, recipientEntry); 27716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp if (Log.isLoggable(TAG, Log.DEBUG)) { 27816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp Log.d(TAG, "Received reverse look up information for " + address 27916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp + " RESULTS: " 28016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp + " NAME : " + c.getString(Queries.Query.NAME) 28116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp + " CONTACT ID : " + c.getLong(Queries.Query.CONTACT_ID) 28216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp + " ADDRESS :" + c.getString(Queries.Query.DESTINATION)); 28316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 28416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } while (c.moveToNext()); 28516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 2861852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira return recipientEntries; 2871852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira } 2881852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira 289ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy /** 290ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy * Given two {@link RecipientEntry}s for the same email address, this will return the one that 291ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy * contains more complete information for display purposes. Defaults to <code>entry2</code> if 292ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy * no significant differences are found. 293ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy */ 29478f38a09c9753c0ac1838ce0bfd3a6bc1a307ff7Scott Kennedy static RecipientEntry getBetterRecipient(final RecipientEntry entry1, 295ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy final RecipientEntry entry2) { 296ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy // If only one has passed in, use it 297ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if (entry2 == null) { 298ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry1; 299ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 300ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 301ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if (entry1 == null) { 302ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry2; 303ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 304ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 305ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy // If only one has a display name, use it 306ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if (!TextUtils.isEmpty(entry1.getDisplayName()) 307ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy && TextUtils.isEmpty(entry2.getDisplayName())) { 308ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry1; 309ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 310ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 311ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if (!TextUtils.isEmpty(entry2.getDisplayName()) 312ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy && TextUtils.isEmpty(entry1.getDisplayName())) { 313ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry2; 314ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 315ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 316ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy // If only one has a display name that is not the same as the destination, use it 317ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if (!TextUtils.equals(entry1.getDisplayName(), entry1.getDestination()) 318ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy && TextUtils.equals(entry2.getDisplayName(), entry2.getDestination())) { 319ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry1; 320ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 321ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 322ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if (!TextUtils.equals(entry2.getDisplayName(), entry2.getDestination()) 323ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy && TextUtils.equals(entry1.getDisplayName(), entry1.getDestination())) { 324ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry2; 325ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 326ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 327ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy // If only one has a photo, use it 328ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if ((entry1.getPhotoThumbnailUri() != null || entry1.getPhotoBytes() != null) 329ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy && (entry2.getPhotoThumbnailUri() == null && entry2.getPhotoBytes() == null)) { 330ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry1; 331ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 332ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 333ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy if ((entry2.getPhotoThumbnailUri() != null || entry2.getPhotoBytes() != null) 334ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy && (entry1.getPhotoThumbnailUri() == null && entry1.getPhotoBytes() == null)) { 335ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry2; 336ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 337ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 338ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy // Go with the second option as a default 339ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy return entry2; 340ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy } 341ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy 34216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp private static Cursor doQuery(CharSequence constraint, int limit, Long directoryId, 3434b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic Account account, Context context, Query query, 3444b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 3454b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic if (!ChipsUtil.hasPermissions(context, permissionsCheckListener)) { 346f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic if (Log.isLoggable(TAG, Log.DEBUG)) { 347f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic Log.d(TAG, "Not doing query because we don't have required permissions."); 348f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 349f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic return null; 350f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 35116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp final Uri.Builder builder = query 35216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp .getContentFilterUri() 35316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp .buildUpon() 35416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp .appendPath(constraint.toString()) 35516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, 35616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp String.valueOf(limit + BaseRecipientAdapter.ALLOWANCE_FOR_DUPLICATES)); 35716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp if (directoryId != null) { 35816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, 35916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp String.valueOf(directoryId)); 36016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 36116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp if (account != null) { 36216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp builder.appendQueryParameter(BaseRecipientAdapter.PRIMARY_ACCOUNT_NAME, account.name); 36316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp builder.appendQueryParameter(BaseRecipientAdapter.PRIMARY_ACCOUNT_TYPE, account.type); 36416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 365f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic return context.getContentResolver() 366f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .query(builder.build(), query.getProjection(), null, null, null); 36716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp } 36816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp 3697a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId, 3707a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener, 3714b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic DropdownChipLayouter dropdownChipLayouter, 3724b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 3734db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao this(context, contactId, directoryId, lookupKey, currentId, queryMode, listener, 3744b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic dropdownChipLayouter, null, permissionsCheckListener); 3754db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao } 3764db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao 3774db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId, 3784db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener, 3794b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic DropdownChipLayouter dropdownChipLayouter, StateListDrawable deleteDrawable, 3804b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 3817a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy super(context, 3824b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic getCursorForConstruction(context, contactId, directoryId, lookupKey, queryMode, 3834b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic permissionsCheckListener), 3844b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic 0); 38597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira mCurrentId = currentId; 3867a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy mDirectoryId = directoryId; 3875086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira mCheckedItemChangedListener = listener; 38880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor 389b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin mDropdownChipLayouter = dropdownChipLayouter; 3904db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao mDeleteDrawable = deleteDrawable; 39180f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor } 39280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor 3937a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy private static Cursor getCursorForConstruction(Context context, long contactId, 3944b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic Long directoryId, String lookupKey, int queryType, 3954b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic ChipsUtil.PermissionsCheckListener permissionsCheckListener) { 396f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic final Uri uri; 3977a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final String desiredMimeType; 398f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic final String[] projection; 399f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic 40080f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor if (queryType == QUERY_TYPE_EMAIL) { 401f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic projection = Queries.EMAIL.getProjection(); 4027a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 4037a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (directoryId == null || lookupKey == null) { 4047a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy uri = Queries.EMAIL.getContentUri(); 4057a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy desiredMimeType = null; 4067a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } else { 407f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic uri = Contacts.getLookupUri(contactId, lookupKey) 408f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .buildUpon() 409f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .appendPath(Contacts.Entity.CONTENT_DIRECTORY) 410f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .appendQueryParameter( 411f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)) 412f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .build(); 4137a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy desiredMimeType = ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE; 4147a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 41580f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor } else { 416f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic projection = Queries.PHONE.getProjection(); 4177a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 4187a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (lookupKey == null) { 4197a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy uri = Queries.PHONE.getContentUri(); 4207a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy desiredMimeType = null; 4217a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } else { 422f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic uri = Contacts.getLookupUri(contactId, lookupKey) 423f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .buildUpon() 424f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .appendPath(Contacts.Entity.CONTENT_DIRECTORY) 425f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .appendQueryParameter( 426f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)) 427f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .build(); 4287a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy desiredMimeType = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE; 4297a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 430f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } 431f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic 432f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic final String selection = new StringBuilder() 433f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .append(projection[Queries.Query.CONTACT_ID]) 434f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .append(" = ?") 435f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic .toString(); 436f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic final Cursor cursor; 4374b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) { 438a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki cursor = context.getContentResolver().query( 439f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic uri, projection, selection, new String[] {String.valueOf(contactId)}, null); 440f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic } else { 441f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic cursor = new MatrixCursor(projection); 44280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor } 4437a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 4447a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final Cursor resultCursor = removeUndesiredDestinations(cursor, desiredMimeType, lookupKey); 4457a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy cursor.close(); 4467a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 4477a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy return resultCursor; 448a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki } 449a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki 450a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki /** 451a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * @return a new cursor based on the given cursor with all duplicate destinations removed. 452a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * 453a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * It's only intended to use for the alternate list, so... 454a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * - This method ignores all other fields and dedupe solely on the destination. Normally, 455a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * if a cursor contains multiple contacts and they have the same destination, we'd still want 456a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * to show both. 457a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * - This method creates a MatrixCursor, so all data will be kept in memory. We wouldn't want 458a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * to do this if the original cursor is large, but it's okay here because the alternate list 459a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki * won't be that big. 4607a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy * 4617a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy * @param desiredMimeType If this is non-<code>null</code>, only entries with this mime type 4627a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy * will be added to the cursor 4637a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy * @param lookupKey The lookup key used for this contact if there isn't one in the cursor. This 4647a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy * should be the same one used in the query that returned the cursor 465a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki */ 466a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki // Visible for testing 4677a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy static Cursor removeUndesiredDestinations(final Cursor original, final String desiredMimeType, 4687a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final String lookupKey) { 469a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki final MatrixCursor result = new MatrixCursor( 470a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getColumnNames(), original.getCount()); 471a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki final HashSet<String> destinationsSeen = new HashSet<String>(); 472a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki 4737a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy String defaultDisplayName = null; 4747a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy String defaultPhotoThumbnailUri = null; 4757a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy int defaultDisplayNameSource = 0; 4767a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 4777a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy // Find some nice defaults in case we need them 4787a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy original.moveToPosition(-1); 4797a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy while (original.moveToNext()) { 4807a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final String mimeType = original.getString(Query.MIME_TYPE); 4817a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 4827a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals( 4837a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy mimeType)) { 4847a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy // Store this data 4857a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy defaultDisplayName = original.getString(Query.NAME); 4867a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy defaultPhotoThumbnailUri = original.getString(Query.PHOTO_THUMBNAIL_URI); 4877a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy defaultDisplayNameSource = original.getInt(Query.DISPLAY_NAME_SOURCE); 4887a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy break; 4897a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 4907a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 4917a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 492a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.moveToPosition(-1); 493a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki while (original.moveToNext()) { 4947a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (desiredMimeType != null) { 4957a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final String mimeType = original.getString(Query.MIME_TYPE); 4967a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (!desiredMimeType.equals(mimeType)) { 4977a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy continue; 4987a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 4997a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 500a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki final String destination = original.getString(Query.DESTINATION); 501a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki if (destinationsSeen.contains(destination)) { 502a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki continue; 503a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki } 504a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki destinationsSeen.add(destination); 505a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki 5067a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final Object[] row = new Object[] { 507a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getString(Query.NAME), 508a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getString(Query.DESTINATION), 509a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getInt(Query.DESTINATION_TYPE), 510a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getString(Query.DESTINATION_LABEL), 511a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getLong(Query.CONTACT_ID), 512a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getLong(Query.DATA_ID), 513a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki original.getString(Query.PHOTO_THUMBNAIL_URI), 5147a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy original.getInt(Query.DISPLAY_NAME_SOURCE), 5157a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy original.getString(Query.LOOKUP_KEY), 5167a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy original.getString(Query.MIME_TYPE) 5177a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy }; 5187a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 5197a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (row[Query.NAME] == null) { 5207a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy row[Query.NAME] = defaultDisplayName; 5217a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5227a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (row[Query.PHOTO_THUMBNAIL_URI] == null) { 5237a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy row[Query.PHOTO_THUMBNAIL_URI] = defaultPhotoThumbnailUri; 5247a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5257a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if ((Integer) row[Query.DISPLAY_NAME_SOURCE] == 0) { 5267a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy row[Query.DISPLAY_NAME_SOURCE] = defaultDisplayNameSource; 5277a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5287a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (row[Query.LOOKUP_KEY] == null) { 5297a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy row[Query.LOOKUP_KEY] = lookupKey; 5307a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5317a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 5327a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy // Ensure we don't have two '?' like content://.../...?account_name=...?sz=... 5337a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final String photoThumbnailUri = (String) row[Query.PHOTO_THUMBNAIL_URI]; 5347a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (photoThumbnailUri != null) { 5357a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (sCorrectedPhotoUris.containsKey(photoThumbnailUri)) { 5367a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy row[Query.PHOTO_THUMBNAIL_URI] = sCorrectedPhotoUris.get(photoThumbnailUri); 5377a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } else if (photoThumbnailUri.indexOf('?') != photoThumbnailUri.lastIndexOf('?')) { 5387a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final String[] parts = photoThumbnailUri.split("\\?"); 5397a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final StringBuilder correctedUriBuilder = new StringBuilder(); 5407a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy for (int i = 0; i < parts.length; i++) { 5417a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy if (i == 1) { 5427a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy correctedUriBuilder.append("?"); // We only want one of these 5437a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } else if (i > 1) { 5447a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy correctedUriBuilder.append("&"); // And we want these elsewhere 5457a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5467a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy correctedUriBuilder.append(parts[i]); 5477a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5487a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 5497a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy final String correctedUri = correctedUriBuilder.toString(); 5507a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy sCorrectedPhotoUris.put(photoThumbnailUri, correctedUri); 5517a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy row[Query.PHOTO_THUMBNAIL_URI] = correctedUri; 5527a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5537a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy } 5547a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy 5557a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy result.addRow(row); 556a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki } 557a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki 558a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki return result; 55997d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 56097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 56197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira @Override 56297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira public long getItemId(int position) { 56397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira Cursor c = getCursor(); 5643bb52162b7e842243d4a14e73c15b20dbd1804d7Mindy Pereira if (c.moveToPosition(position)) { 56580f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor c.getLong(Queries.Query.DATA_ID); 5663bb52162b7e842243d4a14e73c15b20dbd1804d7Mindy Pereira } 5673bb52162b7e842243d4a14e73c15b20dbd1804d7Mindy Pereira return -1; 56897d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 56997d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 57097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira public RecipientEntry getRecipientEntry(int position) { 57197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira Cursor c = getCursor(); 57297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira c.moveToPosition(position); 57380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor return RecipientEntry.constructTopLevelEntry( 57480f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor c.getString(Queries.Query.NAME), 57500adb32f3cea49ec82467c0e1a9e42659b556836Makoto Onuki c.getInt(Queries.Query.DISPLAY_NAME_SOURCE), 57680f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor c.getString(Queries.Query.DESTINATION), 57780f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor c.getInt(Queries.Query.DESTINATION_TYPE), 57880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor c.getString(Queries.Query.DESTINATION_LABEL), 57980f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor c.getLong(Queries.Query.CONTACT_ID), 5807a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy mDirectoryId, 58180f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor c.getLong(Queries.Query.DATA_ID), 582ccb8e237ec80934d1c983bb61f66b75541786ddcmindyp c.getString(Queries.Query.PHOTO_THUMBNAIL_URI), 583514f8a75f72fa2e735418ffb5d6e30aa914fbe7bScott Kennedy true, 5847a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy c.getString(Queries.Query.LOOKUP_KEY)); 58597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 58697d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 58797d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira @Override 58897d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira public View getView(int position, View convertView, ViewGroup parent) { 58967ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira Cursor cursor = getCursor(); 59067ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira cursor.moveToPosition(position); 59197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira if (convertView == null) { 5924ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao convertView = mDropdownChipLayouter.newView(AdapterType.RECIPIENT_ALTERNATES); 593007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira } 59480f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor if (cursor.getLong(Queries.Query.DATA_ID) == mCurrentId) { 595007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira mCheckedItemPosition = position; 5965086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira if (mCheckedItemChangedListener != null) { 5975086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira mCheckedItemChangedListener.onCheckedItemChanged(mCheckedItemPosition); 5985086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira } 59997d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 60067ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira bindView(convertView, convertView.getContext(), cursor); 60197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira return convertView; 60297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 60397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 60497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira @Override 60597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira public void bindView(View view, Context context, Cursor cursor) { 60667ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira int position = cursor.getPosition(); 60767ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira RecipientEntry entry = getRecipientEntry(position); 608b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin 609b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin mDropdownChipLayouter.bindView(view, null, entry, position, 6104db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao AdapterType.RECIPIENT_ALTERNATES, null, mDeleteDrawable); 61197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 61297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 61397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira @Override 61497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira public View newView(Context context, Cursor cursor, ViewGroup parent) { 6154ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao return mDropdownChipLayouter.newView(AdapterType.RECIPIENT_ALTERNATES); 61697d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 61797d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira 6185086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira /*package*/ static interface OnCheckedItemChangedListener { 6195086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira public void onCheckedItemChanged(int position); 62097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira } 62197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira} 622