SQLiteException Unable to convert BLOB to string when contact have photo. Android

寵の児 提交于 2019-12-29 07:11:59

问题


In my code I update contact information including name, address, email, and photo. When contact have no photo all OK. But after assigning a photo for the contact I get android.database.sqlite.SQLiteException: unknown error: Unable to convert BLOB to string on each update operation.

My code for adding photo to contact

Bitmap bit =getBitmap();
                    ByteArrayOutputStream streamy = new ByteArrayOutputStream(); 
                    bit.compress(CompressFormat.PNG, 0, streamy); 
                    byte[] photo = streamy.toByteArray();

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

                    try {
                        if (getPhotoUri(rawContactId) != null) {
                            ContactHelper.context.getContentResolver().update(ContactsContract.Data.CONTENT_URI, values,
                                    String.format("%s = ?", ContactsContract.Data.RAW_CONTACT_ID), new String[] {String.format("%d", rawContactId)});
                        } else {
                            ContactHelper.context.getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }

My code to change contact name

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ops.add( ContentProviderOperation.newUpdate( Data.CONTENT_URI )
                .withSelection( Data.RAW_CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'",
                        new String[] { String.valueOf( rawContactId ) } )
                        .withValue( ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName() )                       
                        .build() );

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

回答1:


There is a nice little blog entry on ThinkAndroid that will show you how to do this: http://thinkandroid.wordpress.com/2009/12/30/handling-contact-photos-all-api-levels/

The core part is this:

public static void setContactPhoto(ContentResolver c, byte[] bytes, long personId) {
    ContentValues values = new ContentValues();
    int photoRow = -1;
    String where = ContactsContract.Data.RAW_CONTACT_ID + " = " + personId + " AND " + ContactsContract.Data.MIMETYPE + "=='" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
    Cursor cursor = c.query(ContactsContract.Data.CONTENT_URI, null, where, null, null);
    int idIdx = cursor.getColumnIndexOrThrow(ContactsContract.Data._ID);
    if (cursor.moveToFirst()) {
        photoRow = cursor.getInt(idIdx);
    }
    cursor.close();

    values.put(ContactsContract.Data.RAW_CONTACT_ID, personId);
    values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
    values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes);
    values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);

    if (photoRow >= 0) {
        c.update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data._ID + " = " + photoRow, null);
    } else {
        c.insert(ContactsContract.Data.CONTENT_URI, values);
    }
}

Basically, what you can’t just do is:

ContentValues values = new ContentValues();
values.put(ContactsContract.Data.RAW_CONTACT_ID, personId);
values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes.toByteArray());
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE );
context.getContentResolver().update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data.RAW_CONTACT_ID + " = " + personId, null);

And that’s because there are many rows where the RAW_CONTACT_ID = personId (there are data rows for the photo, phone numbers, emails, etc) and so trying this should give you some kind of SQLite exception along the lines of “CANNOT CONVERT BLOB TO STRING” and this makes sense as in this case you’re probably trying to update the phone number row with these bytes and so it’s throwing the appropriate error. Thus, in the first example, you need to begin by identifying which of these rows where RAW_CONTACT_ID = personId contains the BLOB value of the photo, and in the second query you want to set it in that row specifically. Now notice that sometimes photoRow may come back as -1. This basically tells us that no one has tried to set the photo or any other information before, and so we simply need to do a getContentResolver.insert(). Now, exactly why the behavior is different in these two cases, I don’t know. But the code above works, so once Google releases some better documentation maybe we’ll find out!



来源:https://stackoverflow.com/questions/15937983/sqliteexception-unable-to-convert-blob-to-string-when-contact-have-photo-androi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!