在 ContactsContract 中更新照片的功能

Posted

技术标签:

【中文标题】在 ContactsContract 中更新照片的功能【英文标题】:Function to update a photo in ContactsContract 【发布时间】:2018-05-19 08:49:19 【问题描述】:

我尝试使用获取联系人 id 和图片 uri 的函数更新 ContactsContract 中的照片,但它似乎不起作用(并且我的函数返回 true)。

我真的不明白,因为代码看起来不错。

当联系人已经有照片时,它似乎正在工作......

这是我的功能:

boolean updatePhoto(String idStr, String uri)
        if (uri != null) 
            ArrayList<ContentProviderOperation> ops = new ArrayList<>();

            File imgFile = new File(uri.replace("file://", ""));
            if (imgFile.exists()) 

                Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                myBitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
                ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
                        .withSelection(ContactsContract.Data.CONTACT_ID + " = ?" + " AND " + ContactsContract.Data.MIMETYPE + "=?",
                                new String[]idStr, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, stream.toByteArray())
                        .build());

                try 
                    getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
                 catch(Exception e) 
                    e.printStackTrace();
                    return false;
                
            
        
        return true;
    

【问题讨论】:

【参考方案1】:

您的代码仅在联系人已有照片时才有效,因为您使用的是ContentProviderOperation.newUpdate,如果联系人没有照片,您将需要使用ContentProviderOperation.newInsert

您需要先查询该联系人是否有照片,然后更新/插入新照片:

private boolean hasPhoto(long contactId) 
    Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    InputStream input = Contacts.openContactPhotoInputStream(getContentResolver(), uri);
    if (input == null) 
        return false;
    
    Bitmap photo = BitmapFactory.decodeStream(input);
    return (photo != null);


private long getRawId(long contactId) 
    String selection = RawContacts.CONTACT_ID + "='" + contactId + "'";
    Cursor cur = contentResolver.query(RawContacts.CONTENT_URI, new String[] RawContacts._ID , selection, null, null);
    try 
        if (cur.moveToNext()) 
            return cur.getLong(0);
        
     finally 
        cur.close();
    
    return 0;


private boolean updatePhoto(long contactId, String uri) 
    if (uri == null) 
        // do nothing?
        return false;
    

    ContentProviderOperation.Builder builder;
    if (hasPhoto(contactId)) 
        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI);
        builder.withSelection(Data.CONTACT_ID + " = ?" + " AND " + Data.MIMETYPE + "=?",
                    new String[] String.valueOf(contactId), Photo.CONTENT_ITEM_TYPE);
     else 
        long rawId = getRawId(contactId);
        builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
        builder.withValue(Data.RAW_CONTACT_ID, rawId);
    

    builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
    builder.withValue(Data.IS_SUPER_PRIMARY, 1);
    builder.withValue(Data.IS_PRIMARY, 1);

    byte[] photo = getPhotoAsByteArray(uri); // to simplify the answer's code
    builder.withValue(Photo.PHOTO, photo);

    try 
        ArrayList<ContentProviderOperation> ops = new ArrayList<>();
        ops.add(builder.build());
        getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
     catch(Exception e) 
        e.printStackTrace();
        return false;
    
    return true;

【讨论】:

谢谢,但我也有同样的问题。当我的联系人没有照片时,它不起作用。当联系人有照片时,它就可以工作。 我还没有测试 hasPhoto 方法,它是否适合你,它是否进入 newInsert 子句? hasPhoto() 方法工作正常,因此它进入了 newInsert 子句。 当然...您不能将Data 行添加到Contact,您需要指定将包含该数据行的RawContact - 联系人是一个聚合或多个 RawContact,一个 RawContact 是一个或多个 Data 行的聚合 我找到了解决方案:我不必使用 builder.withValue(Data.CONTACT_ID, contactId);

以上是关于在 ContactsContract 中更新照片的功能的主要内容,如果未能解决你的问题,请参考以下文章

获取联系人照片

获取与 facebook for android 同步的联系人照片

以编程方式保存照片联系人 - Android

在 Kotlin 中查询 Androids ContactsContract

Android:尝试设置为 ImageView 时,联系人照片像素化

获取没有照片的电话联系人,以便将它们保存为 DataOutputStream(vcf 格式)