这是如何正确地将照片设置为通讯录上的联系人吗? [英] Is this how to correctly set a photo to a contact on the address-book?

查看:172
本文介绍了这是如何正确地将照片设置为通讯录上的联系人吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我已经通过使用通讯录上的一些查询找到了联系人.我执行了 此处 .

Suppose I've found a contact by using some query on the address book. Found it by performing a query to get contact info from a specific account (like of WhatsApp), as I've written here.

现在我有一张图片,希望用来更新联系人的照片.

Now I have an image that I wish to use it to update the contact's photo.

我已经基于在StackOverflow上找到的内容创建了代码,用于更新联系人照片.

I have created code based on things I've found here on StackOverflow, that update a contact photo.

事实是,一些用户声称它没有任何作用.我不确定是什么原因造成的.可能是访问联系人(id/lookup-key?)的不好方法.也许我需要获得一个额外的通讯簿字段.也许查询本身是错误的...

Thing is, some users claim it doesn't do anything. I'm not sure what causes it. Maybe bad way to access the contact (id/lookup-key?). Maybe I need to get an extra address-book field. Maybe the query itself is wrong...

我在找出此问题的原因时遇到了问题,因为我无法复制它,因此大多数用户也无法复制.

I'm having problems figuring out the reason for this issue, because I can't reproduce it and so does most of the users.

这就是我所做的:

        final ArrayList<ContentProviderOperation> ops = new ArrayList<>();
        final String lookupKey=...;
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            final byte[] photoByteArray = new byte[(int) file.length()];
            fileInputStream.read(photoByteArray);
            fileInputStream.close();
            final Builder builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI);
            builder.withSelection(Data.LOOKUP_KEY + "=?" + " AND " + Data.MIMETYPE + "=?", new String[]{lookupKey, Photo.CONTENT_ITEM_TYPE});
            builder.withValue(Photo.PHOTO, photoByteArray);
            ops.add(builder.build());
            file.delete();
        } catch (IOException e) {
            e.printStackTrace();
        }
        context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops )

问题

代码有什么问题吗?

The question

Is there anything wrong with the code?

我应该以其他方式更新联系人吗?

Should I update the contact differently?

为什么有些用户无法更新?查找键不够吗?可以更新错误的数据吗?

How come some users fail to update? Isn't the lookup-key enough? Can it update the wrong data?

我在某处阅读过可能需要使用RAW-contact-id的信息,但找不到确切的方法.查询,然后更新/插入?

I've read somewhere that I might need to use RAW-contact-ids, but couldn't find what to do exactly. Query and then update/insert?

有人建议开发人员应考虑使用其应用程序帐户来保存照片,而不是更新照片,因为这可能会引起问题.是真的吗

Someone has suggested that developers should consider using an account of their app to save photos, instead of updating, as it might cause issues. Is it true?

推荐答案

我在代码中看到了许多可能的问题:

I see a number of possible issues in the code:

  1. 您假设已为该联系人存储了一张现有照片(您正在使用newUpdate),如果当前没有照片,则应该使用newInsert.
  2. 您应该在特定的RawContact上进行更新/插入,编写的内容会更新Contact的RawContacts照片数据的所有原始数据,某些RawContacts可能具有只读状态,并且将不允许您的应用程序对其进行修改.
  3. 处理照片,尤其是在将照片存储到Contacts DB中时,这是一个非常占用内存的操作,对于某些设备,它可能会在OutOfMemoryError上崩溃,这是因为它们的RAM非常有限,或者由于当前其他人大量使用了内存.您应该使用try/catch包装包括applyBatch在内的整个代码,并捕获所有异常/错误,并将它们报告给日志,最好还报告给错误报告库(Firebase/crashlytics/etc)
  4. 您仅更新数据原始数据的PHOTO字段,还应该更新PHOTO_FILE_ID字段,因为某些应用程序可能选择读取PHOTO_FILE_ID并从中获取照片.
  5. 您未将新照片设置为其联系人的SUPER_PRIMARY,因此,如果同一联系人中的其他RawContact也有照片,则该照片可能会获胜",并成为该联系人的主要照片./li>
  1. You're assuming there's an existing photo stored for that contact (you're using newUpdate), in case there is not currently a photo, you should do newInsert instead.
  2. You should be updating/inserting on a specific RawContact, what you wrote updates all that Contact's RawContacts photo data raws, some RawContacts might have read-only status, and will not allow your app to modify it.
  3. Handling photos, especially when storing them into the Contacts DB is a very memory intense action, it might crash on OutOfMemoryError for some devices, either because they have very limited RAM or because the memory is currently heavily used by something else. You should wrap your entire code including the applyBatch with try/catch, and catch all Exceptions/Errors and report them to the log, and preferably to your error-reporting library as well (Firebase/crashlytics/etc)
  4. You're only updating the PHOTO field of the data raw, you should also update PHOTO_FILE_ID field, as some apps may choose to read the PHOTO_FILE_ID and get the photo from it instead.
  5. You're not setting your new photo as the SUPER_PRIMARY of its contact, so if some other RawContact in that same Contact also has a photo, it might "win", and be the primary photo for that contact.

下面的代码应该会有所帮助:

Here's code that should help:

// To simplify the code i didn't worry about try/catch, freeing resources, 
// or running slow queries on the main thread, make sure your code does!
public ContentProviderOperation setPhoto(int contactId, byte[] photoByteArray) {
    long rawId = getRawId(contactId);

    ContentProviderOperation.Builder builder;

    String selection = Data.RAW_CONTACT_ID + " = '" + rawId + "' AND " + Data.MIMETYPE + "= '" + Photo.CONTENT_ITEM_TYPE + "'";
    Cursor cur = contentResolver.query(Data.CONTENT_URI, new String[]{ Data._ID }, selection, null, null);
    if (cur.moveToFirst()) {
        // this RawContact already has a photo!
        Long photoDataId = cur.getLong(0);
        Uri uri = ContentUris.withAppendedId(Data.CONTENT_URI, photoDataId);
        builder = ContentProviderOperation.newUpdate(uri);
    } else {
        // this RawContact has no photo.
        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);

    builder.withValue(Photo.PHOTO, photoByteArray);
    builder.withValue(Photo.PHOTO_FILE_ID, null);

    return builder.build();
}

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;
}

这篇关于这是如何正确地将照片设置为通讯录上的联系人吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