大多数图片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没法改(吐槽一下,第三方sdk调用第三方sdk出了bug要人小命),没办法了安卓端自己解决吧,调试发现成功上传的华为手机上传的是uri是content://media/external/images/media/4444类型的而小米的是content://com.miui.gallery.open/raw/%2Fstorage%2Femul...类型的,而小米的这个Provider还是私有的没有开放权限(看报错大概是这个意思),于是就想着也将其转换成content://media/external/images/media类型的,谁知想尽了办法也无法做到大多数图片Uri无法获取文件的bug解决方案_第1张图片

第二天突发奇想既然是文件上传转成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()方法但是要做很多版本适配太麻烦了我没自己写,有类似需求的的可以自己百度下,另不要吐槽我的排版问题,我也不知道要怎么排版

你可能感兴趣的:(Android)