24

How to get the following fields from Android contacts? I used Android 2.2.

  1. Name prefix
  2. First name
  3. Middle name
  4. Last name
  5. Name prefix
  6. Phonetic given name
  7. Phonetic middle name
  8. Phonetic family name
Peter O.
  • 32,158
  • 14
  • 82
  • 96
bharath
  • 14,283
  • 16
  • 57
  • 95
  • Hello, I tried this, but it didn't work. Here is my question, I would really appreciate your help! :) http://stackoverflow.com/questions/35097844/get-contact-name/35098111#35098111 – Ruchir Baronia Jan 30 '16 at 05:03

9 Answers9

59

Look at ContactsContract.CommonDataKinds.StructuredName class. You can find there all columns you are looking for. Try sth like this:

    String whereName = ContactsContract.Data.MIMETYPE + " = ?";
    String[] whereNameParams = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE };
    Cursor nameCur = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
    while (nameCur.moveToNext()) {
        String given = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
        String family = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
        String display = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
    }
    nameCur.close();

It returns all names in contacts. To be more precise you can add a contact id as an additional parameter to the query - you will get address for particular contact.

Krzysztof Wolny
  • 10,576
  • 4
  • 34
  • 46
  • 5
    One note: above query returns ALL (I mean really all) contacts in your phone (even emails without excplicity given names). So you should filter them to get contacts you want – Krzysztof Wolny Jan 09 '11 at 10:24
  • 4
    And one note from my side: the MIMETYPE is really required, otherwise you end up getting not what you expect. I overlooked this detail and it took me an hour to debug it. – Boris Strandjev Dec 27 '11 at 15:32
  • 2
    how about getting the phone owner's first name and last name? is it doable? – silent_coder14 Oct 26 '12 at 10:18
  • @KrzysztofWolny how should I filter the results then? I'm able to retrieve the data, but I see duplicates for those contacts from multiple resources (Google contacts esp.) – xialin Aug 19 '14 at 17:50
  • some app like viber & telegram change first name – Hamidreza Sadegh Dec 06 '14 at 13:31
  • @KrzysztofWolny I did the same as given in this answer but contact names are not getting properly sorted alphabetically. Some contacts appear in between disturbing the alphabetical order. Any idea why this is happening ? I will be thankful if you can give any inputs. – akshay7692 May 24 '15 at 12:54
  • @akshay7692 I'd debug it and check what are the values of `ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME` for every entry and what data you display. You can try sorting basing on other fields. – Krzysztof Wolny May 25 '15 at 14:34
  • filter using `IN_VISIBLE_GROUP` = 1 to get only the contacts that show in the addressbook – Harry Moreno Dec 27 '15 at 05:27
  • What is the difference between the three? Thanks so much Krzystztof! – Ruchir Baronia Jan 30 '16 at 03:54
  • Say, "last name" is FAMILY_NAME and "first name" is GIVEN_NAME, right? – android developer Feb 25 '21 at 08:32
  • @HarryMoreno I still see duplicates when using what you wrote. How come? Should I ignore those? – android developer Feb 25 '21 at 14:54
  • @androiddeveloper sure. I'm no expert. – Harry Moreno Feb 25 '21 at 16:40
  • @HarryMoreno I think it's because of multiple account-types of various apps. Do you know perhaps how to get which app holds which account-type? Maybe I should prioritize by those that are built in, or something. An example of a list of account-types that are built in: https://stackoverflow.com/a/44802016/878126 – android developer Feb 28 '21 at 07:50
  • @HarryMoreno Anyway I decided to make a prioritized solution and offer it here: https://stackoverflow.com/a/66407600/878126 – android developer Feb 28 '21 at 09:30
18

For a specified contact you can do this :

String whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?";
String[] whereNameParams = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, contact_ID };
Cursor nameCur = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
while (nameCur.moveToNext()) {
    String given = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
    String family = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
    String display = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
}
nameCur.close();
jc_35
  • 1,073
  • 1
  • 9
  • 15
8

As the other example (just for fun) but for fetching contact name of a single user:

