簡體   English   中英

如何使用 Glide Android 加載帶有“content://”前綴的 URI?

[英]How to load a URI with “content://” prefix using Glide Android?

我正在嘗試使用 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 加載照片,我將不勝感激。

您需要創建一個使用 ContentResolver 的自定義加載器。 例如,在 Picasso 中,這是有效的,因為已經有一個使用 ContentResolver 的自定義請求處理程序

為我內部使用的聯系人創建了一個自定義Glide 加載器,您可以將其作為參考。

似乎 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);

為此,您需要使用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);
}

嘗試這個。 這應該有效。

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

我正在使用此代碼然后成功工作

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

最快和最簡單的方法是首先找出CONTACT_ID 然后將此CONTACT_IDPHOTO_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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM