按 MIME 类型从 phone-book 中选择联系人
Selecting contacts from phone-book by mime type
我正在尝试通过 MIME-TYPE
从 phone 获取联系人,因此我可以 select 具有以下类型的联系人:
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;
}
问题是这个查询,return 零 个联系人。
知道为什么吗?
您正在查询 table CommonDataKinds.Phone.CONTENT_URI
,其中 仅 数据行 MIMETYPE
= CommonDataKinds.Phone.CONTENT_ITEM_TYPE
。
但是您要求使用 MIMETYPE CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
的行,所以您得到的是一个空游标。
这是对您现有代码的简单修复,但即使修复后,您的代码也非常慢,它会 运行 设备上每个联系人的查询,这很容易是数百个甚至数百个数以千计的查询。如果只需要获取所有联系人的姓名+号码,试试下面的代码(一次查询全部获取):
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();
}
请注意,与您的代码类似,此代码可能会为每个联系人创建多个 Contact
对象,以防一个联系人有多个 phone。
如果每个联系人只需要一个 Contact
对象,则需要修改 Contact
对象以包含 phone 列表,并将 ArrayList<Contact>
更改为 HashMap<Long, Contact>
因此您可以将 phone 添加到现有对象而不是创建新对象。
我正在尝试通过 MIME-TYPE
从 phone 获取联系人,因此我可以 select 具有以下类型的联系人:
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;
}
问题是这个查询,return 零 个联系人。
知道为什么吗?
您正在查询 table CommonDataKinds.Phone.CONTENT_URI
,其中 仅 数据行 MIMETYPE
= CommonDataKinds.Phone.CONTENT_ITEM_TYPE
。
但是您要求使用 MIMETYPE CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
的行,所以您得到的是一个空游标。
这是对您现有代码的简单修复,但即使修复后,您的代码也非常慢,它会 运行 设备上每个联系人的查询,这很容易是数百个甚至数百个数以千计的查询。如果只需要获取所有联系人的姓名+号码,试试下面的代码(一次查询全部获取):
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();
}
请注意,与您的代码类似,此代码可能会为每个联系人创建多个 Contact
对象,以防一个联系人有多个 phone。
如果每个联系人只需要一个 Contact
对象,则需要修改 Contact
对象以包含 phone 列表,并将 ArrayList<Contact>
更改为 HashMap<Long, Contact>
因此您可以将 phone 添加到现有对象而不是创建新对象。