You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 通过手机号查询通讯录联系人姓名字段索引返回-1如何解决

问题排查与解决方案

核心问题原因

字段索引返回-1的问题,核心原因如下:

  • 使用的查询URI不支持拆分姓名字段:ContactsContract.PhoneLookup.CONTENT_FILTER_URI是系统提供的快速通过手机号匹配联系人的接口,它返回的结果集仅包含_ID、DISPLAY_NAME、手机号、头像ID这类基础信息,本身就不包含GIVEN_NAME(名)、FAMILY_NAME(姓)这类拆分的结构化姓名字段,所以查询这两个字段的索引必然返回-1。
  • 代码存在两处可导致异常的写法:
    • 定义的存储查询URI的变量是contactUri,但调用query方法时传入的第一个参数是未定义的uri,会导致查询请求错误
    • 遍历Cursor的循环中没有调用moveToNext()方法,会导致无限死循环

正确实现逻辑

要获取拆分的姓名字段,需要分两步查询:

  1. 先通过PhoneLookup接口用手机号查到对应的联系人ID
  2. 用联系人ID去查询系统通讯录的Data表,筛选结构化姓名类型的数据,即可拿到拆分的姓和名

修正后的代码示例

// 第一步:通过手机号查询联系人ID
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor phoneCursor = cResolver.query(contactUri, null, null, null, null); 
if(phoneCursor != null && phoneCursor.moveToFirst()) {
    int idColumnIndex = phoneCursor.getColumnIndex(ContactsContract.Contacts._ID);
    while (!phoneCursor.isAfterLast()) {
        long contactId = phoneCursor.getLong(idColumnIndex);
        MyContact contact = new MyContact();
        contact.setId(contactId);
        
        // 第二步:用联系人ID查询结构化姓名数据
        Cursor nameCursor = cResolver.query(
            ContactsContract.Data.CONTENT_URI,
            new String[]{
                ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
                ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME
            },
            ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?",
            new String[]{
                String.valueOf(contactId),
                ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
            },
            null
        );
        
        if(nameCursor != null && nameCursor.moveToFirst()) {
            int firstNameIndex = nameCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
            int lastNameIndex = nameCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
            contact.setFirstName(nameCursor.getString(firstNameIndex));
            contact.setLastName(nameCursor.getString(lastNameIndex));
            nameCursor.close();
        }
        
        // 此处处理得到的contact对象
        phoneCursor.moveToNext();
    }
    phoneCursor.close();
}

额外注意事项

  • 请确保你的应用已经申请了android.permission.READ_CONTACTS权限,Android 6.0及以上版本需要动态申请这个危险权限
  • 部分联系人可能没有填写拆分的姓名字段,此时读取到的值会为null,建议做好空值兼容处理

内容的提问来源于stack exchange,提问作者testivanivan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 20:54:02