openContactPhotoInputStream导致“java.lang.IllegalSta

2019-10-19 04:44发布

背景

我想检查是否有接触式图像存在一个特定的联系人(后来真正得到它,更晚)。 查询应尽可能最小,避免非必要的内存使用情况。

我已经想通了,这可能是不可能用正常的方式,所以现在我使用:

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;

问题

这似乎是在极少数的情况下,设备返回我的一个例外:

java.lang.IllegalStateException:从0行山坳0获得磁场槽在android.database.CursorWindow.getBlob(CursorWindow.java:288)在android.database.AbstractWindowedCursor.getBlob未能在android.database.CursorWindow.getBlob_native(本机方法) (AbstractWindowedCursor.java:35)在android.database.CursorWrapper.getBlob(CursorWrapper.java:143)在android.provider.ContactsContract $ Contacts.openContactPhotoInputStream(ContactsContract.java:1174)

事实证明,有很多关于这个问题的报告,但没有关于“openContactPhotoInputStream”功能。

从我读过(例如这里 ),这是因为造成需要被读取BLOB太大,但在这种情况下,我有Android的代码中这个问题...

问题

什么是克服这一点的最好方法是什么?

是否有可能是Android上的错误吗?

我的猜测是,即使我用的try-catch,当我试图让图像后,我会得到相同的错误,对吧?

我怎样才能解决这个问题?

Answer 1:

如何像这样的检查,如果存在照片(未经测试):

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

这里是修改后的版本openContactPhotoInputStream()方法,这应该有可能能够加载照片缩略图的大小接近1 MB没有问题(再次未测试):

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

这应该引起ContactsProvider读取缩略图BLOB到共享内存,并发送AssetFileDescriptor指着它,从中我们可以直接打开InputStream



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