获取联系人的名字和姓氏而不是单个显示名?

Posted

技术标签:

【中文标题】获取联系人的名字和姓氏而不是单个显示名?【英文标题】:Get first and last name of a contact rather than single display name? 【发布时间】:2012-01-15 22:38:03 【问题描述】:

我目前正在使用 android 联系人内容提供商,目前可以使用以下代码毫无问题地访问联系人的完整显示名称:

String[] PROJECTION = new String[] 
         ContactsContract.Contacts._ID,
         ContactsContract.Contacts.DISPLAY_NAME,
         ContactsContract.Contacts.HAS_PHONE_NUMBER,
        ;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

String SELECTION = "LOWER(" + ContactsContract.Contacts.DISPLAY_NAME + ")" 
    + " LIKE '" + constraint + "%' " + "and " + 
        ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1'";

Cursor cur = managedQuery(ContactsContract.Contacts.CONTENT_URI, 
                PROJECTION, SELECTION, null, sortOrder);

但是我希望能够分别获取联系人的名字和姓氏,我尝试使用 StructuredName 来尝试获取此信息,但似乎无法正常工作。

谁能指出我正确的方向,如何正确使用 StructuredName 将名称拆分为 First 和 Last?

更新:

按照 hovanessyan 的建议,我尝试了以下方法:

    String[] PROJECTION = new String[] 
            ContactsContract.Data._ID,
            ContactsContract.Data.DISPLAY_NAME,
            ContactsContract.Data.HAS_PHONE_NUMBER,
    ;

    String SELECTION = ContactsContract.CommonDataKinds.StructuredName.IN_VISIBLE_GROUP + " = '1'";

    String sortOrder = ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

    Cursor cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null, sortOrder);

    int indexGivenName = cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
    int indexFamilyName = cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
    int indexDisplayName = cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);

    while (cursor.moveToNext()) 
        String given = cursor.getString(indexGivenName);
        String family = cursor.getString(indexFamilyName);
        String display = cursor.getString(indexDisplayName);
        Log.e("XXX", "Name: | " + given + " | " + family + " | " + display);
     

但是使用 PROJECTION 会导致崩溃,如下所示:

12-08 16:52:01.575: E/AndroidRuntime(7912): Caused by: java.lang.IllegalArgumentException: Invalid column has_phone_number

如果我删除 PROJECTION,我会打印出所有结果,但其中很多包含 NULL。

例如:

12-08 16:56:14.055: E/XXX(8155): Name: | null | null | null
12-08 16:56:14.055: E/XXX(8155): Name: | null | null | null
12-08 16:56:14.055: E/XXX(8155): Name: | null | null | null
12-08 16:56:14.055: E/XXX(8155): Name: | null | null | null

那么任何人都可以看到我做错了什么,因为我的 PROJECTION 不起作用?

进一步更新:

我已经解决了我的 PROJECTION 的问题,但现在我遇到了一个问题,即 DATA 内容提供者向我提供所有空数据并导致我的代码中出现空指针异常。

例如,来自 ContactsContract.Contacts 的游标计数返回 115,但使用 DATA 表使用相同的参数返回 464,这在我的应用程序中造成了巨大的问题。

有人知道为什么会这样吗?

【问题讨论】:

您还需要选择 minetype 和 lookup_key 并合并联系人,从 android 示例中检查 Contactables。 【参考方案1】:

看看ContactsContract.CommonDataKinds.StructuredName 类。您在那里拥有所有需要的列,您可能可以执行以下操作:

Cursor cursor = contentResolver.query(ContactsContract.Data.CONTENT_URI, other_query_params_for_filtering);

int indexGivenName = cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
int indexFamilyName = cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
int indexDisplayName = cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);

while (cursor.moveToNext()) 
    String given = cursor.getString(indexGivenName);
    String family = cursor.getString(indexFamilyName);
    String display = cursor.getString(indexDisplayName);

【讨论】:

它必须在 FilterQuery 中完成,虽然这似乎是导致问题的原因,但我需要能够获取我的 String 约束等于 Given 或姓。所以我需要一个 managedQuery,这似乎带来了一些问题。 您必须使用通用表数据才能实现此目的:developer.android.com/reference/android/provider/… 我尝试使用通用 DATA 表获取信息,但遇到了一些问题,我已经编辑了我的问题,以防您进一步提供帮助,谢谢。 我明天会看看这个,但只是一个提示 - 如果你只选择不同的结果,光标的大小是多少。 您好,我试过了,但是没有用。这是我的问题,非常感谢您的帮助! :) ***.com/questions/35097844/get-contact-name/…【参考方案2】:

这是一个从ContactsContract.Data表中获取用户数据的通用函数:

Map<String, String> result = new HashMap<>();
Cursor cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, ContactsContract.Data.CONTACT_ID + "='" + YOUR_CONTACT_ID + "'", null, null);
if (cursor != null) 
    while (cursor.moveToNext()) 
        String mime = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE));
        switch (mime) 
            case ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE:
                result.put(FIRST_NAME, cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)));
                result.put(LAST_NAME, cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)));
                break;
            case ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE:
                result.put(CITY, cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY)));
                result.put(STREET, cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET)));
                result.put(ZIP, cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE)));
                break;
            case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE:
                if (ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE == cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))) 
                    result.put(MOBILE, cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
                
                break;
        
    
    cursor.close();

return result;

【讨论】:

【参考方案3】:
        Cursor phone_cursor = cr.query(ContactsContract.CommonDataKinds.
                Phone.CONTENT_URI, null, null, null, null);
        while (phone_cursor.moveToNext()) 
            try 
            int id = Integer.parseInt(phone_cursor.getString(phone_cursor.getColumnIndex
                    (ContactsContract.CommonDataKinds.Phone.CONTACT_ID)));
            Cursor name_cursor = cr.query(ContactsContract.Data.CONTENT_URI,null,
                    ContactsContract.Data.CONTACT_ID + "  = " + id, null, null);

                String name = phone_cursor.getString(phone_cursor.getColumnIndex
                        (ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                String first_name ="";
                String last_name = "";
                while (name_cursor.moveToNext()) 
                    if(name_cursor.getString(name_cursor.getColumnIndex
                            (ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME))!=null)
                    first_name = name_cursor.getString(name_cursor.getColumnIndex
                            (ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
                    last_name = name_cursor.getString(name_cursor.getColumnIndex
                            (ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
                
                name_cursor.close();
                String phoneNumber = phone_cursor.getString(phone_cursor.getColumnIndex
                        (ContactsContract.CommonDataKinds.Phone.NUMBER));
             catch (Exception e) 
            
        
        phone_cursor.close();

【讨论】:

以上是关于获取联系人的名字和姓氏而不是单个显示名?的主要内容,如果未能解决你的问题,请参考以下文章

如何从联系人中获取电子邮件和姓氏?

如何从联系信息中获取名字和姓氏?

如何获取联系人的显示名称属性

如何获取 Android 手机所有者的名字和姓氏?

Wordpress:如何在表格查询中获取用户的名字和姓氏?

从 Android 联系人中获取联系人姓名和姓氏