如何使用 Glide Android 加载带有“content://”前缀的 URI?

问题描述 投票:0回答:7

我正在尝试使用 Glide 加载带有 URI“content://com.android.contacts/contacts/295”的联系人照片。

当我使用时

Glide.with(context).load(Uri.parse(contactPhoto).into(imageview)

Glide 给了我一个 FileNotFoundException

java.io.FileNotFoundException: File does not exist; URI: content://com.android.contacts/contacts/264, calling user: android.uid.shared:10006, calling package is one of: [com.android.providers.contacts, com.android.contacts, com.android.providers.userdictionary]
        at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146)
        at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:689)
        at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1080)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:921)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:848)
        at com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher.loadResource(FileDescriptorLocalUriFetcher.java:21)
        at com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher.loadResource(FileDescriptorLocalUriFetcher.java:14)
        at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:44)
        at com.bumptech.glide.load.model.ImageVideoModelLoader$ImageVideoFetcher.loadData(ImageVideoModelLoader.java:83)
        at com.bumptech.glide.load.model.ImageVideoModelLoader$ImageVideoFetcher.loadData(ImageVideoModelLoader.java:53)
        at com.bumptech.glide.load.engine.DecodeJob.decodeSource(DecodeJob.java:170)
        at com.bumptech.glide.load.engine.DecodeJob.decodeFromSource(DecodeJob.java:128)
        at com.bumptech.glide.load.engine.EngineRunnable.decodeFromSource(EngineRunnable.java:122)
        at com.bumptech.glide.load.engine.EngineRunnable.decode(EngineRunnable.java:101)
        at com.bumptech.glide.load.engine.EngineRunnable.run(EngineRunnable.java:58)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)
        at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:52)

显然 Glide 尝试从错误的位置获取图像。

如果有人告诉我如何使用“content://”URI 加载照片,我将不胜感激。

android android-contentprovider android-contacts android-contentresolver android-glide
7个回答
3
投票

您需要创建一个使用 ContentResolver 的自定义加载程序。 例如,在 Picasso 中,这是可行的,因为已经有一个使用 ContentResolver 的自定义请求处理程序

我创建了一个自定义的

Glide loader 供我内部使用的联系人,您可以作为参考。


1
投票
似乎 Glide 不会自动处理内容照片 Uri。

所以我使用 RxJava 方法解决了我的问题。

这是一个发出位图的方法(请注意调度程序,因为不要滞后滚动性能很重要)

private Observable<Bitmap> _getConvertInputStreamToBitmapObservable(ContentResolver cr, Uri contactUri) { return Observable.create(new Observable.OnSubscribe<Bitmap>() { @Override public void call(Subscriber<? super Bitmap> subscriber) { InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(cr, contactUri); if (inputStream != null) { Bitmap bitmap = BitmapFactory.decodeStream(inputStream); subscriber.onNext(bitmap); } subscriber.onCompleted(); } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); }

这是使用该方法的客户端代码(请注意取消订阅,因为它在回收中很重要)。

if (holder.bitmapSubscription != null) { holder.bitmapSubscription.unsubscribe(); } holder.bitmapSubscription = _getConvertInputStreamToBitmapObservable(context.getContentResolver(), contactUri) .subscribe(holder.userImg::setImageBitmap);
    

0
投票
为此,您需要使用

ContentResolver

ContentResolver contextResolver = context.getContentResolver(); Uri uri = Uri.parse("content://com.android.contacts/contacts/295"); Bitmap thumbnail = null; Cursor cursor = contentResolver.query(uri, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); try { if (cursor.moveToFirst()) { final byte[] thumbnailBytes = cursor.getBlob(0); if (thumbnailBytes != null) { thumbnail = BitmapFactory.decodeByteArray(thumbnailBytes, 0, thumbnailBytes.length); } } } finally { cursor.close(); } if (thumbnail != null) { imageView.setImageBitmap(thumbnail); }

试试这个。这应该有效。


0
投票
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, new Long(contactsPojo.getId())); final Uri displayPhotoUri = Uri.withAppendedPath(uri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO); Glide.with(context) .load(displayPhotoUri) .placeholder(R.mipmap.ic_launcher) .error(R.mipmap.ic_launcher) .fallback(R.mipmap.ic_launcher) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(holder.image);
    

0
投票
我正在使用此代码然后工作成功

Glide.with(context) .load(uri) .addListener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { Log.i(TAG, "onLoadFailed: "); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { Log.i(TAG, "onResourceReady: "); return false; } }) .into(holder.imgProfile);
    

0
投票
最快最简单的方法是先找出

CONTACT_ID

。然后将这个 
CONTACT_ID
PHOTO_URI
 进行匹配。

//first create a cursor val photoCursor = contentResolver.query( ContactsContract.Contacts.CONTENT_URI, photoProjection, ContactsContract.Contacts._ID + "=?", arrayOf(contactId), null ) //where photoProjection is like so val photoProjection: Array<String> = arrayOf( ContactsContract.Contacts.Photo.PHOTO_URI, ContactsContract.Contacts._ID ) //now grab the PHOTO_URI, this will only exist if there is a photo val photo = if (photoCursor?.moveToFirst() == true) { photoCursor.getString(photoCursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)) } else { null } //In Glide now you can load the URI directly Glide.with(this) .load(uri) .apply(imageTransform) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) .into(image)
    

0
投票
数据绑定时,这些都不起作用。

为了捕获该

FileNotFoundException

(这可能会严重影响日志)或用默认图像替换丢失的图像,必须确保该图像存在,
在使用Glide传递Uri之前

XML 看起来像这样:

<QuickContactBadge android:layout_width="48dp" android:layout_height="48dp" android:scaleType="center" app:imageUrl="@{ item.thumbnail }"/>
默认数据绑定组件的伴生对象:

companion object { val LOG_TAG: String = SomeFragment::class.java.simpleName /** DataBinding the QuickContactBadge. */ @BindingAdapter("imageUrl") fun loadImage(imageView: ImageView, uri: Uri?) { if (uri != null && uriWouldResolve(imageView.context, uri)) { Glide.with(imageView.context).load(uri).into(imageView) } else { // TODO: optionally load default image. } } /** Reduce Log Spam. */ private fun uriWouldResolve(context: Context, uri: Uri): Boolean { var exists = false try { val ins: InputStream? = context.contentResolver.openInputStream(uri) if (ins?.read()!! > 0) {exists = true} ins.close() } catch (e: FileNotFoundException) { Log.w(LOG_TAG, "file not found: ${e.message}") } return exists } }
    
© www.soinside.com 2019 - 2024. All rights reserved.