// A contact ID is fetched from ContactList
Uri resultUri = data.getData(); 
Cursor cont = getContentResolver().query(resultUri, null, null, null, null);
if (!cont.moveToNext()) {   
    Toast.makeText(this, "Cursor contains no data", Toast.LENGTH_LONG).show(); 
                return;
}
int columnIndexForId = cont.getColumnIndex(ContactsContract.Contacts._ID);
String contactId = cont.getString(columnIndexForId);

// Fetch contact name with a specific ID
String whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = " + contactId; 
String[] whereNameParams = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE };
Cursor nameCur = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
while (nameCur.moveToNext()) {
    String given = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
    String family = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
    String display = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
    Toast.makeText(this, "Name: " + given + " Family: " +  family + " Displayname: "  + display, Toast.LENGTH_LONG).show();
}
nameCur.close();
cont.close();
perborin
  • 234
  • 2
  • 10
7

try to use this code to get the required information about the contact,the code is here-

import android.provider.ContactsContract.Contacts;
import android.database.Cursor;

// Form an array specifying which columns to return, you can add more.
String[] projection = new String[] {
                         ContactsContract.Contacts.DISPLAY_NAME,
                         ContactsContract.CommonDataKinds.Phone
                         ContactsContract.CommonDataKinds.Email
                      };

Uri contacts =  ContactsContract.Contacts.CONTENT_LOOKUP_URI;
// id of the Contact to return.
long id = 3;

// Make the query. 
Cursor managedCursor = managedQuery(contacts,
                     projection, // Which columns to return 
                     null,       // Which rows to return (all rows)
                                 // Selection arguments (with a given ID)
                     ContactsContract.Contacts._ID = "id", 
                                 // Put the results in ascending order by name
                     ContactsContract.Contacts.DISPLAY_NAME + " ASC");
Ravi
  • 2,277
  • 3
  • 22
  • 37
  • This use of the `projection` array to get needed columns only is the cleanest way. And DISPLAY_NAME is also simpler than the `StructuredName` URI if you don't need separated first and last names. So, I like this one. – John Sep 23 '15 at 16:56
  • `DISPLAY_NAME` will be the phone-number when the contact has no name-information. – RhodanV5500 Apr 10 '19 at 06:02
3

Some links to get you started, in addition to the suggestions from Raunak:

Community
  • 1
  • 1
mchang
  • 681
  • 4
  • 4
1

Experimenting with the ContactsContract.Data.CONTENT_URI in late 2015 on marshmallow. I'm unable to get the GIVEN_NAME or similar fields. I think the later apis have deprecated these. Run the following code to print out the columns you have on your phone

Uri uri = ContactsContract.Data.CONTENT_URI;
String selection = ContactsContract.Data.MIMETYPE + " = ?";
String[] selectionArgs = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE};
Cursor cursor = contentResolver.query(
            uri,       // URI representing the table/resource to be queried
            null,      // projection - the list of columns to return.  Null means "all"
            selection, // selection - Which rows to return (condition rows must match)
            selectionArgs,      // selection args - can be provided separately and subbed into selection.
            null);   // string specifying sort order

if (cursor.getCount() == 0) {
  return;
}
Log.i("Count:", Integer.toString(cursor.getCount())); // returns number of names on phone

while (cursor.moveToNext()) {
  // Behold, the firehose!
  Log.d(TAG, "-------------------new record\n");
  for(String column : cursor.getColumnNames()) {
    Log.d(TAG, column + ": " + cursor.getString(cursor.getColumnIndex(column)) + "\n");
  }
}
Harry Moreno
  • 10,231
  • 7
  • 64
  • 116
  • Hello, I tried this, but it didn't work. Here is my question, I would really appreciate your help! :) http://stackoverflow.com/questions/35097844/get-contact-name/35098111#35098111 – Ruchir Baronia Jan 30 '16 at 05:03
0

try this,

public void onActivityResult(int reqCode, int resultCode, Intent data) { super.onActivityResult(reqCode, resultCode, data);

    try {
        if (resultCode == Activity.RESULT_OK) {
            Uri contactData = data.getData();
            Cursor cur = managedQuery(contactData, null, null, null, null);
            ContentResolver contect_resolver = getContentResolver();

            if (cur.moveToFirst()) {
                String id = cur.getString(cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
                String name = "";
                String no = "";

                Cursor phoneCur = contect_resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);

                if (phoneCur.moveToFirst()) {
                    name = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    no = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                }

                Log.e("Phone no & name :***: ", name + " : " + no);
                txt.append(name + " : " + no + "\n");

                id = null;
                name = null;
                no = null;
                phoneCur = null;
            }
            contect_resolver = null;
            cur = null;
            //                      populateContacts();
        }
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
        Log.e("IllegalArgumentException::", e.toString());
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("Error :: ", e.toString());
    }
}
Abhishek
  • 682
  • 6
  • 17
