0

I am basing my code on the Login sample supplied with Android Studio. That sample contains code to populate an AutoCompleteTextView with email addresses related to the device's ContactsContract.Profile contact. i.e. the phone's owner, me.

I need to keep using the LoaderCallbacks interface methods - onCreateLoader() and onLoaderFinished().

I want to fetch extra details on the contact like:

  • phone number
  • given name
  • family name

To achieve this, I have tried adding extra fields to the ProfileQuery interface defined in the sample (that works correctly to fetch email address):

private interface ProfileQuery {
    String[] PROJECTION = {
            // these fields as per Android Studio sample
            ContactsContract.CommonDataKinds.Email.ADDRESS,
            ContactsContract.CommonDataKinds.Email.IS_PRIMARY,

            // these fields added by me
            ContactsContract.CommonDataKinds.Phone.NUMBER,
            ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
            ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
    };
}

I have modified the onCreateLoader() method to remove the sample's WHERE clause in the hope to get the extra data:

public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
    return new CursorLoader(this,
            // Retrieve data rows for the device user's 'profile' contact.
            Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
                    ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION,

            // select all fields
            null, null,

            // Show primary email addresses first. Note that there won't be
            // a primary email address if the user hasn't specified one.
            ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
}

For what it is worth, at the moment my onLoadFinished() just logs the received data out:

public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
    cursor.moveToFirst();
    while (!cursor.isAfterLast()) {
        Log.d("xxx", cursor.getString(0) + cursor.getString(1) + cursor.getString(2) + cursor.getString(3) + cursor.getString(4));
        cursor.moveToNext();
    }
}

I would like each cursor row to give me a complete set of data relating to the Profile contact. Instead, I am getting seemingly random fields from that contact.

My CursorLoader construction is clearly wrong, but I do not know how to fix that.

How can I get the following details from my Profile contact:

  • email address
  • phone number
  • given name
  • family name?
Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
  • related: [Best way to access all the details of android contacts](http://stackoverflow.com/questions/8506985/best-way-to-access-all-the-details-of-android-contacts) – Richard Le Mesurier Oct 14 '15 at 07:41

1 Answers1

0

The code above is based on a misunderstanding of how the contacts data is stored.

The Uri being used is pointing to the ContactsContract.Data table. The Developer docs explain the structure of this table. Each row in the table is an item of information, not a contact. e.g. an email address, a phone number etc.


The projection defined is specific to email addresses (since the sample deals only with emails). A more general projection that can handle different data types could be something like:

private interface ProfileQuery {
    String[] PROJECTION = {
            ContactsContract.Data.MIMETYPE,
            ContactsContract.Data.DATA1,
            ContactsContract.Data.DATA2,
            ContactsContract.Data.DATA3,
    };
}

As the docs explain:

DATA1 is an indexed column and should be used for the data element that is expected to be most frequently used in query selections. For example, in the case of a row representing email addresses DATA1 should probably be used for the email address itself, while DATA2 etc can be used for auxiliary information like type of email address.

.

For example, Phone.NUMBER is the same as Data.DATA1.


The query then returns a cursor row for each piece of information in the Profile contact. In my case, the 3 email addresses I stored, a phone number and my name.

For each row the Data.MIMETYPE column defines how the other data columns should be read. The mimetypes can be queried based on constants declared in ContactsContract.CommonDataKinds class, such as:

  • Email.CONTENT_ITEM_TYPE
  • Phone.CONTENT_ITEM_TYPE
  • StructuredName.CONTENT_ITEM_TYPE
  • Organization.CONTENT_ITEM_TYPE
Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255