我正在尝试检查特定联系人是否存在联系人图像(稍后实际获取该联系人图像)。查询应该尽可能少,并避免不需要的内存使用。
我已经发现这可能是不可能使用正常方式,所以现在我正在使用:
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行col 0获取字段槽 在android.database.CursorWindow.getBlob_native(本机方法)失败 在android.database.CursorWindow.getBlob(CursorWindow.java:288)at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:35) 在android.database.CursorWrapper.getBlob(CursorWrapper.java:143)at android.provider.ContactsContract $ Contacts.openContactPhotoInputStream(ContactsContract.java:1174)
事实证明,有很多关于这个问题的报道,但不是关于“openContactPhotoInputStream”函数。
从我读过的内容(例如here),它是由于需要读取的blob太大而引起的,但在这种情况下,我在Android的代码中遇到了这个问题... < / p>
克服这个问题的最佳方法是什么?
这可能是Android上的一个错误吗?
我的猜测是,即使我使用try-catch,当我稍后尝试获取图像时,我也会得到同样的错误,对吧?
我该如何解决这个问题?
答案 0 :(得分: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
。