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
。
但是您要求的行具有MIMETYPEcommondatatypes.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();
}