Question

My application uses the Contacts ContentProvider to store some of its data. When I load a contact into memory, I want to save its ID (so that I know how to save changes later), and the ID of all data fields it is using (so they can be directly updated). Here is some of my code:

    Uri entityUri = Uri.withAppendedPath(
            ContentUris.withAppendedId(RawContacts.CONTENT_URI, id),
            Entity.CONTENT_DIRECTORY);

    Cursor resultData = context.getContentResolver().query(
            entityUri,
            new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1},
            null, null, null);
    resultData.moveToFirst();

    this.id = id;
    while (resultData.isAfterLast() == false) {
        this.source_id = resultData.getInt(0);
        if (!resultData.isNull(1)) {
            if (resultData.getString(2).equals(Fields.DISPLAY_NAME)) {
                this.display_name = resultData.getString(3);
                this.display_name_id = resultData.getInt(1);
            }
        }
        resultData.moveToNext();
    }
    resultData.close();
    return this;

That queries the ContentProvider and gets the DISPLAY_NAME field from the data. The ID of the data record is stored in the display_name_id variable. It comes out as 4612 when I run it on my device.

I tried saving it, but it does not update as expected. In order to debug, I added a query that tries to find the correct data table record.

    Cursor c = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
            new String[] {ContactsContract.Data._ID, CommonDataKinds.StructuredName.DISPLAY_NAME},
            ContactsContract.Data._ID + "=?",
            new String[] {String.valueOf(this.display_name_id)}, null);

However, this cursor comes back as having a length of 0. How can this be? Why is the ID incorrect?

Was it helpful?

Solution

I tried locally and it works for me, here's my code slightly adapted from yours:

public void testContacts(final @Nonnull Context context, final int rawContactId, final @Nonnull String expectedDisplayName) {
    Uri entityUri = Uri.withAppendedPath(
            ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId),
            ContactsContract.RawContacts.Entity.CONTENT_DIRECTORY);

    Cursor resultData = context.getContentResolver().query(
            entityUri,
            new String[]{
                    ContactsContract.RawContacts.SOURCE_ID,
                    ContactsContract.RawContacts.Entity.DATA_ID,
                    ContactsContract.RawContacts.Entity.MIMETYPE,
                    ContactsContract.RawContacts.Entity.DATA1
            },
            null, null, null);

    int displayNameId = -1;
    try {
        final int columnIndexDataId = resultData.getColumnIndex(ContactsContract.RawContacts.Entity.DATA_ID);
        final int columnIndexMimetype = resultData.getColumnIndex(ContactsContract.RawContacts.Entity.MIMETYPE);
        final int columnIndexData = resultData.getColumnIndex(ContactsContract.RawContacts.Entity.DATA1);
        while (resultData.moveToNext()) {
            if (!resultData.isNull(columnIndexDataId)) {
                if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(resultData.getString(columnIndexMimetype)) &&
                        expectedDisplayName.equals(resultData.getString(columnIndexData))) {
                    displayNameId = resultData.getInt(1);
                    break;
                }
            }
        }
    } finally {
        resultData.close();
    }

    String reLookedUpDisplayName = null;
    if (displayNameId != -1) {
        Cursor reLookupCursor = context.getContentResolver().query(
                ContactsContract.Data.CONTENT_URI,
                new String[] {
                        ContactsContract.Data._ID,
                        ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME
                },
                ContactsContract.Data._ID + "=?",
                new String[] {String.valueOf(displayNameId)},
                null);
        try {
            final int columnIndexId = reLookupCursor.getColumnIndex(ContactsContract.Data._ID);
            final int columnIndexDisplayName = reLookupCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
            while (reLookupCursor.moveToNext()) {
                reLookedUpDisplayName = reLookupCursor.getString(columnIndexDisplayName);
            }
        } finally {
            reLookupCursor.close();
        }
    }

    Toast.makeText(
            context,
            reLookedUpDisplayName != null ? "Found re-looked up name: " + reLookedUpDisplayName : "Didn't find name re-looking it up",
            Toast.LENGTH_LONG)
            .show();
}

There's no big difference from your code, so compare or try to replace bits of it to see where you have a problem. Make sure you use a fresh Cursor for each query, and close it correctly afterwards (in a finally clause).

Another thing, make sure that if (resultData.getString(2).equals(Fields.DISPLAY_NAME)) is really what you're wanting to do (it compares the entry mime type with Fields.DISPLAY_NAME), but since you're saying you get the data ID correctly this shouldn't be the problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top