使用“content://"显示来自 URI 的图像在 Android Q 上使用 Glide 的方案 [英] Display image from URI with "content://" scheme with Glide on Android Q

查看:23
本文介绍了使用“content://"显示来自 URI 的图像在 Android Q 上使用 Glide 的方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

之前有人问过有关 Android Q 和 Glide 的问题,但我无法将它们放在一起,所以我希望有人愿意提供帮助.

Questions around Android Q and Glide have been asked before but I'm not able to put them all together, so I hope someone is willing to help.

我正在将从云 (Firebase) 下载或从图库中选择或使用相机拍摄的图像保存到本地存储.我曾经将它保存在应用程序的文件夹中,并且可以将其添加到图库中,但是对于 Android Q,这不再可能.所以我改变了我的应用程序以使用 MediaStore 和 ContentResolver 来访问文件并保存它.文件保存在MediaStore.Images.Media.EXTERNAL_CONTENT_URIPictures目录下.

I'm saving images, downloaded from the cloud(Firebase) or chosen from gallery or taken with the camera, to local storage. I used to save it in the app's folder and could add it to the gallery, but with Android Q that is not possible anymore. So I changed my app to use the MediaStore and ContentResolver to access files and save it. Files are saved in the Pictures directory of MediaStore.Images.Media.EXTERNAL_CONTENT_URI.

存储处理器:

public Uri createUriForFile(String fileName, String parentId)
{
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
    {
        Uri uriFromContentResolver = getUriFromContentResolver(fileName);
        if(uriFromContentResolver != null)
        {
            return uriFromContentResolver;
        }else
        {
            ContentResolver resolver = baseActivity.getApplicationContext().getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
            contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
            contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, EXTERNAL_PICTURE_RELATIVE_PATH);
            return resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        }
    }else {
        File pictureFile  = new File( EXTERNAL_PICTURE_STORAGE_DIR.getAbsolutePath() + File.separator + parentId + File.separator + fileName );
        checkAndCreatePictureDir(parentId);
        return FileProvider.getUriForFile(baseActivity, baseActivity.getApplicationContext().getPackageName() + ".fileprovider", pictureFile);
    }
}

public Uri getUriFromContentResolver(String fileName)
{
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
    {
        ContentResolver resolver = baseActivity.getApplicationContext().getContentResolver();

        Cursor queryCursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media.DISPLAY_NAME,
                        MediaStore.Images.Media.RELATIVE_PATH}, MediaStore.Images.Media.DISPLAY_NAME + "=? ",
                new String[]{fileName}, null);

        if (queryCursor != null && queryCursor.moveToFirst())
        {
            Uri content = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon().appendEncodedPath(queryCursor.getString(queryCursor.getColumnIndex(MediaStore.Images.Media.RELATIVE_PATH)))
                    .appendPath(queryCursor.getString(queryCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME))).build();
            return content;
        } else
        {
            return null;
        }
    }else
    {
        return null;
    }

它将文件保存到存储中,可以使用 Android Studio 中的设备资源管理器查看.它也被上传到云端,可以从那里查看(如果它是一个新文件).但是当我尝试使用 Glide 将它加载到 ImageView 时,它给了我一个错误:java.lang.UnsupportedOperationException: Unknown or unsupported URL: content://.我似乎无法弄清楚为什么.它曾经可以工作,并且 URI 应该是正确的,因为它也用于其他地方(上传文件、保存文件等)并且可以正常工作.Glide/我的代码有什么问题?

It saves the file to the storage, it can be seen with the Device Explorer in Android Studio. It is also uploaded to the cloud and can be viewed from there(if it is a new file). But when I'm trying to load it into a ImageView with Glide, it gives me an error: java.lang.UnsupportedOperationException: Unknown or unsupported URL: content://. And I can't seem to figure out why. It used to work and the URI should be correct as it is used on other places as well(uploading the file, saving the file, etc.) and it works. What is the problem with Glide/my code?

完全错误:

E/GlideExecutor: Request threw uncaught throwable
java.lang.UnsupportedOperationException: Unknown or unsupported URL: content://media/external/images/media/Pictures/**AppName**/IMG20200112164646.jpg
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
    at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:151)
    at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:705)
    at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1687)
    at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1503)
    at android.content.ContentResolver.openInputStream(ContentResolver.java:1187)
    at com.bumptech.glide.load.data.StreamLocalUriFetcher.loadResourceFromUri(StreamLocalUriFetcher.java:85)
    at com.bumptech.glide.load.data.StreamLocalUriFetcher.loadResource(StreamLocalUriFetcher.java:60)
    at com.bumptech.glide.load.data.StreamLocalUriFetcher.loadResource(StreamLocalUriFetcher.java:15)
    at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:44)
    at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:62)
    at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:302)
    at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:272)
    at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:233)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:919)
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:446)

推荐答案

你的 getUriFromContentResolver() 是错误的.查询 _ID,然后使用 ContentUris.withAppendedId() 组合要使用的 Uri.

Your getUriFromContentResolver() is wrong. Query for the _ID, then use ContentUris.withAppendedId() to assemble the Uri to use.

例如,在 这个示例应用中,来自<一本 href="https://commonsware.com/Q" rel="nofollow noreferrer">这本书,我用的:

For example, in this sample app from this book, I use:

  suspend fun getLocalUri(filename: String): Uri? =
    withContext(Dispatchers.IO) {
      val resolver = context.contentResolver

      resolver.query(collection, PROJECTION, QUERY, arrayOf(filename), null)
        ?.use { cursor ->
          if (cursor.count > 0) {
            cursor.moveToFirst()
            return@withContext ContentUris.withAppendedId(
              collection,
              cursor.getLong(0)
            )
          }
        }

      null
    }

其中 PROJECTIONQUERY 是:

private val PROJECTION = arrayOf(MediaStore.Video.Media._ID)
private const val QUERY = MediaStore.Video.Media.DISPLAY_NAME + " = ?"

以及 collection 在哪里:

  private val collection =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) MediaStore.Video.Media.getContentUri(
      MediaStore.VOLUME_EXTERNAL
    ) else MediaStore.Video.Media.EXTERNAL_CONTENT_URI

(在我的例子中,我正在查询视频;你可以使用 MediaStore.Images 代替)

(in my case, I am querying videos; you would use MediaStore.Images instead)

这篇关于使用“content://"显示来自 URI 的图像在 Android Q 上使用 Glide 的方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