从 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_IDRAW_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;
    }
  }
}