That's not how it works. The Data table contains one row per contact value field (phone number, email address, structured name ...). Each row has a mimetype
value that tells you how to interpret the columns of that row.
For example, if the mimetype
column has the value Phone.CONTENT_ITEM_TYPE
you must use the Phone
column mapping to access the data.
So if a contact has one phone number and one email address there are at least 3 rows for this contact in the Data
table. One for the StructuredName
(this one is required exactly once for each RawContact
), one for the Phone
number and one for the Email
address.
Each row also has a RAW_CONTACT_ID
that contains the row id of the RawContact the value belongs to.
When you query the Data
table, you actually read from a view that joins the real Data
table with the RawContacts
table, so each row also contains the CONTACT_ID
of the contact the row belongs to. That means if two rows have the same CONTACT_ID
they belong to the same contact.
I hope that explains it. I don't really know what you're trying to achieve in the end, so I can't give any helpful code snippets.
Update
The key to this is to check the mimetype of each row before you decide how to interpret the values. Also you need to read the CONTACT_ID
or RAW_CONTACT_ID
to be able to aggregate the data correctly. If you order the result by CONTACT_ID
you can assume that all rows belonging to a contact have been read when the CONTACT_ID
value changes.
The (untested) code snippet below should point you to the right direction. The point is, you can not get all the data of a contact in a single row. You always need to read multiple rows and aggregate them in some way.
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;
}
}
}