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

shr*_*ari 2 android android-contentprovider android-contacts android-contact-mimetype

我想从构建联系人选择器中读取联系人信息。我正在阅读电话号码,街道,电子邮件和地址。这是错误的。

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

Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
context.startActivityForResult(contactPickerIntent, REQUEST_ID_CONTACT_PICKER); 
Run Code Online (Sandbox Code Playgroud)

以下是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));

        }
Run Code Online (Sandbox Code Playgroud)

我无法确定为什么我在街道,emailId等列中得到了错误的数据(即联系电话)。

在这里,cursor.moveToNext()需要转到第一行,所以这显然是必需的,我的问题不是我得到的记录不同,我在街道,emailId列中得到了手机号码,这是错误的。

shr*_*ari 6

浪费了3天以上后,找到了执行我想要的方法:

有一个用于存储所有类型的数据(例如电话,地址,电子邮件等)的通用结构请参见通用列名称

这就是为什么我们无法使用联系人选择器的意图获取所有类型的数据(联系人,电子邮件,地址等)的原因,因此首先,由于联系人选择器的意图,我们需要获取联系人ID或contact lookUpKey,而不是查询其他详细信息分别。

但是,当尝试获取其他详细信息时会出现问题,因为每个数据都保存在相同的表结构中,即可以容纳任何联系数据的通用表。

并且,给定行中存储的数据类型由该行的MIMETYPE值指定,该值确定通用列DATA1至DATA15的含义。例如,如果数据Mime类型为Phone.CONTENT_ITEM_TYPE,则DATA1列存储电话号码,但如果数据Mime类型为Email.CONTENT_ITEM_TYPE,则DATA1存储电子邮件地址。

因此,首先,我们需要在查询任何类型的内容之前设置带有Mime类型的where子句,请参见此处的mime类型列表

这是我们应该如何选择联系人的方式:

int REQUEST_ID_CONTACT_PICKER = 1001;
Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
startActivityForResult(contactPickerIntent, REQUEST_ID_CONTACT_PICKER); 
Run Code Online (Sandbox Code Playgroud)

比在onActivityResult中,我们在数据中获得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!!");
    }
  }
Run Code Online (Sandbox Code Playgroud)

我们不需要查找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;
  }
Run Code Online (Sandbox Code Playgroud)

这是我们可以使用ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE以下方法获取电话详细信息的方式:

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;
  }
Run Code Online (Sandbox Code Playgroud)

这是我们如何使用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;
  }
Run Code Online (Sandbox Code Playgroud)

这是我们可以使用ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE以下方法获取PhoneDetails的方法:

  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;
  }
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)