0

Background

I want to change the photo of specific contacts in the address book.

The problem

I do some query of the contacts, as such:

final Cursor phonesCursor = context.getContentResolver()
            .query(ContactsContract.Data.CONTENT_URI,null,null,null,null);

and then, inside the loop that goes over the cursor, I tried to update the first contact's photo :

    if (phonesCursor != null) {
        while (phonesCursor.moveToNext()) {
            final int rawContactId = phonesCursor.getInt(phonesCursor
                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID));
            final String phoneNumber = phonesCursor.getString(phonesCursor
                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            String name = phonesCursor.getString(phonesCursor.getColumnIndex(Phone.DISPLAY_NAME));
            phonesMap.put(rawContactId, phoneNumber);
            Log.d("AppLog", "trying to set image for " + name);
            int photoRow = phonesCursor.getInt(phonesCursor.getColumnIndex(Phone._ID));
            phonesCursor.close();
            final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
            ByteArrayOutputStream streamy = new ByteArrayOutputStream();
            bitmap.compress(CompressFormat.PNG, 0, streamy);
            byte[] photo = streamy.toByteArray();

            final ContentValues values = new ContentValues();
            values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
            values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
            values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, photo);
            values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
            final int update = context.getContentResolver().update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data._ID + " = " + photoRow, null);
            Log.d("AppLog", "update result:" + update);
            break;
        }
    }

Thing is, the result is that "update" returns "1", so it is supposed to be successful, but when I get to the contacts, I don't see this photo.

What I tried

I tried to use a batch instead (using ArrayList and getContentResolver().applyBatch ), but it also didn't work .

I also tried to change the update call, to identify the item I wish to change in a different way (using RAW_CONTACT_ID instead). It also didn't work.

The questions

  1. How come it occurs? What should I do to fix this?

  2. What's the best way to update multiple contacts with new photos?

  3. Is it possible to also get the photo of the contact using the query that I had, without an extra query ? I wish to do it in order to see for myself that the contact was different before.

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • what does `phonesCursor.getCount()` return? and why are you doing your update only for `getPosition() == 0`? if not sure about your `Cursor` content use `DatabaseUtils#dumpCursor` / `DatabaseUtils#dumpCurrentRow` – pskink Aug 21 '16 at 05:57
  • If you are adding a contact through your App, why bother Amending something in a Contact. Just deleted it and add it in Again from Scratch. If you dont know how to do that i can give you the code – Tasos Aug 21 '16 at 06:29
  • @pskink It returns a value that's more than 0, because I have contacts. I removed the getPosition part now. It's a leftover of other tests. – android developer Aug 21 '16 at 08:29
  • @Tasos I didn't write that I add the contact. I wrote that I wish to update a contact. An already existing contact, that I've queried. – android developer Aug 21 '16 at 08:30
  • ok, how many contacts do you have and what does `phonesCursor.getCount()` return? give the numbers – pskink Aug 21 '16 at 08:35
  • @pskink At least 100. – android developer Aug 21 '16 at 10:45
  • i asked that question twice but it seems you dont want to answer... ok – pskink Aug 21 '16 at 10:49
  • @pskink I'm not near the computer that I made this sample so I can't provide an exact number, but I remember that it was at least 100. – android developer Aug 21 '16 at 10:59
  • Ok so you just modifying a contact photo -- Check this solution here http://stackoverflow.com/questions/7968156/android-change-contact-picture – Tasos Aug 21 '16 at 13:59
  • @Tasos This is what I looked at when I wrote this code, but, since I already have all the fields, I don't wish to perform extra queries. – android developer Aug 21 '16 at 16:19
  • @pskink OK, I've checked the count of the cursor, and it's 8796. – android developer Aug 21 '16 at 16:22
  • but the number of your contacts is (i guess) less than 1000? so i hope you already figured out what is `ContactsContract.Data` for and what kind of data it stores... and as i said `DatabaseUtils#dumpCursor` / `DatabaseUtils#dumpCurrentRow` are helpful here – pskink Aug 21 '16 at 16:25
  • Take a look at this then if it may help https://github.com/heinrisch/Contact-Picture-Sync/blob/master/src/heinrisch/contact/picture/sync/ContactHandler.java --- http://stackoverflow.com/questions/13990084/how-to-update-a-native-contact-photo-on-android – Tasos Aug 21 '16 at 16:33
  • If that doesnt help try here --- http://stackoverflow.com/questions/37209954/update-existing-contact-with-image-in-android -- http://stackoverflow.com/questions/36855859/changing-contacts-image-to-a-large-photo-via-photo-file-id-in-android/36946702#36946702 – Tasos Aug 21 '16 at 16:36
  • @pskink OK, I got it to change the photo, but using CONTACT_ID . What I did previously probably changed the field for an extended data of the contact, so that's why it was seem like it didn't do anything. Thing is, I remember that it's considered an unsafe way to use CONTACT_ID, since it can change once in a while. I remember it was recommended to use a more unique way to identify contacts. Can you please show what's the best way to change the photo? – android developer Aug 21 '16 at 21:14
  • do you mean `ContactsContract.RawContactsColumns.CONTACT_ID` ? – pskink Aug 22 '16 at 06:12
  • @pskink I meant ContactsContract.Data.CONTACT_ID , as this is the one used in the query, but it's pointing to the exact same value (since it's an interface), so it's the same... https://developer.android.com/reference/android/provider/ContactsContract.Data.html https://developer.android.com/reference/android/provider/ContactsContract.RawContactsColumns.html#CONTACT_ID – android developer Aug 22 '16 at 06:39
  • see http://pastebin.com/KWAuRj6m – pskink Aug 22 '16 at 08:19
  • @pskink So if there are multiple rows there that are of a single contact, the value of PHOTO_ID points to the ID of the contact's main data? – android developer Aug 22 '16 at 22:22
  • main data? what "main data" do you mean? – pskink Aug 23 '16 at 05:33
  • @pskink There are multiple records in this table, which all are of the same contact, no? One of them has the basic information about the contact, no? The one with mimetype CONTENT_ITEM_TYPE , no? – android developer Aug 23 '16 at 11:30
  • see http://pastebin.com/caQbpK4B, just add one contact with display name "aaaa" and try setting on it two different emails / three phone numbers etc and see the logcat of the code sippet i posted – pskink Aug 23 '16 at 11:48
  • @pskink I don't understand. – android developer Aug 24 '16 at 09:33
  • what in particular? – pskink Aug 24 '16 at 09:41
  • I don't understand what you show me, and what to do with it. – android developer Aug 27 '16 at 16:24

1 Answers1

0

OK, the correct field to use is "LOOKUP_KEY" :

int lookupKeyIdx = phonesCursor.getColumnIndex(Phone.LOOKUP_KEY);
final String lookupKey = phonesCursor.getString(lookupKeyIdx);
...
final int update = context.getContentResolver().update(ContactsContract.Data.CONTENT_URI, values, Phone.LOOKUP_KEY + " = " + lookupKey , null);
android developer
  • 114,585
  • 152
  • 739
  • 1,270