Android: Retrieve contact name from phone number
Asked Answered
E

6

54

I would like to retrieve the name of a contact associated with an incoming telephone number. As I process the incoming number in the broascastreceiver having a String with the name of the incoming caller would help my project greatly.

I would think this involves a query using the sql WHERE clause as a filter, but do I need to sort the contacts? An example or hint would be of great assistance.

Etana answered 20/6, 2010 at 13:23 Comment(1)
For the facility of others, I have written a post which contains the whole code to query name, photo, contact ID, etc. with decent explanation. The code contains snippets as found on different answers, but more organized and tested. Link: hellafun.weebly.com/home/…Murmansk
D
83

For that you need to use the optimized PhoneLookup provider as described.

Add the permission to AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_CONTACTS"/>

Then:

public String getContactName(final String phoneNumber, Context context)
{
    Uri uri=Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,Uri.encode(phoneNumber));

    String[] projection = new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME};

    String contactName="";
    Cursor cursor=context.getContentResolver().query(uri,projection,null,null,null);

    if (cursor != null) {
        if(cursor.moveToFirst()) {
            contactName=cursor.getString(0);
        }
        cursor.close();
    }

    return contactName;
}
Demography answered 20/6, 2010 at 13:47 Comment(8)
Right off the dev page, thank you for the quick response. The toString() method in Uri should convert this query to the contacts name?Etana
No, it won't you will have to resolve the Cursor yourself. For some help check this questions: #903843Demography
I would initialize a cursor with a managedQuery using the URI, then move the cursor to the fist position and get the data? Once I get the cursor at the first position I use getString? I assume that the first position would be right because the query is for a number therefore the query will pull up names only for that number?Etana
That's exactly how you have to do. Don't forget to wrap in a try/catch.Demography
What specifically goes into the rest of that query? This answer isn't much more helpful than the already existing documentation.Commandant
You should answer with full code. After query how to iterate and get name. Beginner can not understand this 2 lines. You should make function that returns name based on numberProvince
Hello, I tried something similar, but it didn't work. Here is my question, I would really appreciate your help! :) https://mcmap.net/q/182714/-get-contact-name/…Shaff
This throws java.lang.IllegalArgumentException: Invalid column display_name. @Vikram.exe's answer is better.Gladiate
B
90

Although this has already been answered, but here is the complete function to get the contact name from number. Hope it will help others:

public static String getContactName(Context context, String phoneNumber) {
    ContentResolver cr = context.getContentResolver();
    Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
    Cursor cursor = cr.query(uri, new String[]{PhoneLookup.DISPLAY_NAME}, null, null, null);
    if (cursor == null) {
        return null;
    }
    String contactName = null;
    if(cursor.moveToFirst()) {
        contactName = cursor.getString(cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME));
    }

    if(cursor != null && !cursor.isClosed()) {
        cursor.close();
    }

    return contactName;
}

[Updating based on Marcus's comment]

You will have to ask for this permission:

<uses-permission android:name="android.permission.READ_CONTACTS"/>

Banks answered 5/8, 2013 at 18:12 Comment(5)
it makes the app "not responsible" when resuming the activity. How should I do thatMisdemeanant
I'm also getting ANR every time I run on Android 5.1Eggcup
Probably for the ANR you need to run it on a thread other than the UI thread.Frenchify
Worth to mention is that this needs the <uses-permission android:name="android.permission.READ_CONTACTS"/> permissionRousing
Hello, I tried something similar, but it didn't work. Here is my question, I would really appreciate your help! :) https://mcmap.net/q/182714/-get-contact-name/…Shaff
D
83

For that you need to use the optimized PhoneLookup provider as described.

Add the permission to AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_CONTACTS"/>

Then:

public String getContactName(final String phoneNumber, Context context)
{
    Uri uri=Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,Uri.encode(phoneNumber));

    String[] projection = new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME};

    String contactName="";
    Cursor cursor=context.getContentResolver().query(uri,projection,null,null,null);

    if (cursor != null) {
        if(cursor.moveToFirst()) {
            contactName=cursor.getString(0);
        }
        cursor.close();
    }

    return contactName;
}
Demography answered 20/6, 2010 at 13:47 Comment(8)
Right off the dev page, thank you for the quick response. The toString() method in Uri should convert this query to the contacts name?Etana
No, it won't you will have to resolve the Cursor yourself. For some help check this questions: #903843Demography
I would initialize a cursor with a managedQuery using the URI, then move the cursor to the fist position and get the data? Once I get the cursor at the first position I use getString? I assume that the first position would be right because the query is for a number therefore the query will pull up names only for that number?Etana
That's exactly how you have to do. Don't forget to wrap in a try/catch.Demography
What specifically goes into the rest of that query? This answer isn't much more helpful than the already existing documentation.Commandant
You should answer with full code. After query how to iterate and get name. Beginner can not understand this 2 lines. You should make function that returns name based on numberProvince
Hello, I tried something similar, but it didn't work. Here is my question, I would really appreciate your help! :) https://mcmap.net/q/182714/-get-contact-name/…Shaff
This throws java.lang.IllegalArgumentException: Invalid column display_name. @Vikram.exe's answer is better.Gladiate
T
26

