问题
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