在安卓中读取所有联系人的电话号码

71

我正在使用这段代码来检索所有联系人姓名和电话号码:

String[] projection = new String[]
{
    People.NAME,
    People.NUMBER
};

Cursor c = ctx.getContentResolver().query(People.CONTENT_URI, projection, null, null, People.NAME + " ASC");
c.moveToFirst();

int nameCol = c.getColumnIndex(People.NAME);
int numCol = c.getColumnIndex(People.NUMBER);

int nContacts = c.getCount();

do
{
  // Do something
} while(c.moveToNext());

然而,这只会返回每个联系人的主要号码,但我也想获取次要号码。我该怎么做?


1
尝试使用Android联系人提取器。这是一个小巧、简单易用的库。 - Nitesh Tiwari
15个回答

153

以下代码展示了一种简单的方法来读取所有电话号码和姓名:

Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
while (phones.moveToNext())
{
  String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
  String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

}
phones.close();

注意: getContentResolver 是从Activity上下文获取的一个方法。


1
谢谢,这个单一查询方法快了100倍! - Pavel Alexeev
18
如果联系人有多个号码,那么速度会更快,但联系人姓名可能会重复。 - Wayne
@Dinesh Kumar,这个代码可以检索所有联系人,但我需要用户选择单个联系人。 - Karthik
如何避免重复? - Asif Sb
2
它只获取了一些少量的联系人!在我的情况下,ContactsContract.CommonDataKinds.Phone.CONTENT_URI 获取了361个联系人,但是 ContactsContract.Contacts.CONTENT_URI 却获取了5115个联系人!这有什么区别?! - S.M.Mousavi
它会创建重复的联系人。 所以@AsifSb使用以下游标 cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); - user9140980

30

您可以通过以下方式读取与联系人相关联的所有电话号码:

Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, personId);
Uri phonesUri = Uri.withAppendedPath(personUri, People.Phones.CONTENT_DIRECTORY);
String[] proj = new String[] {Phones._ID, Phones.TYPE, Phones.NUMBER, Phones.LABEL}
Cursor cursor = contentResolver.query(phonesUri, proj, null, null, null);
请注意,此示例(与您的示例一样)使用了已弃用的联系人 API。自 Eclair 起,该 API 已被替换为 ContactsContract API。ContactsContract

26

这段代码展示了如何获取每个联系人的所有电话号码。

ContentResolver cr = getActivity().getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur.getCount() > 0) {
    while (cur.moveToNext()) {
        String id = cur.getString(cur.getColumnIndex(
                  ContactsContract.Contacts._ID));
        String name = cur.getString(cur.getColumnIndex(
                  ContactsContract.Contacts.DISPLAY_NAME));
        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()) {
                  int phoneType = pCur.getInt(pCur.getColumnIndex(
                      ContactsContract.CommonDataKinds.Phone.TYPE));
                  String phoneNumber = pCur.getString(pCur.getColumnIndex(
                      ContactsContract.CommonDataKinds.Phone.NUMBER));
                  switch (phoneType) {
                        case Phone.TYPE_MOBILE:
                            Log.e(name + "(mobile number)", phoneNumber);
                            break;
                        case Phone.TYPE_HOME:
                            Log.e(name + "(home number)", phoneNumber);
                            break;
                        case Phone.TYPE_WORK:
                            Log.e(name + "(work number)", phoneNumber);
                            break;
                        case Phone.TYPE_OTHER:
                            Log.e(name + "(other number)", phoneNumber);
                            break;                                  
                        default:
                            break;
                  }
              } 
              pCur.close();
        }
    }
}

嗨@anivaler。我已经尝试在我的代码中实现您的解决方案,但它并不好用。显示正确的数字,但当我滚动时数字会改变。您能否看一下我的问题,请?http://stackoverflow.com/questions/38978923/recyclerview-change-the-value-of-my-phonenumber-in-contactscontract-when-scroll/38979586?noredirect=1#comment65314036_38979586 - S.P.
嗨,我已经实现了它,它运行得很好,但我不知道哪里出了问题,它会显示带有姓名的电话号码超过2次,但当我在手机上检查时,相同的号码和姓名只出现一次。 - Sunil Chaudhary

14

11

你可以使用以下代码获取所有的电话联系人:

    Cursor c = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            new String[] { ContactsContract.Contacts._ID,
                    ContactsContract.Contacts.DISPLAY_NAME,
                    ContactsContract.CommonDataKinds.Phone.NUMBER,
                    ContactsContract.RawContacts.ACCOUNT_TYPE },
            ContactsContract.RawContacts.ACCOUNT_TYPE + " <> 'google' ",
            null, null);

