当前位置: 首页 > 知识库问答 >
问题:

OpenConrectPhotoInputStream导致"java.lang.IllegalStateExcture:从行0中获取字段插槽失败"

董弘新
2023-03-14

我正在尝试检查是否存在特定联系人的联系人图像(稍后才能实际获取,更晚)。查询应尽可能少,并避免不必要的内存使用。

我发现用常规方法可能无法做到这一点,所以现在我使用:

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:在android.database.CursorWindow.getBlob_native(本机方法)在android.database.CursorWindow.getBlob(CursorWindow.java:288)在android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:35)在android.database.CursorWrapper.getBlob(CursorWrapper.java:143)从第0行获取字段槽失败在android.provider.ContactsContract$Contacts.openContactPhotoInputStream(ContactsContract.java:1174)

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

从我所读到的(例如这里),这是因为需要读取的blob太大,但在这种情况下,我在Android代码中遇到了这个问题。。。

克服这个问题的最好方法是什么?

这可能是Android系统上的一个bug吗?

我的猜测是,即使我使用try-catch,当我稍后尝试获取图像时,我也会得到相同的错误,对吗?

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

共有1个答案

宇文念
2023-03-14

像这样检查照片是否存在(未测试)如何:

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()方法的一个修改版本,该方法可能能够加载大小接近1MB的照片缩略图,而不会出现问题(同样未经测试):

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

这应该会导致ConrectsProvider读取缩略图BLOB到共享内存,并发送指向它的AssetFiledescription ptor,从中我们可以直接打开一个InputStream

 类似资料:
  • 我想从我的数据库中选择值,但我得到了错误 我不知道我的代码哪里错了。。这是我在dbHelper中的代码。 我想在其他类中得到值。我使用这个代码。 有人能帮我吗?我真的需要解决办法,请帮帮我。。谢谢当做

  • 这是一段相关的代码: 我得到以下例外情况: 第81行第0列第0列的IllegalStateExceptionget字段插槽失败。 如果查询没有返回任何结果(即moveToFirst()为什么为true),有人能解释为什么到达第81行吗?或者有没有其他的解释来解释这个例外? 编辑添加:Android留档在Cursor.moveToFirst()(http://developer.android.co

  • 问题内容: 我想编写一个函数,为插入的行返回一列的值(在这种情况下为自动递增的主键)。 本质上,我想插入一些新数据,生成一个新的主键,然后获取该键。我可以简单地在表中查找最高的主键,但是有可能其他人也可以运行该函数,并且我可以返回错误的键,对吗? 解决这个问题的最简单方法是什么? 问题答案: 正如评论中指出的那样,来自MySQL文档: 该函数不受竞争条件的影响,因为它在特定于您的连接的MySQL中

  • 问题内容: 我正在使用bit(1)字段来存储布尔值,并使用PDO准备好的语句将其写入表中。 这是测试表: 这是测试代码: 运行该代码会在TestBool下为我提供一行值1。和使用bindValue()和bindParm()一样。我也尝试了命名占位符(而不是?),结果相同。 然后我尝试了: 哪个工作正常(TestBool的值为0)。将SQL直接打入MySQL也可以。 请注意,插入1始终有效。 那么,

  • 我已经建立了一个字段声明列表,需要找出每个字段的名称: 我找不到任何检索字段名称的方法。 奇怪的是,其中一个构造函数确实接受一个字段参数,所以不确定为什么它没有getter。我需要从另一个节点获取它吗? FieldDeclaration(节点列表修饰符、类型、字符串名称)创建一个FieldDeclaration。https://www.javadoc.io/doc/com.github.javap

  • 问题内容: 我有选择: 但这仅在返回一个值。如果没有返回任何内容。如何获得没有任何申请的“候选人”? 有表格“候选人”。 如果候选人没有应用程序或不存在,我需要得到0。 编辑 我现在有了: 它完美地工作。但是有可能写得更简单还是最好的解决方案?我应该创建任何索引吗? 问题答案: 您需要在PostgreSQL中使用COALESCE函数http://developer.postgresql.org/p