1. 程式人生 > >大多數圖片Uri無法獲取檔案的bug解決方案

大多數圖片Uri無法獲取檔案的bug解決方案

昨天公司前段找到自己問Android的內嵌頁<type="file">上傳有問題,公司之前的內嵌頁為了方便開發用了一個第三方的庫agentweb自己測試了下發現6.0的手機可以,但7.0及之上的不能上傳,於是升級了一一該庫的依賴到最新版本com.just.agentweb:agentweb:4.0.2的不能上傳,看了下是作者在4.0將檔案選擇拆分了,需要整合agentweb-filechooser才可以使用內嵌頁的檔案選擇,並且7.0及其之後的系統也支援了,但發現他開啟的檔案瀏覽器,最近之類的選項下無法找到圖片(ps:我們的前端限制了檔案的格式,第三方庫作者給的例子裡時I*/*型別,前端用的是image/png等等組合的)但是相簿下的選項還是可以使用上傳的,作為一個沒有追求的開發者就忽略了這個問題,開開心心的把bug點掉,表示自己解決了內嵌頁檔案上傳的問題,然而蛋疼的是自己心血來潮用公司的紅米4x測試了下,悲劇的是圖片上傳無法使用,然而把作者的示例運行了下發現同樣是紅米4x作者的demo可以用,於是旁敲側擊問前端是不是程式碼寫錯了吧坐著的檔案上傳示例發過去,結果前端用的阿里雲oss沒法改(吐槽一下,第三方對接第三方除了bug要人小命),沒辦法了安卓端自己解決吧,除錯發現成功上傳的華為手機上傳的是uri是

content://media/external/images/media/4444型別的而小米的是content://com.miui.gallery.open/raw/%2Fstorage%2Femul...型別的,而小米的這個Provider還是私有的沒有開放許可權(看報錯大概是這個意思),於是就想著也將其轉換成content://media/external/images/media型別的,誰知想盡了辦法也無法做到

第二天突發奇想既然是檔案上傳轉成file的檔案uri試試,結果果然可以了。。。

下面給出個工具類轉換content://型別的uri為file型別的

public class UriUtils {
    /**
     * 轉換uri陣列為file型別的uri陣列
     */
    public static void processUriArrayToFileUriArray(Context context, Uri[] uris) {
        if (uris == null) {
            return;
        }
        Uri[] uriArray = new Uri[uris.length];
        for (int i = 0; i < uris.length; i++) {
            uris[i] = getFileUri(context, uris[i]);
        }
    }

    /**
     * 轉換uri為file型別的uri
     */
    public static Uri getFileUri(final Context context, final Uri uri) {
        String realFilePath = getRealFilePath(context, uri);
        if (TextUtils.isEmpty(realFilePath)) {
            return null;
        }
        return Uri.fromFile(new File(realFilePath));
    }

    /**
     * 得到圖片uri的實際地址
     */
    public static String getRealFilePath(final Context context, final Uri uri) {
        if (null == uri) {
            return null;
        }
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }

}

嗯,其實能不能解決大多數uri不能使用的bug我也不知道,但是聯想到之前自己做原生頁面的檔案選擇時檔案上傳的uri也是這樣有的可以用有的不可以,但轉換成file:///型別的uri就可以了,就瞎編這個標題,大家不妨一試,content://型別的uri很容易出現系統適配問題

ps:內嵌頁實現檔案上傳重寫WebChromeClient的onShowFileChooser()方法但是要做很多版本適配太麻煩了我沒自己寫,有類似需求的的可以自己百度下,另不要吐槽我的排版問題,我也不知道要怎麼排版