通过Android中的PHOTO_FILE_ID将联系人的图像更改为大照片


问题内容

这似乎适用于小图像:

ContentValues values = new ContentValues();

values.put(ContactsContract.Data.RAW_CONTACT_ID, id);
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);
if (photoRow >= 0) {
    context.getContentResolver().update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data._ID + " = " + photoRow, null);
} else {
    context.getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
}

文档中我意识到,对于大图像,我需要设置PHOTO_FILE_ID,因此我可以替换:

ContactsContract.CommonDataKinds.Photo.PHOTO

与:

ContactsContract.CommonDataKinds.Photo.PHOTO_FILE_ID

但是,然后我需要提供一个PHOTO_FILE_ID而不是原始数据。我的问题:

  1. 如何保存照片(字节[])并获取PHOTO_FILE_ID?
  2. 如果已经有可用的照片(PHOTO不是PHOTO_FILE_ID)。我需要删除它才能看到大图像,还是要优先处理大图像?如果没有,如何删除?

问题答案:

您自己的答案会奏效,但效率不高,因为需要将照片编码为SQL查询并通过Android
IPC传输。这也使它受制于Android的IPC大小限制1MB(即,如果您的照片太大,则内容提供商操作将失败)。

设置(创建或覆盖)RawContact的(主)照片的最有效方法是使用openAssetFileDescriptor和这样的
ContactsContract.RawContacts.DisplayPhoto
URI(例如,从Android文档复制的示例):

public void writeDisplayPhoto(long rawContactId, byte[] photo) {
    Uri rawContactPhotoUri = Uri.withAppendedPath(
            ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
            RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
    try {
        AssetFileDescriptor fd =
            getContentResolver().openAssetFileDescriptor(rawContactPhotoUri, "rw");
        OutputStream os = fd.createOutputStream();
        os.write(photo);
        os.close();
        fd.close();
    } catch (IOException e) {
        // Handle error cases.
    }
}

这种方法的唯一缺点是,它总是创建/替换的主要照片RawContact。如果RawContact还没有照片,它将添加一张。

不幸的是没有办法用openAssetFileDescriptorPHOTO_FILE_ID,所以你不能覆盖使用这种方法的ID标识的特定照片。但是,在现实生活中,大多数联系人最多只能有一张照片,所以这并不是一个真正的限制。

这将自动Photo.PHOTO使用大照片的缩略图更新列,并分配一个PHOTO_FILE_ID