Android 按mime类型从通讯录中选择联系人

Android 按mime类型从通讯录中选择联系人,android,android-contacts,contentobserver,Android,Android Contacts,Contentobserver,我正试图通过MIME-TYPE从手机中获取联系人,因此我可以选择具有以下类型的联系人: ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE 以下是我使用的方法: public static ArrayList<Contact> fetchContactsFromPhone(@NonNull Context context) { ArrayList<Contact> contacts

我正试图通过
MIME-TYPE
从手机中获取联系人,因此我可以选择具有以下类型的联系人:

ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
以下是我使用的方法:

public static ArrayList<Contact> fetchContactsFromPhone(@NonNull Context context) {
    ArrayList<Contact> contacts = new ArrayList<>();

    Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
    String _ID = ContactsContract.Contacts._ID;

    String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
    String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
    Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
    String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
    ContentResolver contentResolver = context.getContentResolver();
    Cursor cursor = contentResolver.query(CONTENT_URI, null, null, null, null);

    if (cursor != null && cursor.getCount() > 0) {

        while (cursor.moveToNext()) {

            String contact_id = cursor.getString(cursor.getColumnIndex(_ID));

            String name = cursor.getString(cursor.getColumnIndex(DISPLAY_NAME));
            long hasPhoneNumber = Long.parseLong(cursor.getString(cursor.getColumnIndex(HAS_PHONE_NUMBER)));

            if (hasPhoneNumber > 0) {

                Cursor phoneCursor = contentResolver.query(
                        PhoneCONTENT_URI,
                        null,
                        Phone_CONTACT_ID + " = " + contact_id + " AND " + ContactsContract.Data.MIMETYPE + " = " + "'"+ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE+"'"
                        , null, null);


                if (phoneCursor != null) {
                    while (phoneCursor.moveToNext()) {
                        Contact contact = new Contact();

                        String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
                        phoneNumber = phoneNumber.replaceAll("[()\\-\\s]", "").trim();

                        contact.setName(name);
                        contact.setPhoneNum(phoneNumber);

                        contacts.add(contact);
                    }
                    phoneCursor.close();
                }
            }
        }
        cursor.close();
    }

    //return data
    return contacts;
}
publicstaticarraylistfetchcontactsfromphone(@NonNull Context){
ArrayList联系人=新建ArrayList();
Uri CONTENT\u Uri=Contacts contract.Contacts.CONTENT\u Uri;
String _ID=Contacts contact.Contacts.\u ID;
String DISPLAY\u NAME=Contacts contract.Contacts.DISPLAY\u NAME;
字符串HAS\u PHONE\u NUMBER=Contacts contract.Contacts.HAS\u PHONE\u NUMBER;
Uri PhoneCONTENT\u Uri=ContactsContract.CommonDataTypes.Phone.CONTENT\u Uri;
字符串Phone\u CONTACT\u ID=contacts contract.commondatatypes.Phone.CONTACT\u ID;
字符串编号=contacts contract.commonDataTypes.Phone.NUMBER;
ContentResolver ContentResolver=context.getContentResolver();
Cursor Cursor=contentResolver.query(CONTENT\u URI,null,null,null);
if(cursor!=null&&cursor.getCount()>0){
while(cursor.moveToNext()){
String contact_id=cursor.getString(cursor.getColumnIndex(_id));
字符串名称=cursor.getString(cursor.getColumnIndex(DISPLAY_name));
long hasPhoneNumber=long.parseLong(cursor.getString(cursor.getColumnIndex(HAS_PHONE_NUMBER));
如果(hasPhoneNumber>0){
Cursor phoneCursor=contentResolver.query(
PhoneCONTENT_URI,
无效的
电话\联系人\ ID+“=”+联系人\ ID+”和“+联系人合同.Data.MIMETYPE+”=“+””“+联系人合同.commonDataTypes.StructuredName.CONTENT\项目\类型+””
,空,空);
如果(phoneCursor!=null){
while(phoneCursor.moveToNext()){
触点=新触点();
字符串phoneNumber=phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
phoneNumber=phoneNumber.replaceAll(“[()\\-\\s]”,“).trim();
contact.setName(name);
联系人:setPhoneNum(电话号码);
联系人。添加(联系人);
}
phoneCursor.close();
}
}
}
cursor.close();
}
//返回数据
返回联系人;
}
问题是这个查询,返回零个联系人


知道原因吗?

您正在查询表
CommonDataTypes.Phone.CONTENT\u URI
,该表只包含数据行,其中包含
MIMETYPE
=
CommonDataTypes.Phone.CONTENT\u ITEM\u TYPE
。 但是您要求的行具有MIMETYPE
commondatatypes.StructuredName.CONTENT\u ITEM\u TYPE
,因此您得到的是一个空游标

这是对现有代码的简单修复,但即使修复后,您的代码也非常慢,它会在设备上为每个联系人运行一个查询,这很容易是数百甚至数千个查询。如果您只需要获取所有联系人的姓名+号码,请尝试以下代码(一次查询即可获取所有联系人):

ArrayList contacts=new ArrayList();
//确保从Contacts contract.CommonDataTypes.Phone导入电话
String[]projection={Phone.CONTACT\u ID,Phone.DISPLAY\u NAME,Phone.NUMBER};
cursorcur=cr.query(Phone.CONTENT\u URI,projection,null,null,null);
while(cur!=null&&cur.moveToNext(){
long id=cur.getLong(0);
字符串名称=cur.getString(1);
字符串编号=cur.getString(2);
Log.d(标记“got”+id+,“+name+”,“+number”);
触点=新触点();
contact.setName(name);
联系人:setPhoneNum(号码);
联系人。添加(联系人);
}
如果(cur!=null){
cur.close();
}
请注意,与您的代码类似,此代码可能会为每个联系人创建多个
Contact
对象,以防一个联系人有多个电话。
如果每个联系人只需要一个
联系人
对象,则需要修改
联系人
对象以包含电话列表,并将
ArrayList
更改为
HashMap
,这样您就可以将手机添加到现有对象中,而不是创建新对象。

我接受您的回答,因为它解决了获得
零结果以及提高性能的问题,谢谢。但是,我使用MIME-TYPE筛选的条件是,我试图获取不属于任何帐户[WhatsApp account for ex]的联系人,因为这会导致获取相同号码但格式不同的重复联系人!此外,我的应用程序添加了像WhatsApp这样的联系人,因此在抓取过程中,我从许多帐户中获得了许多重复的联系人!你知道如何克服这一点吗?正如我在下面的回答中提到的代码,按帐户过滤对你没有帮助,因为拥有多个号码的联系人即使从单个帐户中选择(例如谷歌),也会重复。您需要将
ArrayList
更改为
HashMap
,其中键为
CONTACT\u ID
,并将属于同一联系人的多个号码放在一个
CONTACT
对象中是的,您是正确的!,非常感谢您的帮助:)
ArrayList<Contact> contacts = new ArrayList<>();

// Make sure you import Phone from ContactsContract.CommonDataKinds.Phone

String[] projection = { Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER };
Cursor cur = cr.query(Phone.CONTENT_URI, projection, null, null, null);

while (cur != null && cur.moveToNext()) {
    long id = cur.getLong(0);
    String name = cur.getString(1);
    String number = cur.getString(2);

    Log.d(TAG, "got " + id + ", " + name + ", " + number);

    Contact contact = new Contact();

    contact.setName(name);
    contact.setPhoneNum(number);
    contacts.add(contact);
}

if (cur != null) {
    cur.close();
}