This was very helpful, here's my final code for retrieving the caller's Name, id, and Photo:

private void uploadContactPhoto(Context context, String number) {

Log.v("ffnet", "Started uploadcontactphoto...");

String name = null;
String contactId = null;
InputStream input = null;

// define the columns I want the query to return
String[] projection = new String[] {
        ContactsContract.PhoneLookup.DISPLAY_NAME,
        ContactsContract.PhoneLookup._ID};

// encode the phone number and build the filter URI
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));

// query time
Cursor cursor = context.getContentResolver().query(contactUri, projection, null, null, null);

if (cursor.moveToFirst()) {

    // Get values from contacts database:
    contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup._ID));
    name =      cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));

    // Get photo of contactId as input stream:
    Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(contactId));
    input = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);

    Log.v("ffnet", "Started uploadcontactphoto: Contact Found @ " + number);            
    Log.v("ffnet", "Started uploadcontactphoto: Contact name  = " + name);
    Log.v("ffnet", "Started uploadcontactphoto: Contact id    = " + contactId);

} else {

    Log.v("ffnet", "Started uploadcontactphoto: Contact Not Found @ " + number);
    return; // contact not found

}

// Only continue if we found a valid contact photo:
if (input == null) {
    Log.v("ffnet", "Started uploadcontactphoto: No photo found, id = " + contactId + " name = " + name);
    return; // no photo
} else {
    this.type = contactId;
    Log.v("ffnet", "Started uploadcontactphoto: Photo found, id = " + contactId + " name = " + name);
}

... then just do whatever you want with "input" (their photo as an InputStream), "name", and "contactId".

And here are the docs listing the ~15 or so columns you have access to, just add them to the projection near the start of the code up above: http://developer.android.com/reference/android/provider/ContactsContract.PhoneLookup.html

Triangulate answered 1/1, 2012 at 21:24 Comment(0)
F
2

This version is the same as Vikram.exe's answer with code to avoid the ANR

interface GetContactNameListener {
    void contactName(String name);
}

public void getContactName(final String phoneNumber,final GetContactNameListener listener) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            ContentResolver cr = getContentResolver();
            Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
            Cursor cursor = cr.query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);
            if (cursor == null) {
                return;
            }
            String contactName = null;
            if(cursor.moveToFirst()) {
                contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
            }

            if(cursor != null && !cursor.isClosed()) {
                cursor.close();
            }

            listener.contactName(contactName);
        }
    }).start();

}
Frenchify answered 5/10, 2015 at 20:27 Comment(0)
H
1

Pass the contact number from which you are getting the call in the following method. This Method will check whether the contact is saved in your mobile or not. If the contact is saved then it will return the contact name otherwise it return a string unknown number

Add this code in your Broadcast receiver class

    public String getContactDisplayNameByNumber(String number,Context context) {
    Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
    name = "Incoming call from";

    ContentResolver contentResolver = context.getContentResolver();
    Cursor contactLookup = contentResolver.query(uri, null, null, null, null);

    try {
        if (contactLookup != null && contactLookup.getCount() > 0) {
            contactLookup.moveToNext();
            name = contactLookup.getString(contactLookup.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
            // this.id =
            // contactLookup.getString(contactLookup.getColumnIndex(ContactsContract.Data.CONTACT_ID));
            // String contactId =
            // contactLookup.getString(contactLookup.getColumnIndex(BaseColumns._ID));
        }else{
            name = "Unknown number";
        }
    } finally {
        if (contactLookup != null) {
            contactLookup.close();
        }
    }

    return name;
}

to get Source code visit this link

Hobard answered 18/12, 2016 at 14:12 Comment(0)
A
0

For that, we can use the PhoneLookup provider to get the names or contact details using the mobile number.

Add the permission to AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_CONTACTS"/>

Add the following custom kotlin method in your activity and call the same with the required mobile number.

fun getContactNameByPhoneNumber(context: Context, phoneNumber: String): String? {
        var phone = phoneNumber
        if(phoneNumber != null && phoneNumber.length > 0 && phoneNumber[0].equals('+'))
            phone = phoneNumber.substring(3)

        val projection = arrayOf(
            ContactsContract.PhoneLookup.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Phone.NUMBER
        )
        val cursor = context.contentResolver.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            projection,
            ContactsContract.CommonDataKinds.Phone.NUMBER, null, null
        ) ?: return ""
        for (i in 0 until cursor.count) {
            cursor.moveToPosition(i)
            val nameFieldColumnIndex = cursor
                .getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME)
            val phoneFieldColumnIndex = cursor
                .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)

            if(phone.equals(cursor.getString(phoneFieldColumnIndex)))
                return cursor.getString(nameFieldColumnIndex)
        }
        return "Unknown"
    }

For more: https://developer.android.com/training/contacts-provider/retrieve-names

Amadus answered 11/2, 2022 at 6:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.