从 Android 联系提供商处检索联系信息
Retrieve Contact info from Android Contact Provider
我正在尝试从联系人提供程序检索数据,但显示的数据似乎查询不正确。我使用的代码如下:
mCursor = mContext.getContentResolver().query(
ContactsContract.Data.CONTENT_URI, null, null, null, null);
if(mCursor == null){
mListener.onRetrieveError();
return;
}
for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
String contact_f = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
String contact_m = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
String contact_l = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
String phone_type = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
String email_type = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
Log.d(TAG, "|" + contact_l + ", " + contact_f + " " + contact_m + " | " + phone_type + " | " + email_type);
}
日志显示例如:
Log: |LastName, FirstName | FirstName | FirstName
Log: |null, 3 null | 3 | 3
我期待:
Log: |LastName, FirstName MiddleName | PhoneType| EmailType
我希望能够获取名字、姓氏、中间名、电子邮件类型 (home/work...) - 以及列出的所有电子邮件类型以及 phone 类型。
例如,目标是为联系人获取他的姓氏、名字和中间名,并说我们得到的是家庭和工作 phone 或电子邮件
我得到的结果似乎是混合的。
任何想法。
此致
你可以使用这个
public void getAllContacts(){
Cursor cursor = null;
ContactPerson contact;
try {
cursor = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
int nameIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int phoneNumberIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
int emailAddressIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
cursor.moveToFirst();
do {
contact = new ContactPerson(cursor.getString(nameIdx),cursor.getString(phoneNumberIdx),cursor.getString(emailAddressIdx));
cpList.add(contact);
// Toast.makeText(getActivity(),cursor.getString(nameIdx)+" "+ cursor.getString(phoneNumberIdx),Toast.LENGTH_SHORT).show();
} while (cursor.moveToNext());
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getActivity(),e.getMessage(), Toast.LENGTH_LONG).show();
Log.d("Error",e.getMessage());
} finally {
if (cursor != null) {
cursor.close();
}
}
}
我认为您使用的 URI 有误。
尝试使用 ContactsContract.Contacts.CONTENT_URI
而不是 ContactsContract.Data.CONTENT_URI
(这是我使用的)。
事情不是这样的。 Data table contains one row per contact value field (phone number, email address, structured name ...). Each row has a mimetype
值告诉您如何解释该行的列。
例如,如果 mimetype
列具有值 Phone.CONTENT_ITEM_TYPE
you must use the Phone
列映射以访问数据。
因此,如果一位联系人有一个 phone 号码和一个电子邮件地址,则该联系人在 Data
table 中至少有 3 行。一个用于 StructuredName
(this one is required exactly once for each RawContact
), one for the Phone
number and one for the Email
地址。
每一行也有一个 RAW_CONTACT_ID
that contains the row id of the RawContact 该值所属的值。
当您查询 Data
table 时,您实际上是从连接真实 Data
table 与 RawContacts
[=54] 的视图中读取的=],因此每一行还包含该行所属联系人的 CONTACT_ID
。这意味着如果两行具有相同的 CONTACT_ID
它们属于同一个联系人。
我希望能解释清楚。我真的不知道你最终想要实现什么,所以我不能提供任何有用的代码片段。
更新
这样做的关键是在决定如何解释值之前检查每行的 mimetype。您还需要阅读 CONTACT_ID
或 RAW_CONTACT_ID
才能正确聚合数据。如果您按 CONTACT_ID
对结果排序,您可以假设当 CONTACT_ID
值更改时,属于联系人的所有行都已被读取。
下面的(未经测试的)代码片段应该为您指明了正确的方向。关键是,您无法在一行中获取联系人的所有数据。您总是需要读取多行并以某种方式聚合它们。
mCursor = mContext.getContentResolver().query(
ContactsContract.Data.CONTENT_URI, null, null, null, ContactsContract.Data.CONTACT_ID);
if(mCursor == null){
mListener.onRetrieveError();
return;
}
colIdxContactId = mCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
colIdxMimetype = mCursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
long lastContactId = -1L;
for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext())
// this is the contact Id the current row belongs to
long contactId = mCursor.getLong(colIdxContactId);
if (lastContactId != contactId) {
// the previous contact is complete, the following data belong to a new contact
// handle this case ...
lastContactId = contactId;
}
// the mimetype column tells us how to interpret the current row:
switch(mCursor.getString(colIdxMimetype)) {
case ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE: {
// this row is a structured name
String contact_f = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
String contact_m = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
String contact_l = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
// store names somewhere ...
break;
}
case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE: {
// this row represents a phone number
int phone_type = mCursor.getInt(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
// store phone_type somewhere ...
break;
}
case ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE: {
// this row represents an email address
int email_type = mCursor.getInt(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
// store email_type somewhere ...
break;
}
}
}
我正在尝试从联系人提供程序检索数据,但显示的数据似乎查询不正确。我使用的代码如下:
mCursor = mContext.getContentResolver().query(
ContactsContract.Data.CONTENT_URI, null, null, null, null);
if(mCursor == null){
mListener.onRetrieveError();
return;
}
for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
String contact_f = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
String contact_m = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
String contact_l = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
String phone_type = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
String email_type = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
Log.d(TAG, "|" + contact_l + ", " + contact_f + " " + contact_m + " | " + phone_type + " | " + email_type);
}
日志显示例如:
Log: |LastName, FirstName | FirstName | FirstName
Log: |null, 3 null | 3 | 3
我期待:
Log: |LastName, FirstName MiddleName | PhoneType| EmailType
我希望能够获取名字、姓氏、中间名、电子邮件类型 (home/work...) - 以及列出的所有电子邮件类型以及 phone 类型。
例如,目标是为联系人获取他的姓氏、名字和中间名,并说我们得到的是家庭和工作 phone 或电子邮件
我得到的结果似乎是混合的。
任何想法。
此致
你可以使用这个
public void getAllContacts(){
Cursor cursor = null;
ContactPerson contact;
try {
cursor = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
int nameIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int phoneNumberIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
int emailAddressIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
cursor.moveToFirst();
do {
contact = new ContactPerson(cursor.getString(nameIdx),cursor.getString(phoneNumberIdx),cursor.getString(emailAddressIdx));
cpList.add(contact);
// Toast.makeText(getActivity(),cursor.getString(nameIdx)+" "+ cursor.getString(phoneNumberIdx),Toast.LENGTH_SHORT).show();
} while (cursor.moveToNext());
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getActivity(),e.getMessage(), Toast.LENGTH_LONG).show();
Log.d("Error",e.getMessage());
} finally {
if (cursor != null) {
cursor.close();
}
}
}
我认为您使用的 URI 有误。
尝试使用 ContactsContract.Contacts.CONTENT_URI
而不是 ContactsContract.Data.CONTENT_URI
(这是我使用的)。
事情不是这样的。 Data table contains one row per contact value field (phone number, email address, structured name ...). Each row has a mimetype
值告诉您如何解释该行的列。
例如,如果 mimetype
列具有值 Phone.CONTENT_ITEM_TYPE
you must use the Phone
列映射以访问数据。
因此,如果一位联系人有一个 phone 号码和一个电子邮件地址,则该联系人在 Data
table 中至少有 3 行。一个用于 StructuredName
(this one is required exactly once for each RawContact
), one for the Phone
number and one for the Email
地址。
每一行也有一个 RAW_CONTACT_ID
that contains the row id of the RawContact 该值所属的值。
当您查询 Data
table 时,您实际上是从连接真实 Data
table 与 RawContacts
[=54] 的视图中读取的=],因此每一行还包含该行所属联系人的 CONTACT_ID
。这意味着如果两行具有相同的 CONTACT_ID
它们属于同一个联系人。
我希望能解释清楚。我真的不知道你最终想要实现什么,所以我不能提供任何有用的代码片段。
更新
这样做的关键是在决定如何解释值之前检查每行的 mimetype。您还需要阅读 CONTACT_ID
或 RAW_CONTACT_ID
才能正确聚合数据。如果您按 CONTACT_ID
对结果排序,您可以假设当 CONTACT_ID
值更改时,属于联系人的所有行都已被读取。
下面的(未经测试的)代码片段应该为您指明了正确的方向。关键是,您无法在一行中获取联系人的所有数据。您总是需要读取多行并以某种方式聚合它们。
mCursor = mContext.getContentResolver().query(
ContactsContract.Data.CONTENT_URI, null, null, null, ContactsContract.Data.CONTACT_ID);
if(mCursor == null){
mListener.onRetrieveError();
return;
}
colIdxContactId = mCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
colIdxMimetype = mCursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
long lastContactId = -1L;
for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext())
// this is the contact Id the current row belongs to
long contactId = mCursor.getLong(colIdxContactId);
if (lastContactId != contactId) {
// the previous contact is complete, the following data belong to a new contact
// handle this case ...
lastContactId = contactId;
}
// the mimetype column tells us how to interpret the current row:
switch(mCursor.getString(colIdxMimetype)) {
case ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE: {
// this row is a structured name
String contact_f = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
String contact_m = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
String contact_l = mCursor.getString(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
// store names somewhere ...
break;
}
case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE: {
// this row represents a phone number
int phone_type = mCursor.getInt(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
// store phone_type somewhere ...
break;
}
case ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE: {
// this row represents an email address
int email_type = mCursor.getInt(mCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
// store email_type somewhere ...
break;
}
}
}