shridutt kothari shridutt kothari - 6 months ago 81
Android Question

Getting mobile number value for email id and street column, when using Contact Picker with Android native using intent with action Intent.ACTION_PICK

I am trying to get contact from contact picker, and getting mobile number in stree, email fields, which is wrong.

Following is the code to invoke contact picker:

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


Following is the OnActivityResult method's code, where i am fetching contact info from cursor:

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));

}


I am unable to identify, why i am getting wrong data (i.e. contact number) in street, emailId etc column.


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.

Answer

After wasting more than 3 days found the way to do what i wanted:

There's a common structure for storing all type of data i.e phone, address, email etc. 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

This is how we should fire a intent to choose the contact:

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

Than in onActivityResult, we get the URI in data:

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!!");
    }
  }

Not we need to find the LookUpKey, which is helpful to fetch any Mime type of data:

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

This is how we can fetch Phone Details using 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;
  }

This is how we can fetch Email Details using 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;
  }

This is how we can fetch PhoneDetails using ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE:

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

And this is the Contact POJO class, we are creating in above code:

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