Android:从电话号码中检索联系人姓名

54
我希望能够通过一个传入的电话号码来检索与其关联的联系人的姓名。在广播接收器中处理传入的电话号码时,如果有一个包含来电者姓名的字符串,将极大地帮助我的项目。
我认为这涉及使用SQL WHERE子句作为过滤器的查询,但我需要对联系人进行排序吗?一个示例或提示会非常有帮助。

为了方便他人,我写了一篇帖子,其中包含查询姓名、照片、联系人 ID 等全部代码,并附有详细的解释。该代码包含了从不同答案中找到的代码片段,但更加有组织和经过测试。链接:http://hellafun.weebly.com/home/get-information-of-a-contact-from-number - Usman
6个回答

90

虽然这个问题已经得到了回答,但是这里提供一个获取电话号码对应联系人名称的完整函数。希望能帮助其他人:

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;
}

[基于Marcus的评论更新]

您需要请求此权限:

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


当恢复活动时,这使应用程序“不负责任”。我该怎么做? - Myat Min Soe
每次在Android 5.1上运行时,我也会遇到ANR。 - Marco Altran
可能是由于ANR,你需要在UI线程之外的线程上运行它。 - Marc
2
值得一提的是,这需要 <uses-permission android:name="android.permission.READ_CONTACTS"/> 权限。 - Marcus
你好,我尝试了类似的东西,但它没有起作用。这是我的问题,我真的很感谢你的帮助! :) http://stackoverflow.com/questions/35097844/get-contact-name/35098111#35098111 - Ruchir Baronia

83

要实现这一点,您需要使用优化的PhoneLookup提供程序,如所述。

AndroidManifest.xml中添加权限:

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

那么:

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;
}

1
不,它不会自动解决游标问题。如果需要帮助,请查看以下链接:https://dev59.com/nHNA5IYBdhLWcg3wk--A - Pentium10
1
我会使用URI初始化一个带有managedQuery的游标,然后将游标移动到第一个位置并获取数据。一旦我将游标移动到第一个位置,我就会使用getString。我假设第一个位置是正确的,因为查询是针对一个数字的,因此查询只会提取该数字的名称。 - Noah Seidman
9
具体来说,查询的其余部分包括什么?这个答案并没有比现有的文档提供更多帮助。 - eternalmatt
7
请提供完整的代码作为答案。当被询问如何迭代和获取名称时,初学者可能无法理解这两行代码。你需要编写一个函数,根据数字返回名称。 - Bhavesh Hirpara
你好,我尝试了类似的东西,但是它没有起作用。这是我的问题,我真的很感激你的帮助! :) http://stackoverflow.com/questions/35097844/get-contact-name/35098111#35098111 - Ruchir Baronia
显示剩余3条评论

26

这非常有帮助,这是我最终用来获取调用者姓名、id和照片的代码:

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);
}

然后您可以对“input”(他们的照片作为InputStream)、“name”和“contactId”进行任何操作。

以下是文档,列出了您可以访问的大约15个列,只需将它们添加到代码开头附近的projection中: http://developer.android.com/reference/android/provider/ContactsContract.PhoneLookup.html


2

这个版本与Vikram.exe的答案相同,但加入了代码以避免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();

}

1

在以下方法中传递您接到电话的联系人号码。此方法将检查联系人是否保存在您的手机中。如果联系人已保存,则返回联系人姓名,否则返回一个字符串“未知号码”。

将此代码添加到您的广播接收器类中。

    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;
}

要获取源代码,请访问this link


0
为此,我们可以使用PhoneLookup提供程序来获取使用手机号码的姓名或联系方式。
将权限添加到AndroidManifest.xml中:
<uses-permission android:name="android.permission.READ_CONTACTS"/>

在您的活动中添加以下自定义 Kotlin 方法,并使用所需的手机号码调用它。
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"
    }

了解更多信息:https://developer.android.com/training/contacts-provider/retrieve-names


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接