openContactPhotoInputStream causes “java.lang.IllegalStateException: get field slot from row 0 col 0 failed”

六月ゝ 毕业季﹏ 提交于 2019-12-11 12:18:56

问题


Background

I'm trying to check if a contact image exists for a specific contact (and later to actually get it, much later). the query should be as minimal as possible and avoid un-needed memory usage.

I've figured out this probably isn't possible using the normal way, so for now I'm using:

final Uri lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, contactKey);
final Cursor contactCur = mContentResolver.query(lookupUri, new String[] { ContactsContract.Contacts._ID },
        null, null, null);
if (contactCur == null)
    return false;
contactCur.moveToFirst();
long contactId = 0;
if (contactCur.getCount() != 0)
    contactId = contactCur.getLong(contactCur.getColumnIndex(ContactsContract.Contacts._ID));
contactCur.close();
if (contactId == 0)
    return false;
final Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);

final InputStream inputStream;
if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH)
    inputStream = ContactsContract.Contacts.openContactPhotoInputStream(mContext.getContentResolver(),
            contactUri, bigPicture);
else
    inputStream = ContactsContract.Contacts.openContactPhotoInputStream(mContext.getContentResolver(),
            contactUri);
if (inputStream != null) {
    IOUtils.closeQuietly(inputStream);
    return true;
}
return false;

The problem

It seems like on some rare cases, devices return me an exception of :

java.lang.IllegalStateException: get field slot from row 0 col 0 failed at android.database.CursorWindow.getBlob_native(Native Method) at android.database.CursorWindow.getBlob(CursorWindow.java:288) at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:35) at android.database.CursorWrapper.getBlob(CursorWrapper.java:143) at android.provider.ContactsContract$Contacts.openContactPhotoInputStream(ContactsContract.java:1174)

as it turns out, there are plenty of reports on this issue, but not regarding "openContactPhotoInputStream" function.

from what I've read (for example here), it is caused since the blob that need to be read is too large, but in this case, I have this problem within Android's code...

The question

What's the best way to overcome this?

Is it possible it's a bug on Android?

My guess is that even if I use try-catch , when I try to get the image later I would get the same error, right?

How can I fix this?


回答1:


How about something like this for checking if a photo exists (untested):

ContentResolver cr = mContext.getContentResolver();
if (bigPicture && VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) {
    Uri displayPhotoUri = Uri.withAppendedPath(contactUri,
            ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
    AssetFileDescriptor fd = null;
    try {
        fd = cr.openAssetFileDescriptor(displayPhotoUri, "r");
    } catch (FileNotFoundException e) {}
    if (fd != null) {
        try {
            fd.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }
}

Uri photoUri = Uri.withAppendedPath(contactUri,
        ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = cr.query(photoUri, new String[] {BaseColumns._ID},
        ContactsContract.Contacts.Photo.PHOTO + " IS NOT NULL", null, null);
if (cursor == null) {
    return false;
}
try {
    return cursor.moveToFirst();
} finally {
    cursor.close();
}

And here is a modified version of the openContactPhotoInputStream() method, which should potentially be able to load a photo thumbnail with a size close to 1 MB without issues (again not tested):

public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri,
        boolean preferHighres) {
    if (preferHighres && VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) {
        Uri displayPhotoUri = Uri.withAppendedPath(contactUri,
                ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
        try {
            return cr.openAssetFileDescriptor(displayPhotoUri, "r").createInputStream();
        } catch (IOException e) {}
    }
    Uri photoUri = Uri.withAppendedPath(contactUri,
            ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
    try {
        return cr.openAssetFileDescriptor(displayPhotoUri, "r").createInputStream();
    } catch (IOException e) {}
    return null;
}

This should cause the ContactsProvider to read the thumbnail BLOB to shared memory, and send an AssetFileDescriptor pointing to it, from which we can directly open an InputStream.



来源:https://stackoverflow.com/questions/20932297/opencontactphotoinputstream-causes-java-lang-illegalstateexception-get-field-s

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