0

Combining various solutions here, and seeing there are duplicate records from the results (due to multiple accounts), I've decided to make a function that will prioritize common account-types over others. On this sample, I also ignore the records of completely empty/null names (if all are as such), but you can change this if you wish:

@RequiresPermission(
    allOf = [Manifest.permission.READ_CONTACTS])
@WorkerThread
fun getContactIdToContactNameMap(context: Context): LongSparseArray<ContactObject> {
    val contactIdToContactObjectMap = LongSparseArray<ContactObject>()
    val contentResolver = context.contentResolver
    contentResolver.query(ContactsContract.Data.CONTENT_URI,
        arrayOf(
            ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID,
            ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
            ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
            ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME,
            ContactsContract.RawContacts.ACCOUNT_TYPE),
        ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.Data.IN_VISIBLE_GROUP + " = ?",
        arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, "1"),
        null)?.use { cursor ->
        //            Log.d("AppLog", "got ${cursor.count} records for names")
        val colContactId = cursor.getColumnIndex(
            ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID)
        val colFirstName = cursor.getColumnIndex(
            ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)
        val colFamilyName = cursor.getColumnIndex(
            ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)
        val colMiddleName = cursor.getColumnIndex(
            ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME)
        val colAccountType =
            cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE)
        val googleAccount = "com.google"
        //https://stackoverflow.com/a/44802016/878126
        val prioritizedAccountTypes =
            hashSetOf("vnd.sec.contact.phone", "com.htc.android.pcsc",
                "com.sonyericsson.localcontacts", "com.lge.sync", "com.lge.phone",
                "vnd.tmobileus.contact.phone", "com.android.huawei.phone",
                "Local Phone Account",
                "")
        val contactIdToAccountTypeMap = LongSparseArray<String>()
        while (cursor.moveToNext()) {
            val contactId = cursor.getLong(colContactId)
            val accountType = cursor.getString(colAccountType).orEmpty()
            val existingContact = contactIdToContactObjectMap.get(contactId)
            if (existingContact != null) {
                //this can occur, as we go over all of the items, including duplicate ones made by various sources
                //                        https://stackoverflow.com/a/4599474/878126
                val previousAccountType = contactIdToAccountTypeMap.get(contactId)
                //google account is most prioritized, so we skip current one if previous was of it
                if (previousAccountType == googleAccount)
                    continue
                if (accountType != googleAccount && previousAccountType != null && prioritizedAccountTypes.contains(
                        previousAccountType))
                //we got now a name of an account that isn't prioritized, but we already had a prioritized one, so ignore
                    continue
            }
            contactIdToAccountTypeMap.put(contactId, accountType)
            val firstName = cursor.getString(colFirstName)?.trim()
            val lastName = cursor.getString(colFamilyName)?.trim()
            val middleName = cursor.getString(colMiddleName)?.trim()
            if (firstName.isNullOrBlank() && lastName.isNullOrBlank() && middleName.isNullOrBlank())
                continue
            val contactObject = existingContact ?: ContactObject()
            contactObject.firstName = firstName
            contactObject.lastName = lastName
            contactObject.middleName = middleName
            contactIdToContactObjectMap.put(contactId, contactObject)
        }
    }
    return contactIdToContactObjectMap
}

class ContactObject {
    var firstName: String? = null
    var middleName: String? = null
    var lastName: String? = null
}

Usage:

thread {
    if (ActivityCompat.checkSelfPermission(this,
            Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
        val contactIdToContactNameMap = getContactIdToContactNameMap(this)
        Log.d("AppLog", "found ${contactIdToContactNameMap.size()} names for contacts")
    } else Log.d("AppLog", "no contacts permission...")
}
android developer
  • 114,585
  • 152
  • 739
  • 1,270
-2

Check here there is example code exactly for that: http://developer.android.com/guide/topics/ui/layout/listview.html