天天看點

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>