How to search Contacts with address (FORMATTED_ADDRESS) with one query?
Asked Answered
C

1

7

I try to implement a live search over the users contacts, and I want to get the name, thumbnail and address (if there is one) of each matching contact.

The live search is running while the user is typing.

So he types ma and will get 'martin', 'matthews'...

He'll continue with mat and will only see 'matthews'

I try to achieve this with a single query like the following, but I always get the contact number in the FORMATTED_ADRESS field. I guess I have a JOIN problem, because I'm using ContactsContract.CommonDataKinds and ContactsContract.Contacts in the same query?

public static List<ContactModel> getContactsForQuery(Context context, String query) {

    String[] projection = new String[] {
        ContactsContract.Contacts.DISPLAY_NAME,
        Contacts.PHOTO_THUMBNAIL_URI,
        ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS
    };

    Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String selection = ContactsContract.Contacts.DISPLAY_NAME + " LIKE '%" + query +  "%'";
    Cursor cursor = context.getContentResolver().query(uri, projection, selection, null,null);
    if (cursor.moveToFirst()) {

        do {
            String name = cursor.getString(0);
            String thumbail = cursor.getString(1);
            String formattedADress = cursor.getString(2);
        }
        while (cursor.moveToNext());
    }

I actually solved my issue, with

  1. querying for Contacts._ID, Contacts.DISPLAY_NAME
  2. start a second query with the Contacts._ID like the following

    Cursor detailCursor = context.getContentResolver().query(
           ContactsContract.Data.CONTENT_URI,
           new String[]{
               CommonDataKinds.StructuredPostal.STREET,
               CommonDataKinds.StructuredPostal.CITY,
               CommonDataKinds.StructuredPostal.POSTCODE
           },
           ContactsContract.Data.CONTACT_ID + "=? AND " 
               + CommonDataKinds.StructuredPostal.MIMETYPE + "=?",
           new String[]{
               String.valueOf(contactID),
               CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE
           },
           null);
    

but this will start a second query for every contact, which might not be the best approach.

So my final question is: is it possible to get this work with the first query?

Cruiserweight answered 11/8, 2016 at 9:31 Comment(1)
why downvote? did i miss something?Cruiserweight
C
0

Mmmh, very sad, that no one was able to answer my question and grab the bounty points ;-(

For the record, here's my working example. It solves the issue but I still think it's producing a big overload. On every user entry (afterTextchange) I call the getContactsDetailsQuery which first gets all users with their ID containing the query in their name (cursor) and afterwards I start another query (detailCursor) for every user to get the adress. To prevent the overload, i added an limit..

public static List<SearchModel> getContactDetailsForQuery(Context context, String query, int limit) {

    final int CONTACT_ID_INDEX = 0;
    final int CONTACT_NAME_INDEX = 1;
    final int CONTACT_THUMBNAIL_INDEX = 2;

    //my custom model to hold my results
    List<SearchModel> results = new ArrayList<SearchModel>();

    final String[] selectUser = new String[]{
        Contacts._ID,
        Contacts.DISPLAY_NAME,
        Contacts.PHOTO_THUMBNAIL_URI};
    String selection = Contacts.DISPLAY_NAME + " LIKE ?";
    String[] selectionArgs = new String[]{"%" + query + "%"};
    String sortOrder = Contacts.DISPLAY_NAME + " ASC";

    Cursor cursor = context.getContentResolver().query(Contacts.CONTENT_URI, selectUser, selection, selectionArgs, sortOrder, null);

    int contactCounter = 0;
    if (cursor != null && cursor.moveToFirst()) {

        do {
            String contactID = cursor.getString(CONTACT_ID_INDEX);
            String displayName = cursor.getString(CONTACT_NAME_INDEX);
            String thumbnail = cursor.getString(CONTACT_THUMBNAIL_INDEX);

            //get user details with user id (this is the query i wanted to change in my question!!)
            Cursor detailCursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
                new String[]{
                    CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS},
                ContactsContract.Data.CONTACT_ID + "=? AND " +
                    CommonDataKinds.StructuredPostal.MIMETYPE + "=?",
                new String[]{String.valueOf(contactID), CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE},
                null);

            if (detailCursor != null && detailCursor.moveToFirst()) {
                //special case: user has several address, query all of them
                do {
                    String formattedAddress = detailCursor.getString(detailCursor.getColumnIndex(CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS));
                    //user has serveral adress -> init model for each adress
                    SearchModel contact = new SearchModel();
                    results.add(contact);
                    contactCounter++;

                } while (detailCursor.moveToNext() && contactCounter < limit);

            } else {

                //user has no adress -> init model
                SearchModel contact = new SearchModel();
                results.add(contact);
                contactCounter++;
            }

            detailCursor.close();

        } while (cursor.moveToNext() && contactCounter < limit);
    }
    cursor.close();

    return results;
}
Cruiserweight answered 31/8, 2016 at 10:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.