1

我的应用程序中有一个代码可以获取联系人的 URI,然后通过尝试打开照片的输入流来验证联系人是否有照片,获取照片的 URI 并对其进行解码。

很少,我得到一个奇怪的异常,即 URI 不存在。我得到一个不存在的照片文件的 URI。

获取照片 URI:

// Get Uri to the contact
Uri contact = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,
        c.getInt(c.getColumnIndex(PhoneLookup._ID)));

// Get input stream of the photo
InputStream is = Contacts.openContactPhotoInputStream(context.getContentResolver(), contact);
// If no input stream (then there is no photo of contact), return 'null' instead of photo Uri
if (is == null) {
    Log.d(TAG, "No photo");
    return;
}

// Get display photo Uri of the contact
Uri photoUri = Uri.withAppendedPath(contact, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);

此时,当一个联系人没有照片时,is获取null并返回。但很少,photoUri得到content://com.android.contacts/contacts/303/display_photo

现在对其进行解码(在其他功能中):

InputStream isPhoto = context.getContentResolver().openInputStream(photoUri);

从这一行抛出的异常是:

java.io.FileNotFoundException: No photo file found for ID 0
    at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146)
    at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:617)
    at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:717)
    at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:614)
    at android.content.ContentResolver.openInputStream(ContentResolver.java:449)
    at com.app.android.utils.ImageUtils.decodeBitmapFromPhotoUri(ImageUtils.java:39)
    ...

内容解析器怎么可能给我一张不存在的照片的URI(联系人存在并且肯定没有照片)而不是返回null

更新:我看到它只发生在不是由设备拍摄的照片上(比如从谷歌帐户收到的照片或从互联网下载的照片)。

4

2 回答 2

3

改变获取照片输入流的方式后,一切正常。

代替:

InputStream isPhoto = context.getContentResolver().openInputStream(photoUri);

我用了:

InputStream photoInputStream =
    Contacts.openContactPhotoInputStream(context.getContentResolver(), contactUri);

注意:现在 Uri 是联系人而不是他的照片。

于 2013-05-23T09:02:08.717 回答
0

在遵循ContactsContract.Contacts.Photo中的示例时,我遇到了与您尝试使用时相同的异常openDisplayPhoto

    public InputStream openDisplayPhoto(long contactId) {
    Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,
            contactId);
    Uri displayPhotoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo
            .DISPLAY_PHOTO);
    try {
        AssetFileDescriptor fd =
                getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
        return fd.createInputStream();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

使用时效果很好openPhoto(实际上是缩略图):

    public InputStream openPhoto(long contactId) {
    Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,
            contactId);
    Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo
            .CONTENT_DIRECTORY);
    Cursor cursor = getContentResolver().query(photoUri,
            new String[]{ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
    if (cursor == null) {
        return null;
    }
    try {
        if (cursor.moveToFirst()) {
            byte[] data = cursor.getBlob(0);
            if (data != null) {
                return new ByteArrayInputStream(data);
            }
        }
    } finally {
        cursor.close();
    }
    return null;
}

实际上,例如,当联系人图片来自 Google+ 时,它只能作为缩略图使用,而不能作为正常的全尺寸图片使用。

于 2016-02-06T09:37:11.853 回答