private Cursor doQuery(CharSequence constraint, int limit, Long directoryId) { final Uri.Builder builder = mQuery .getContentFilterUri() .buildUpon() .appendPath(constraint.toString()) .appendQueryParameter( ContactsContract.LIMIT_PARAM_KEY, String.valueOf(limit + ALLOWANCE_FOR_DUPLICATES)); if (directoryId != null) { builder.appendQueryParameter( ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)); } if (mAccount != null) { builder.appendQueryParameter(PRIMARY_ACCOUNT_NAME, mAccount.name); builder.appendQueryParameter(PRIMARY_ACCOUNT_TYPE, mAccount.type); } final long start = System.currentTimeMillis(); final Cursor cursor = mContentResolver.query(builder.build(), mQuery.getProjection(), null, null, null); final long end = System.currentTimeMillis(); if (DEBUG) { Log.d( TAG, "Time for autocomplete (query: " + constraint + ", directoryId: " + directoryId + ", num_of_results: " + (cursor != null ? cursor.getCount() : "null") + "): " + (end - start) + " ms"); } return cursor; }
@Override public View getView(int position, View convertView, ViewGroup parent) { final RecipientEntry entry = getEntries().get(position); String displayName = entry.getDisplayName(); String destination = entry.getDestination(); if (TextUtils.isEmpty(displayName) || TextUtils.equals(displayName, destination)) { displayName = destination; // We only show the destination for secondary entries, so clear it // only for the first level. if (entry.isFirstLevel()) { destination = null; } } final View itemView = convertView != null ? convertView : mInflater.inflate(getItemLayout(), parent, false); final TextView displayNameView = (TextView) itemView.findViewById(getDisplayNameId()); final TextView destinationView = (TextView) itemView.findViewById(getDestinationId()); final TextView destinationTypeView = (TextView) itemView.findViewById(getDestinationTypeId()); final ImageView imageView = (ImageView) itemView.findViewById(getPhotoId()); displayNameView.setText(displayName); if (!TextUtils.isEmpty(destination)) { destinationView.setText(destination); } else { destinationView.setText(null); } if (destinationTypeView != null) { final CharSequence destinationType = mQuery .getTypeLabel( mContext.getResources(), entry.getDestinationType(), entry.getDestinationLabel()) .toString() .toUpperCase(); destinationTypeView.setText(destinationType); } if (entry.isFirstLevel()) { displayNameView.setVisibility(View.VISIBLE); if (imageView != null) { imageView.setVisibility(View.VISIBLE); final byte[] photoBytes = entry.getPhotoBytes(); if (photoBytes != null) { final Bitmap photo = BitmapFactory.decodeByteArray(photoBytes, 0, photoBytes.length); imageView.setImageBitmap(photo); } else { imageView.setImageResource(getDefaultPhotoResource()); } } } else { displayNameView.setVisibility(View.GONE); if (imageView != null) { imageView.setVisibility(View.INVISIBLE); } } return itemView; }
/** * Get a HashMap of address to RecipientEntry that contains all contact information for a contact * with the provided address, if one exists. This may block the UI, so run it in an async task. * * @param context Context. * @param inAddresses Array of addresses on which to perform the lookup. * @param callback RecipientMatchCallback called when a match or matches are found. */ public static void getMatchingRecipients( Context context, BaseRecipientAdapter adapter, ArrayList<String> inAddresses, int addressType, Account account, RecipientMatchCallback callback) { Queries.Query query; if (addressType == QUERY_TYPE_EMAIL) { query = Queries.EMAIL; } else { query = Queries.PHONE; } int addressesSize = Math.min(MAX_LOOKUPS, inAddresses.size()); HashSet<String> addresses = new HashSet<String>(); StringBuilder bindString = new StringBuilder(); // Create the "?" string and set up arguments. for (int i = 0; i < addressesSize; i++) { Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses.get(i).toLowerCase()); addresses.add(tokens.length > 0 ? tokens[0].getAddress() : inAddresses.get(i)); bindString.append("?"); if (i < addressesSize - 1) { bindString.append(","); } } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Doing reverse lookup for " + addresses.toString()); } String[] addressArray = new String[addresses.size()]; addresses.toArray(addressArray); HashMap<String, RecipientEntry> recipientEntries = null; Cursor c = null; try { c = context .getContentResolver() .query( query.getContentUri(), query.getProjection(), query.getProjection()[Queries.Query.DESTINATION] + " IN (" + bindString.toString() + ")", addressArray, null); recipientEntries = processContactEntries(c, null /* directoryId */); callback.matchesFound(recipientEntries); } finally { if (c != null) { c.close(); } } // final Set<String> matchesNotFound = new HashSet<String>(); getMatchingRecipientsFromDirectoryQueries( context, recipientEntries, addresses, account, matchesNotFound, query, callback); getMatchingRecipientsFromExtensionMatcher(adapter, matchesNotFound, callback); }
/** * Get a HashMap of address to RecipientEntry that contains all contact information for a contact * with the provided address, if one exists. This may block the UI, so run it in an async task. * * @param context Context. * @param inAddresses Array of addresses on which to perform the lookup. * @return HashMap<String,RecipientEntry> */ public static HashMap<String, RecipientEntry> getMatchingRecipients( Context context, ArrayList<String> inAddresses, int addressType) { Queries.Query query; if (addressType == QUERY_TYPE_EMAIL) { query = Queries.EMAIL; } else { query = Queries.PHONE; } int addressesSize = Math.min(MAX_LOOKUPS, inAddresses.size()); String[] addresses = new String[addressesSize]; StringBuilder bindString = new StringBuilder(); // Create the "?" string and set up arguments. for (int i = 0; i < addressesSize; i++) { Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses.get(i).toLowerCase()); addresses[i] = (tokens.length > 0 ? tokens[0].getAddress() : inAddresses.get(i)); bindString.append("?"); if (i < addressesSize - 1) { bindString.append(","); } } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Doing reverse lookup for " + addresses.toString()); } HashMap<String, RecipientEntry> recipientEntries = new HashMap<String, RecipientEntry>(); Cursor c = context .getContentResolver() .query( query.getContentUri(), query.getProjection(), query.getProjection()[Queries.Query.DESTINATION] + " IN (" + bindString.toString() + ")", addresses, null); if (c != null) { try { if (c.moveToFirst()) { do { String address = c.getString(Queries.Query.DESTINATION); recipientEntries.put( address, RecipientEntry.constructTopLevelEntry( c.getString(Queries.Query.NAME), c.getInt(Queries.Query.DISPLAY_NAME_SOURCE), c.getString(Queries.Query.DESTINATION), c.getInt(Queries.Query.DESTINATION_TYPE), c.getString(Queries.Query.DESTINATION_LABEL), c.getLong(Queries.Query.CONTACT_ID), c.getLong(Queries.Query.DATA_ID), c.getString(Queries.Query.PHOTO_THUMBNAIL_URI))); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d( TAG, "Received reverse look up information for " + address + " RESULTS: " + " NAME : " + c.getString(Queries.Query.NAME) + " CONTACT ID : " + c.getLong(Queries.Query.CONTACT_ID) + " ADDRESS :" + c.getString(Queries.Query.DESTINATION)); } } while (c.moveToNext()); } } finally { c.close(); } } return recipientEntries; }
/** * Get a HashMap of address to RecipientEntry that contains all contact information for a contact * with the provided address, if one exists. This may block the UI, so run it in an async task. * * @param context Context. * @param inAddresses Array of addresses on which to perform the lookup. * @param callback RecipientMatchCallback called when a match or matches are found. * @return HashMap<String,RecipientEntry> */ public static void getMatchingRecipients( Context context, ArrayList<String> inAddresses, int addressType, Account account, RecipientMatchCallback callback) { Queries.Query query; if (addressType == QUERY_TYPE_EMAIL) { query = Queries.EMAIL; } else { query = Queries.PHONE; } int addressesSize = Math.min(MAX_LOOKUPS, inAddresses.size()); HashSet<String> addresses = new HashSet<String>(); StringBuilder bindString = new StringBuilder(); // Create the "?" string and set up arguments. for (int i = 0; i < addressesSize; i++) { Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses.get(i).toLowerCase()); addresses.add(tokens.length > 0 ? tokens[0].getAddress() : inAddresses.get(i)); bindString.append("?"); if (i < addressesSize - 1) { bindString.append(","); } } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Doing reverse lookup for " + addresses.toString()); } String[] addressArray = new String[addresses.size()]; addresses.toArray(addressArray); HashMap<String, RecipientEntry> recipientEntries = null; Cursor c = null; try { c = context .getContentResolver() .query( query.getContentUri(), query.getProjection(), query.getProjection()[Queries.Query.DESTINATION] + " IN (" + bindString.toString() + ")", addressArray, null); recipientEntries = processContactEntries(c); callback.matchesFound(recipientEntries); } finally { if (c != null) { c.close(); } } // See if any entries did not resolve; if so, we need to check other // directories final Set<String> matchesNotFound = new HashSet<String>(); if (recipientEntries.size() < addresses.size()) { final List<DirectorySearchParams> paramsList; Cursor directoryCursor = null; try { directoryCursor = context .getContentResolver() .query(DirectoryListQuery.URI, DirectoryListQuery.PROJECTION, null, null, null); paramsList = BaseRecipientAdapter.setupOtherDirectories(context, directoryCursor, account); } finally { if (directoryCursor != null) { directoryCursor.close(); } } // Run a directory query for each unmatched recipient. HashSet<String> unresolvedAddresses = new HashSet<String>(); for (String address : addresses) { if (!recipientEntries.containsKey(address)) { unresolvedAddresses.add(address); } } matchesNotFound.addAll(unresolvedAddresses); Cursor directoryContactsCursor = null; for (String unresolvedAddress : unresolvedAddresses) { for (int i = 0; i < paramsList.size(); i++) { try { directoryContactsCursor = doQuery( unresolvedAddress, 1, paramsList.get(i).directoryId, account, context.getContentResolver(), query); } finally { if (directoryContactsCursor != null && directoryContactsCursor.getCount() == 0) { directoryContactsCursor.close(); directoryContactsCursor = null; } else { break; } } } if (directoryContactsCursor != null) { try { final Map<String, RecipientEntry> entries = processContactEntries(directoryContactsCursor); for (final String address : entries.keySet()) { matchesNotFound.remove(address); } callback.matchesFound(entries); } finally { directoryContactsCursor.close(); } } } } callback.matchesNotFound(matchesNotFound); }