从Android联系人选择器中获取联系信息

37

我想调用联系人选择器,将人名、电话和电子邮件获取到字符串中,并使用意图将它们发送到另一个活动。到目前为止,这个方法可以工作:

Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);  
startActivityForResult(intent, 1);  

// ...

@Override  
public void onActivityResult(int reqCode, int resultCode, Intent data) {  
    super.onActivityResult(reqCode, resultCode, data);  
    if (resultCode == Activity.RESULT_OK) {  
        Uri contactData = data.getData();  
        Cursor c =  managedQuery(contactData, null, null, null, null);  
        if (c.moveToFirst()) {  
            String name = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));  
            Intent intent = new Intent(CurrentActivity.this, NewActivity.class);  
            intent.putExtra("name", name);  
            startActivityForResult(intent, 0);  
        }  
    }  
}
但是如果我添加了以下内容:
String number = c.getString(c.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)); 

它强制关闭了

也许有其他方法可以获取他们的号码?

2个回答

61

电话号码

电话号码被存储在它们自己的表中,需要单独查询。要查询电话号码表,请使用存储在SDK变量ContactsContract.CommonDataKinds.Phone.CONTENT_URI中的URI。使用WHERE条件语句来获取指定联系人的电话号码。

    if (Integer.parseInt(cur.getString(
           cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
        Cursor pCur = cr.query(
        ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
        null, 
        ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", 
        new String[]{id}, null);
        while (pCur.moveToNext()) {
        // Do something with phones
        } 
        pCur.close();
    }

对Android联系人SQLite数据库执行第二个查询。电话号码通过存储在ContactsContract.CommonDataKinds.Phone.CONTENT_URI中的URI进行查询。联系人ID存储在电话表中,作为ContactsContract.CommonDataKinds.Phone.CONTACT_ID,并使用WHERE子句限制返回的数据。

电子邮件地址

查询电子邮件地址类似于电话号码。必须执行查询以从数据库获取电子邮件地址。查询存储在ContactsContract.CommonDataKinds.Email.CONTENT_URI中的URI以查询电子邮件地址表。

Cursor emailCur = cr.query( 
        ContactsContract.CommonDataKinds.Email.CONTENT_URI, 
        null,
        ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", 
        new String[]{id}, null); 
    while (emailCur.moveToNext()) { 
        // This would allow you get several email addresses
            // if the email addresses were stored in an array
        String email = emailCur.getString(
                      emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
        String emailType = emailCur.getString(
                      emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE)); 
    } 
    emailCur.close();
与电话查询一样,电子邮件表的字段名称也存储在ContactsContract.CommonDataKinds下。电子邮件查询是在ContactsContract.CommonDataKinds.Email.CONTENT_URI中执行的,并且WHERE子句必须与ContactsContract.CommonDataKinds.Email.CONTACT_ID字段匹配。由于可以存储多个电子邮件地址,请通过光标返回的记录进行循环处理。
更多教程请看此处 该方法需要Android API版本5或更高版本。

1
我该如何在最后一个 while 循环中查询电话号码? - eyal
7
cr.query似乎无法正常工作。此外,String[]{id}中的id是什么?我找不到这些变量中的任何一个。 - Kelly Elton
1
@kelton52 cr是内容解析器。您可以使用getContentResolver()来检索它。 - DarkLeafyGreen
3
@eyal 字符串 phoneNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 翻译: 将@eyal中的代码翻译为中文:从联系人数据库中获取电话号码,将其存储在字符串变量phoneNumber中。 - DarkLeafyGreen
1
我找到了一种避免多次查询的替代方法,使用ContactsContract.Contacts.Entity,链接在这里:https://dev59.com/WWYq5IYBdhLWcg3w8VG8#14082019 - Bianca Daniciuc
显示剩余4条评论

1

在接受的答案基础上,如果你想直接跳转到所需的电子邮件地址而不需要联系人权限,请使用以下内容:

private static final int REQUEST_CODE_EMAIL = 1;

void startSelectingEmail() {
    Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Email.CONTENT_URI);
    startActivityForResult(intent, REQUEST_CODE_EMAIL);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_EMAIL) {
        Uri emailUri = data.getData();
        Cursor emailCursor = getContext().getContentResolver().query(emailUri, null, null, null, null);
        if (emailCursor != null) {
            if (emailCursor.moveToFirst()) {
                String email = emailCursor.getString(
                        emailCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.DATA));
                String emailType = emailCursor.getString(
                        emailCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.TYPE));
                Log.d(TAG, "Email: " + emailType + " " + email);
            }
            emailCursor.close();
        }
    }
}

这不需要联系人权限来读取电子邮件地址,就像上面的双重查询方法一样。它还使您无需为具有多个电子邮件的联系人编写用户界面来选择适当的电子邮件地址,用户在联系人应用程序中选择特定的电子邮件,因此您只会得到一个结果。
光标返回了很多列,除了电子邮件地址外还有显示名称,尽管这仅在运行Android M的Nexus 5上得到了验证。

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