22

I need to get all phone contacts and their email address and photo uri:

This is what am doing:

private void getContacts() {

        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(Contacts.CONTENT_URI, null, null, null, Contacts.DISPLAY_NAME);

        if (cur.getCount() > 0) {
            while (cur.moveToNext()) {

                // if
                // (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)))
                // > 0) {

                Contact contact = new Contact();

                String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));

                Uri uri = getContactPhotoUri(Long.parseLong(id));
                // set photoUri
                contact.setContactPhotoUri(uri);

                // set name
                contact.setContactName(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));

                // get the phone number
                Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);
                while (pCur.moveToNext()) {

                    // set phone munber
                    contact.setContactNumber(pCur.getString(pCur
                            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
                    contacts.add(contact);

                }
                pCur.close();

                // get email and type
                Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[] { id }, null);
                while (emailCur.moveToNext()) {
                    // This would allow you get several email addresses
                    // if the email addresses were stored in an array

                    // set email
                    contact.setContactEmail(emailCur.getString(emailCur
                            .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)));

                    contacts.add(contact);

                }
                emailCur.close();

            }
        }

        cur.close();
        contactAdapter = new ContactAdapter(this, R.id.contactList, contacts);

        // }

    }

    public Uri getContactPhotoUri(long contactId) {
        Uri photoUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
        photoUri = Uri.withAppendedPath(photoUri, Contacts.Photo.CONTENT_DIRECTORY);
        return photoUri;
    }

My problem am getting all contacts including gmail contacts, i dont want gmail contacts to be included. And the time taken is also very slow. How do i optimize this, I know its taking time coz i am using many cursors.. but dont know how to make a single cusror that can give me name email number photo uri ...Thanks!

UPDATED FINAL:

private void getContacts() {

    ContentResolver cr = getContentResolver();

    Cursor cur = cr.query(Data.CONTENT_URI, new String[] { Data.CONTACT_ID, Data.MIMETYPE, Email.ADDRESS,
            Contacts.DISPLAY_NAME, Phone.NUMBER }, null, null, Contacts.DISPLAY_NAME);

    Contact contact;

    if (cur.getCount() > 0) {

        while (cur.moveToNext()) {

            String id = cur.getString(cur.getColumnIndex(Data.CONTACT_ID));

            String mimeType = cur.getString(cur.getColumnIndex(Data.MIMETYPE));

            if (allContacts.containsKey(id)) {
                // update contact
                contact = allContacts.get(id);
            } else {
                contact = new Contact();
                allContacts.put(id, contact);
                // set photoUri
                contact.setContactPhotoUri(getContactPhotoUri(Long.parseLong(id)));
            }

            if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE))
                // set name
                contact.setContactName(cur.getString(cur.getColumnIndex(Contacts.DISPLAY_NAME)));

            if (mimeType.equals(Phone.CONTENT_ITEM_TYPE))
                // set phone munber
                contact.setContactNumber(cur.getString(cur.getColumnIndex(Phone.NUMBER)));

            if (mimeType.equals(Email.CONTENT_ITEM_TYPE))
                // set email
                contact.setContactEmail(cur.getString(cur.getColumnIndex(Email.ADDRESS)));

        }
    }

    cur.close();
    // get contacts from hashmap
    contacts.clear();
    contacts.addAll(allContacts.values());

    // remove null contacts
    for (Contact _contact : contacts) {

        if (_contact.getContactName() == null && _contact.getContactNumber() == null
                && _contact.getContactEmail() == null) {
            contacts.remove(_contact);
            break;
        }

    }

    contactAdapter = new ContactAdapter(this, R.id.contactList, contacts);
    contactAdapter.notifyDataSetChanged();

}

public Uri getContactPhotoUri(long contactId) {
    Uri photoUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    photoUri = Uri.withAppendedPath(photoUri, Contacts.Photo.CONTENT_DIRECTORY);
    return photoUri;
}
sukarno
  • 597
  • 2
  • 10
  • 31

1 Answers1

23

You should be able to get all the information needed in one query on Data.CONTENT_URI, Check out "android.provider.ContactsContract.Data" table and the examples on how to query different types of data Email,Phone,Photo etc... http://developer.android.com/reference/android/provider/ContactsContract.Data.html

For example:

Cursor data = cntx.getContentResolver().query(Data.CONTENT_URI, new String[] {Data._ID,Data.MIMETYPE,Email.ADDRESS,Photo.PHOTO},Data.CONTACT_ID + "=?" + " AND " + "(" +  Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "' OR " + Data.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE +"')",
                        new String[] {String.valueOf(contactId)}, null);

Should bring you all the information you need regarding one specific contactId, you could theoretically ask for all contacts and sort the information yourself.

As for filtering gmail contacts this is a more complex issue, take a look at ACCOUNT_NAME / TYPE http://developer.android.com/reference/android/provider/ContactsContract.RawContacts.html parameter and a discussion regarding this issue here: What is the default Account Type / Name for contacts on Android Contact Application?

Community
  • 1
  • 1
Raanan
  • 4,777
  • 27
  • 47
  • forget about filtering by gmail account.. need to get all contacts email number display name and photo uri in one custom query.. so as to improve performance – sukarno Apr 01 '13 at 12:06
  • In the first link I provided you can see that the Data table is also merged with ContactContarct.Contacts -> so you can ask for the Contacts.DISPLAY_NAME. Take in consideration the the Data table contains many records so you need to make sure you are looking at the "right" one. – Raanan Apr 01 '13 at 12:16
  • Hi i tried it worked,, but have an issue here all contacts being repeated: check is my updated code – sukarno Apr 01 '13 at 13:51
  • eample i have a contact named: Jaffa it has a phone number and a mail id.. where now am getting three contacts for each item(name,number, email)... what might be the problem – sukarno Apr 01 '13 at 13:53
  • That's how Data table is built, you have multiple records for each contact, one record might contain the email and the other the photo and another the phone number, you have to write a logic to merge the information you receive by contactId , mime type and take in consideration other params like primary for example. i.e. Use a HashMap of ContactID -> Contact adding the information as you find it. – Raanan Apr 01 '13 at 14:17
  • Ok thanks for that.. can u please tell me how to merge them to a single contact, so that i will close this thread, am little confused. – sukarno Apr 01 '13 at 14:24
  • Well you are doing everything alright so far, add Data.CONTACT_ID & Data.MIMETYPE to the query results fields, change your "contacts" from a list to a HashMap when you get a cursor record first check if the Contact is already in the Contacts hashmap (if not create a new one) then depending on the record mimetype update the correct field in Contact (photo/email/phone). – Raanan Apr 01 '13 at 14:30
  • I tried above updated code but not getting correct result... how to check for mimetypes?? – sukarno Apr 01 '13 at 15:14
  • Sorry i forgot to add Data.CONTACT_ID to projection now am getting correct results but only thing is now am missing all gmail contacts and the list is not ordered by contact name. Thanks – sukarno Apr 01 '13 at 15:27
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27333/discussion-between-raanan-and-sukarno) – Raanan Apr 01 '13 at 15:35