Search code examples
androiduriandroid-contactscontactscontractrawcontactid

writeDisplayPhoto() changes the photo of another contact


I'm trying to set contact photo by using the function in the official android docs here,but the function changes the photo off completely different contact although i check the contactURI and contactID and use it to get the contact name and still changes the wrong contact photo.

Test example:

picked contact id: 4673

the value off rawContactPhotoUri in writeDisplayImage(): content://com.android.contacts/raw_contacts/4673/display_photo

the id for of the contact whom photo was changed by error: 147

My Process

I select the image and then select the contact using startActivityForResult(), then execute the function

My Code

onActivityResult() is:

 else if (requestCode == SELECT_CONTACT_FOR_RESULT) {
        if (resultCode == RESULT_OK) {
            contactUri=data.getData();
            setContactImage(contactUri, selectedImageURI, MainActivity.this)
        } else {
            //}
    } 

the setContactImage()

    public static void setContactImage(final Uri rawContactUri, final Uri selectedImageURI, final Activity activity, final boolean isFromShare) {
    final String nameString = getContactName(rawContactUri, activity);//get name using URI
    final long contactID = ContentUris.parseId(rawContactUri);
    if (writeDisplayPhoto(activity, contactID, getByteFromIMGUri(activity, selectedImageURI))) {//success toast                            }

writeDisplayImage()

private static boolean writeDisplayPhoto(Activity activity, long contactID, byte[] photo) {
    Uri rawContactPhotoUri = Uri.withAppendedPath(
            ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, contactID),
            ContactsContract.RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
    Debug.d(activity, "contactID: " + contactID + "rawContactPhotoUri: " + rawContactPhotoUri);
    try {
        AssetFileDescriptor fd =
                activity.getContentResolver().openAssetFileDescriptor(rawContactPhotoUri, "rw");
        OutputStream os = fd.createOutputStream();
        os.write(photo);
        os.close();
        fd.close();
        return true;
    } catch (IOException e) {
        Debug.e(activity, "Write Photo EXCEPTION: " + e);
        return false;
        // Handle error cases.
    }
}

getContactName()

 static String getContactName(Uri rawContactUri, Context context) {
    Cursor cursor;  // Cursor object
    cursor = context.getContentResolver().query(rawContactUri, null, null, null, null);
    cursor.moveToFirst();
    int phoneIndex = cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
    String string = cursor.getString(phoneIndex);
    cursor.close();
    Debug.d(context, "Name: " + string + " ,ID: " + ContentUris.parseId(rawContactUri) + " ,URI: " + rawContactUri, false);
    return string;
}

Solution

  • You seem to have a confusion between Contact ID and RawContact ID.

    In ContactsContract a Contact is comprised of multiple RawContacts. The ID of a Contact is not the same as the IDs of its RawContacts, and it's possible that the same ID will be used for some Contact but also some totally different RawContact (as you noticed with the wrong contact getting updated).

    The is in line: setContactImage(contactUri, selectedImageURI, MainActivity.this) where you're passing a ContactUri (with a Contact ID) to a method that expects a RawContactUri (with a RawContact ID). You also have some errors when getting the ID out of a RawContactUri and calling it contactId wrongly.

    Here's some code to find some random RawContactUri from a given ContactUri:

    Uri getSomeRawContactUri(Uri contactUri) {
        long contactId = ContentUris.parseId(contactUri);
        String[] projection = new String[] { RawContacts._ID };
        String selection = RawContacts.CONTACT_ID + " = " + contactId;
        Cursor cursor = context.getContentResolver().query(RawContacts.CONTENT_URI, projection, selection, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            long rawContactId = cursor.getLong(0);
            cursor.close();
            Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
            return rawContactUri;
        }
        return null;
    }