天天看点

android10加载图片问题解决思路全程记录 FileNotFoundException: /content:/media/external/images

在网上找到一段代码跑在android 10上,加载相册图片失败该怎么解决?

1、首先确认已经给了相应权限

2、跟踪加载图片的代码

Cursor cursor = getApplicationContext().getContentResolver()
                    .query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
                            null, null, MediaStore.Images.Media.DATE_ADDED);
           

打印日志发现这个写法正确、可以获取6张图片,既然读取图片没有问题,那就继续往下

3、看显示图片的代码

Glide.with(context)
                .load(arrayList.get(position).cover)
                .placeholder(R.drawable.image_placeholder).centerCrop().into(viewHolder.imageView);
           

原来用的是Glide加载,那为什么不行呢?网络搜索下 Android 10 Glide,找到结果如下

https://github.com/bumptech/glide/issues/3896 核心内容如下

issue:
on Android 10 , Glide failed to load image from local storage.

fix for above issue
android:requestLegacyExternalStorage="true"
           

就是说在application加入android:requestLegacyExternalStorage="true"就可以解决

4、requestLegacyExternalStorage

进一步查询这个requestLegacyExternalStorage的作用,你就会知道更底层一些的知识。

#######################################

再说一个错误

FileNotFoundException: /content:/media/external/images

参考文章

https://blog.csdn.net/dickyqie/article/details/105120866

https://stackoverflow.com/questions/6935497/android-get-gallery-image-uri-path

https://stackoverflow.com/questions/3401579/get-filename-and-path-from-uri-from-mediastore

https://zhuanlan.zhihu.com/p/128558892

简单分析下

高版本采用MediaStore来管理文件、增删改查都可以用这个。说一个常见的应用场景,那就是读取手机相册里面的图片。我们调用相册读取的图片路径是一个uri,类似这样子的

我们需要先转为图片真实的路径才可以读取。图片真实的路径长什么样?

/storage/emulated/0/DCIM/Camera/394210ccb4c70757ee9e74da852f6c65.jpg
           

那怎么转换呢,这时候就要用到MediaStore帮助我们。简单说,MediaStore就是一个文件数据库,手机上的文件都记录在这个库里。我们看转换代码

public static String getRealPathFromURI(Context context, Uri contentUri) {
        Cursor cursor = null;
        try {
            String[] proj = { MediaStore.Images.Media.DATA };
            cursor = context.getContentResolver().query(contentUri,  proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }

        finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
           

网上其他资料一般到这里就完了,但是我这么写了,还是取不到。进一步研究发现,MediaStore在获取文件的时候需要用到provider,在application需要添加如下代码

<provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true"
            tools:replace="android:authorities">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>