检查完整的示例在这里


4
对于我的大约800个联系人,使用这个答案中的代码运行时间为89毫秒,但是另一种方式(查询每个ID的联系人ID,然后查询电话号码)需要23000毫秒! - hungson175
1
超级快!最佳答案 - Azhar Bandri

10
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) 
{
    System.out.println("name : " + name + ", ID : " + id);

    // get the <span id="IL_AD4" class="IL_AD">phone
    // number</span>
    Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
                           null, 
                           ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);

    while (pCur.moveToNext())
    {
        String phone = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        System.out.println("phone" + phone);
    }

pCur.close();

3

已接受的答案有效,但未提供唯一的数字。

请参考以下代码,它会返回唯一的数字。

public static void readContacts(Context context) {
        if (context == null)
            return;
        ContentResolver contentResolver = context.getContentResolver();

        if (contentResolver == null)
            return;

        String[] fieldListProjection = {
                ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
                ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER,
                ContactsContract.Contacts.HAS_PHONE_NUMBER
        };

        Cursor phones = contentResolver
                .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI
                        , fieldListProjection, null, null, null);
        HashSet<String> normalizedNumbersAlreadyFound = new HashSet<>();

        if (phones != null && phones.getCount() > 0) {
            while (phones.moveToNext()) {
                String normalizedNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER));
                if (Integer.parseInt(phones.getString(phones.getColumnIndex(
                        ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                    if (normalizedNumbersAlreadyFound.add(normalizedNumber)) {
                        String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
                        String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                        String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                        Log.d("test", " Print all values");
                    }
                }
            }
            phones.close();
        }
    }

2
以同样的方式,只需使用其他“People”引用获取他们的其他数字。
People.TYPE_HOME
People.TYPE_MOBILE
People.TYPE_OTHER
People.TYPE_WORK

1
我修复了我的下面的需求。
清单权限。
        <uses-permission android:name="android.permission.READ_CONTACTS" />
        <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
        <!-- Read Contacts from phone -->
        <uses-permission android:name="android.permission.read_contacts" />
        <uses-permission android:name="android.permission.read_phone_state" />
        <uses-permission android:name="android.permission.READ_CALL_LOG" />

注意:在清单中授予权限后,一些手机可能会拒绝。如果发生这种情况,您需要进入“设置”-->“应用程序”-->找到您的应用程序并单击它,然后打开所需的权限。

enter image description here

 btn_readallcontacks.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            List<User> userList = new ArrayList<User>();
            while (phones.moveToNext()) {
                User user = new User();
                user.setNamee(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
                user.setPhone(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
                userList.add(user);
                Log.d(TAG, "Name : " + user.getNamee().toString());
                Log.d(TAG, "Phone : " + user.getPhone().toString());
            }
            phones.close();
        }
    });

1

这个one终于给了我我一直在寻找的答案。它可以让你检索手机上所有联系人的姓名和电话号码。

package com.test;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;

public class TestContacts extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
                              null, null, null, null);
        if (cur != null && cur.getCount() > 0) {
            while (cur.moveToNext()) {

                if (Integer.parseInt.equals(cur.getString(cur.getColumnIndex(
                            ContactsContract.Contacts.HAS_PHONE_NUMBER)))) {
                    String id = cur.getString(cur.getColumnIndex(
                                ContactsContract.Contacts._ID));
                    String name = cur.getString(cur.getColumnIndex(
                                ContactsContract.Contacts.DISPLAY_NAME));
                    Cursor pCur = cr.query(
                                           ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                            null,
                            ContactsContract.CommonDataKinds.Phone.CONTACT_ID
                                    + " = ?", new String[] { id }, null);
                    int i = 0;
                    int pCount = pCur.getCount();
                    String[] phoneNum = new String[pCount];
                    String[] phoneType = new String[pCount];
                    while (pCur != null && pCur.moveToNext()) {
                        phoneNum[i] = pCur.getString(pCur.getColumnIndex(
                        ContactsContract.CommonDataKinds.Phone.NUMBER));
                        phoneType[i] = pCur.getString(pCur.getColumnIndex(
                                ContactsContract.CommonDataKinds.Phone.TYPE));
                        i++;
                    }
                }

            }

        }

    }
}

1
不附带解释的踩踏真的不应该被允许,但我已经更新了我的代码到现在的状态。我目前使用这段代码。如果有错别字或其他导致它无法正常工作的问题,请告诉我,我会修复它。 - craned

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