AndroidUtilCode icon indicating copy to clipboard operation
AndroidUtilCode copied to clipboard

Uri转换

Open Lexiaoy opened this issue 3 years ago • 3 comments

Android版本大于10时,选择文件后使用返回的Uri通过UriUtils.uri2File转为文件路径后,会丢失原文件名称和后缀,建议使用原文件名称

Lexiaoy avatar Feb 18 '22 06:02 Lexiaoy

+1,我也遇到一样的问题,使用以下方法代替


/** * Android 10 以上适配 * @param context * @param uri * @return */ @RequiresApi(api = Build.VERSION_CODES.Q) private static String uriToFileApiQ(Context context, Uri uri) { File file = null; //android10以上转换 if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) { file = new File(uri.getPath()); } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { //把文件复制到沙盒目录 ContentResolver contentResolver = context.getContentResolver(); Cursor cursor = contentResolver.query(uri, null, null, null, null); if (cursor.moveToFirst()) { @SuppressLint("Range") String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); try { InputStream is = contentResolver.openInputStream(uri); File cache = new File(context.getExternalCacheDir().getAbsolutePath(), Math.round((Math.random() + 1) * 1000) + displayName); FileOutputStream fos = new FileOutputStream(cache); android.os.FileUtils.copy(is, fos); file = cache; fos.close(); is.close(); } catch (IOException e) { e.printStackTrace(); } } } return file.getAbsolutePath(); }

CrazyDoraemon avatar Feb 21 '22 08:02 CrazyDoraemon

也贡献点自己的力量,当我将api提到30的时候,使用系统文件夹获取文件Uri,经测试,可以直接以Uri进行上传转inputStream上传,但如果需求上传之后又需要打开文件(类似聊天im的文件上传),在不申请特殊权限的情况下,我使用的是将文件copy到沙盒的方式,下面提供下 @CrazyDoraemon 的代码改造,不需要限制andorid10以上能用,以及对方法进行简单拓展

    public static File uriToFileApi(Context context, Uri uri) {
        File file = null; //android10以上转换
        if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
            file = new File(uri.getPath());
        } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { //把文件复制到沙盒目录
            ContentResolver contentResolver = context.getContentResolver();
            Cursor cursor = contentResolver.query(uri, null, null, null, null);
            if (cursor.moveToFirst()) {
                @SuppressLint("Range")
				String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                try {
                    InputStream is = contentResolver.openInputStream(uri);
                    //先判断当前文件夹是否有该文件
                    String dir =context.getExternalCacheDir().getAbsolutePath()+"/kyl_file_cache";
                    FileUtils.createOrExistsDir(dir);
                    File cache = new File(dir, displayName);
                    if(FileUtils.isFileExists(cache)){
                        //如果存在,说明已经写入过了,那么判断hash值是不是一样
                         int oldHash = Arrays.hashCode(FileUtils.getFileMD5(context, uri));
                         int newHash = Arrays.hashCode(FileUtils.getFileMD5(cache));
                        Timber.i("通过hash值判断文件是否相同:%s  -  %s   = %s",oldHash,newHash,oldHash-newHash);
                         if(newHash==oldHash){
                             return cache;
                         }else {
                             // 时间原因,简单拓展,重复覆盖的几率较小,后续如果有必要,可以数字递增
                             cache=new File(context.getExternalCacheDir().getAbsolutePath(), Math.round((Math.random() + 1) * 1000) +displayName);
                         }
                    }

                    FileOutputStream fos = new FileOutputStream(cache);
//                    android.os.FileUtils.copy(is, fos);
                    UtilsBridge.writeFileFromIS(cache.getAbsolutePath(), is);
                    file = cache;
                    fos.close();
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    file=null;
                }
            }
        }
        return file;
    }

以上部分工具都是该库的工具类,请自行查找

AreYReady avatar Mar 15 '22 03:03 AreYReady