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

Android Studio(Java)获取指定联系人手机号报错求助

问题根源与修复方案

核心问题

你传入getContentResolver().query()的contactUri指向的是联系人主数据表(ContactsContract.Contacts.CONTENT_URI),这个表仅存储联系人的基础信息(如姓名、唯一ID),并不包含电话号码字段——电话号码存在专门的ContactsContract.CommonDataKinds.Phone数据表中,所以cursor里找不到NUMBER列,导致phoneNumberIndex返回-1。

另外你代码里定义了projection数组但查询时传了null,虽然不影响功能,但会查询所有字段,建议传入定义好的projection来优化性能。

修复方案

方案1:直接选择联系人电话记录(推荐)

如果是通过Intent唤起联系人选择器,把Intent的目标Uri改成ContactsContract.CommonDataKinds.Phone.CONTENT_URI,这样返回的Uri直接指向电话记录,无需关联查询:

// 示例:唤起联系人选择器的代码
Intent pickContactIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
// 用ActivityResultLauncher启动(替代已废弃的startActivityForResult)
pickContactLauncher.launch(pickContactIntent);

对应的查询代码可以简化为:

ContactInfo contactInfo = null;
String[] projection = {
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
        ContactsContract.CommonDataKinds.Phone.NUMBER
};
try (Cursor cursor = getContentResolver().query(contactUri, projection, null, null, null)) {
    if (cursor != null && cursor.moveToFirst()) {
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY));
        String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        contactInfo = new ContactInfo(name, phoneNumber);
    }
} catch (Exception e) {
    Log.d("Info SMS Error", Arrays.toString(e.getStackTrace()));
}
Log.d("Info SMS", String.valueOf(contactInfo));
return contactInfo;

方案2:通过联系人ID关联查询电话表

如果必须使用联系人主表的Uri,需要先从主表获取联系人ID,再用ID关联查询电话表:

ContactInfo contactInfo = null;
// 1. 从联系人主表获取ID和姓名
String[] contactProjection = {
        ContactsContract.Contacts._ID,
        ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
};
try (Cursor contactCursor = getContentResolver().query(contactUri, contactProjection, null, null, null)) {
    if (contactCursor != null && contactCursor.moveToFirst()) {
        String contactId = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID));
        String name = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
        
        // 2. 用联系人ID查询电话表获取号码
        String[] phoneProjection = {ContactsContract.CommonDataKinds.Phone.NUMBER};
        String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
        String[] selectionArgs = {contactId};
        
        try (Cursor phoneCursor = getContentResolver().query(
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                phoneProjection,
                selection,
                selectionArgs,
                null)) {
            if (phoneCursor != null && phoneCursor.moveToFirst()) {
                String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                contactInfo = new ContactInfo(name, phoneNumber);
            }
        }
    }
} catch (Exception e) {
    Log.d("Info SMS Error", Arrays.toString(e.getStackTrace()));
}
Log.d("Info SMS", String.valueOf(contactInfo));
return contactInfo;

额外注意事项

  • 动态权限检查:Android 6.0(API 23)及以上系统,除了在AndroidManifest.xml中声明READ_CONTACTS权限,还需要在代码中动态申请权限,确保用户授权后再执行查询操作。
  • 多号码处理:部分联系人可能有多个电话号码,上述代码仅获取第一个号码,若需要全部号码,可循环遍历phoneCursor。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 06:13:11