I'm trying to load a Contact photo with URI "content://com.android.contacts/contacts/295" by using Glide.
When I use
Glide.with(context).load(Uri.parse(contactPhoto).into(imageview)
Glide gives me a 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)
Obviously Glide tries to get the image from the wrong place.
I would appreciate if someone point me on how to load a photo with "content://" URIs.
You need to create a custom loader that uses a ContentResolver. In Picasso for example this works because there is already a custom request handler that uses a ContentResolver.
I created one custom Glide loader for contacts for my internal use that you can take as reference.
Seems that Glide doesn't handle content photos Uri automatically.
So I've solved my issue using an RxJava approach.
Here is a method that emits a bitmap (Please notice the scheduler as it is important to not lag the scrolling performance)
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());
}
And here is the client code that uses the method (Please notice the unsubscribing as it is important in recycling).
if (holder.bitmapSubscription != null) {
holder.bitmapSubscription.unsubscribe();
}
holder.bitmapSubscription = _getConvertInputStreamToBitmapObservable(context.getContentResolver(),
contactUri)
.subscribe(holder.userImg::setImageBitmap);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With