欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

大多数图片Uri无法获取文件的bug解决方案

程序员文章站 2024-02-14 16:36:16
...

昨天公司前段找到自己问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类型的,谁知想尽了办法也无法做到大多数图片Uri无法获取文件的bug解决方案

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