使用 Intent.ACTION_PICK 读取 phone 号码和地址

Read phone number along with address using Intent.ACTION_PICK

我想从构建联系人选择器中读取联系信息。我正在阅读 phone 号码、街道、电子邮件和 address.It 出错了。

以下是调用联系人选择器的代码:

Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
context.startActivityForResult(contactPickerIntent, REQUEST_ID_CONTACT_PICKER); 

以下是 OnActivityResult 方法的代码,其中我 fetching contact 来自光标的信息:

Uri contactURI = intent.getData();
                    Cursor cursor = activity.getContentResolver().query(contactURI, null, null, null, null);
int count = cursor.getCount();
// here value of count is 1, so need to do cursor.moveToNext() to go to selected record.
if (cursor.moveToNext()) {
            String givenName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            String familyName =  cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
            String displayName =  cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
            String middleName =  cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));

            int contactType = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
            String phoneNo = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            String poBox = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
            String street = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
            String city = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
            String state = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
            String postalCode = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
            String country = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
            String neighborhood = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD));
            String formattedAddress = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS));
            String emailId = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));

        }

我无法确定为什么我在街道、电子邮件 ID 等列中收到错误的数据(即联系电话)。

Here cursor.moveToNext() is required to go to first row, so it's obviously required, and my question is not that i am getting different record, i am getting mobile number in street, emailId column, which is wrong.

在浪费了 3 天多之后找到了做我想做的事情的方法:

有一个 common structure 用于存储所有类型的数据,即 phone、地址、电子邮件等。 See the common columns names,

That's why we can not get all type of data (contact, email, address etc) with contact picker intent, so first we need to get the contact Id or contact lookUpKey as a result of contact picker intent, than we need to query other details separately.

But the problem comes when try to fetch other details because, each data is saved in same table structure, i.e. generic table that can hold any kind of contact data.

And the kind of data stored in a given row is specified by the row's MIMETYPE value, which determines the meaning of the generic columns DATA1 through DATA15. For example, if the data Mime type is Phone.CONTENT_ITEM_TYPE, then the column DATA1 stores the phone number, but if the data Mime type is Email.CONTENT_ITEM_TYPE, then DATA1 stores the email address.

So first we need to set where clause with Mime type before querying the any type of content, see the list of mime types here

这就是我们应该如何触发选择联系人的意图:

int REQUEST_ID_CONTACT_PICKER = 1001;
Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
startActivityForResult(contactPickerIntent, REQUEST_ID_CONTACT_PICKER); 

比起在onActivityResult中,我们得到了data中的URI:

public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    Contact contact = null;
    if (resultCode == Activity.RESULT_OK) {
      switch (requestCode) {
        case REQUEST_ID_CONTACT_PICKER :
          try {
            Uri contactURI = intent.getData();
            contact = fetchAndBuildContact(getApplicationContext(), contactURI);
            Log.d(LOG_TAG, "Pick contact sucessfully!!"+contact.toString());
          }
          catch (Exception e) {
            Log.e(LOG_TAG, "Failed to pick contact!!");
            e.printStackTrace();
          }
          break;
      }
    } else {
      Log.e(LOG_TAG, "Failed to pick contact!!");
    }
  }

我们不需要找到 LookUpKey,它有助于获取任何 Mime 类型的数据:

  private Contact fetchAndBuildContact(Context ctx, Uri uriContact){
      // Getting cursorLookUpKey because contacts ID may not be correct all the time.
      Cursor cursorLookUpKey = ctx.getContentResolver().query(uriContact, new String[]{ContactsContract.Data.LOOKUP_KEY}, null, null, null);
      Contact contact = null;
      String lookupKey = null;
      if (cursorLookUpKey.moveToFirst()) {
          lookupKey = cursorLookUpKey.getString(cursorLookUpKey.getColumnIndex(ContactsContract.Data.LOOKUP_KEY));
          if(null != lookupKey ){
              contact = new Contact();
              contact = buildConactPhoneDetails(lookupKey, ctx, contact);
              contact = buildEmailDetails(lookupKey, ctx, contact);
              contact = buildAddressDetails(lookupKey, ctx, contact);
          }
      }
      cursorLookUpKey.close();
      return contact;
  }

这就是我们如何使用 ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE 获取 Phone 详细信息:

private Contact buildConactPhoneDetails(String lookupKey, Context ctx, final Contact contact) {
      ContentResolver contentResolver = ctx.getContentResolver();
      String contactWhere = ContactsContract.Data.LOOKUP_KEY + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; 
      String[] contactWhereParams = new String[]{lookupKey, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE};
      Cursor cursorPhone = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, contactWhere, contactWhereParams, null);
      if (cursorPhone.getCount() > 0) {
            if (cursorPhone.moveToNext()) {
                if (Integer.parseInt(cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                    String givenName = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                    String familyName = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
                    String middleName = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
                    int contactType = cursorPhone.getInt(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                    String phoneNo = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contact.contactNumber = phoneNo;
                    contact.givenName = givenName;
                    contact.familyName = familyName;
                    contact.middleName = middleName;
                    contact.contactType = contactType;
                }
            }
      }
      cursorPhone.close();
      return contact;
  }

这就是我们如何使用 ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE 获取电子邮件详细信息:

  private Contact buildEmailDetails (String lookupKey, Context ctx, final Contact contact) {
      ContentResolver contentResolver = ctx.getContentResolver();
      String emailWhere = ContactsContract.Data.LOOKUP_KEY+ " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; 
      String[] emailWhereParams = new String[]{lookupKey, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE};
      Cursor emailCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, emailWhere, emailWhereParams, null); 
      if (emailCursor.moveToNext()) { 
          String emailId = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
          contact.emailId = emailId;
      } 
      emailCursor.close();
      return contact;
  }

这就是我们如何使用 ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE 获取 Phone 详细信息:

  private Contact buildAddressDetails(String lookupKey, Context ctx, final Contact contact) {
    ContentResolver contentResolver = ctx.getContentResolver();
    String addrWhere = ContactsContract.Data.LOOKUP_KEY + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; 
    String[] addrWhereParams = new String[]{lookupKey, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}; 
    Cursor addrCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, addrWhere, addrWhereParams, null); 
    if (addrCursor.moveToNext()) {
        String poBox = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
        String street = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
        String city = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
        String state = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
        String postalCode = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
        String country = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
        String neighborhood = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD));
        String formattedAddress = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS));

        contact.poBox = poBox;
        contact.street = street;
        contact.city = city;
        contact.state = state;
        contact.zipcode = postalCode;
        contact.country = country;
        contact.street = street;
        contact.neighborhood = neighborhood;
        contact.poBox = poBox;
        contact.formattedAddress = formattedAddress;
    }
    addrCursor.close();
    return contact;
  }

这是我们在上面的代码中创建的 Contact POJO class:

public class Contact {
    String country;
    String poBox;
    String givenName;
    String middleName;
    String familyName;
    String address;
    String city;
    String state;
    String street;
    String zipcode;
    String emailId;
    String contactNumber;
    String neighborhood;
    String formattedAddress;
    String label;
    int contactType;
}