5

我試圖通過使用Glide加載一個URI爲「content://com.android.contacts/contacts/295」的聯繫人照片。如何使用Glide Android加載帶「content://」前綴的URI?

當我使用

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

滑翔給了我一個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) 

顯然滑翔嘗試從錯誤的地方得到的圖像。

,如果有人點我就如何加載帶有照片我將不勝感激「的內容://」 URI的。

+0

https://github.com/bumptech/glide/issues/394 – TWiStErRob 2015-10-15 16:53:40

回答

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

是的,我知道有一個叫openContactPhotoInputStream方法。 但是,這將檢索主線程中的照片,我在適配器中調用Glide代碼,並希望它在後臺線程中處理獲取圖像。 – 2015-04-03 20:38:23

+0

我沒有使用該方法,因爲它在API 14下不起作用。而且我在這裏看不到問題; Glide不能比原生框架類更快。此外,Glide不保證自動處理任何'Uri'。 – 2015-04-03 20:41:19

+0

我得到'java.lang.IllegalArgumentException:無效列數據15'這是'公共靜態最終字符串PHOTO = DATA15'。使用API​​ 21. – 2016-04-15 13:11:15

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); 
2

您需要創建一個使用ContentResolver的自定義加載程序。 例如在畢加索,這是有效的,因爲存在使用ContentResolver的already a custom request handler

我創建一個自定義Glide loader for contacts for my internal use,你可以採取作爲參考。

+2

感謝您的回答,我已經向Glide提交了一個pull請求,該請求原生實現了此功能,我認爲它很快就會合並。 https://github.com/bumptech/glide/pull/1119 – 2016-04-13 08:58:16

+0

@ AhmedI.Khalil可否請你發佈一個例子嗎? – Mussa 2016-05-13 12:10:36

+2

https://github.com/bumptech/glide/issues/394功能請求現已解決,並將在Glide中以v3.8.0發佈。您必須等待v3.8.0,或者您可以將Glide源代碼(分支v3.0)作爲依賴項加入到您的項目中,並查看我編寫的這個示例。 https://github.com/bumptech/glide/blob/3.0/samples/contacturi/src/main/java/com/bumptech/glide/samples/contacturi/MainActivity.java – 2016-05-13 15:56:29

-1
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);