How to set default image to Android phone contact

2019-06-07 17:38发布

问题:

I have a piece of code which updates the an Android contact´s image, the problem is that it doesn't work when the contact has no previous image. I also checked that the contact was from "Phone" account or "*@gmail.com" account. When it already has an image with these accounts I have no problem updating the image, the problem is just when the contact has no previous image assigned.

Here is the method in charge of updating the image.

public void update(long id, Bitmap bitmap) {       

    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

    // Picture
    try
    {
        ByteArrayOutputStream image = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG , 100, image);

        Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
        builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
        builder.withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND " + ContactsContract.Data.MIMETYPE + "=?", 
                new String[]{String.valueOf(id), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE});
        builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, image.toByteArray());
        ops.add(builder.build());
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    try
    {
        this.context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

And here is how I know if the contact belongs to one of the two accounts I mentioned above:

// Getting the raw contact id
public static int getRawContactId(Context context, long id) {

    String[] projection = new String[] { ContactsContract.RawContacts._ID };
    String selection = ContactsContract.RawContacts.CONTACT_ID + "=?";
    String[] selectionArgs = new String[] { String.valueOf(id) };
    Cursor c = context.getContentResolver().query(
            ContactsContract.RawContacts.CONTENT_URI, projection,
            selection, selectionArgs, null);
    int rawContactId = -1;
    if (c.moveToFirst()) {
        rawContactId = c.getInt(c
                .getColumnIndex(ContactsContract.RawContacts._ID));
    }

    return rawContactId;
}

Here I get the account name for further analysis

//...
Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
String[] rawProjection = { RawContacts._ID, RawContacts.ACCOUNT_NAME };
Cursor raw = context.getContentResolver().query(rawContactUri, rawProjection, null, null, null);
if (raw.moveToFirst()) {
    account = raw.getString(1);
}

Thanks in advance.

回答1:

The problem seems to be that, as you describe, you're updating the image http://developer.android.com/reference/android/content/ContentProviderOperation.html#newUpdate(android.net.Uri)

instead of inserting a new one http://developer.android.com/reference/android/content/ContentProviderOperation.html#newInsert(android.net.Uri)

If the contact doesn't has a previous image, it's impossible to update the field in the database because it doesn't exists. You should perform an insert operation instead.

It's debatable if the api method should fail hard throwing an exception at runtime.

Hope it helps.



回答2:

After some research as suggested I found an approach that works just fine.

https://stackoverflow.com/a/15145256/2423274

Here is the relevant part:

// Create new photo entry

int rawContactId = -1;
Cursor cursor = resolver.query(ContactsContract.RawContacts.CONTENT_URI, null, ContactsContract.RawContacts.CONTACT_ID + "=?", new String[] {id}, null);

if(cursor.moveToFirst()) {
    rawContactId = cursor.getInt(cursor.getColumnIndex(ContactsContract.RawContacts._ID));

    if(rawContactId > -1) {
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
                        .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photoBytes)
                        .build());
try {
    resolver.applyBatch(ContactsContract.AUTHORITY, ops);
} 
catch (Exception e) {
    e.printStackTrace();
}