Android使用SiliCompressor压缩相册图片触发NumberFormatException问题
Android相册选图压缩触发NumberFormatException问题解决
问题场景
从相册选择单张/多张图片,使用SiliCompressor库压缩时抛出java.lang.NumberFormatException,错误提示为For input string: "msf:126968",触发代码为压缩图片的核心行:
File file = new File(SiliCompressor.with(getContext()).compress(FileUtils.getPath(getContext(), imageuri), new File(getContext().getCacheDir(), "temp" + i)));
报错原因
FileUtils.getPath(getContext(), imageuri)返回的不是图片的真实本地文件路径,而是msf:126968格式的MediaStore URI字符串。SiliCompressor的compress方法期望接收合法的文件路径,内部处理时会尝试将传入的字符串解析为数字(大概率是解析MediaStore资源ID),但msf:126968无法转成数字,因此抛出异常。
注:msf:开头的URI是Android 10及以上版本中MediaStore Files Provider的标识,这类URI无法直接映射到本地文件路径,旧的路径转换工具类(如FileUtils.getPath)对其处理完全失效。
解决方案
方案1:将URI对应的文件复制到临时文件后再压缩
先通过ContentResolver读取URI对应的文件内容,写入本地缓存的临时文件,再将临时文件路径传给SiliCompressor压缩:
- 新增临时文件转换方法:
private File getTempFileFromUri(Context context, Uri uri) throws IOException { InputStream inputStream = context.getContentResolver().openInputStream(uri); // 创建临时文件,后缀用jpg适配大多数图片格式 File tempFile = File.createTempFile("temp_album_img", ".jpg", context.getCacheDir()); try (FileOutputStream outputStream = new FileOutputStream(tempFile)) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } finally { if (inputStream != null) { inputStream.close(); } } return tempFile; }
- 修改压缩代码(以多选场景为例):
// 替换原压缩代码块 if (imageList.size() < 8) { imageuri = result.getData().getClipData().getItemAt(i).getUri(); try { File originalTempFile = getTempFileFromUri(getContext(), imageuri); // 压缩临时文件 File compressedFile = SiliCompressor.with(getContext()).compress( originalTempFile.getAbsolutePath(), new File(getContext().getCacheDir(), "temp" + i) ); // 压缩完成后删除临时原文件,节省缓存空间 originalTempFile.delete(); compresseduri = Uri.fromFile(compressedFile); imageList.add(new CustomModel(getfilename(imageuri), compresseduri)); } catch (IOException e) { e.printStackTrace(); Toast.makeText(getContext(), "图片压缩失败", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getContext(), "最多选择8张图片", Toast.LENGTH_SHORT).show(); }
方案2:使用SiliCompressor的URI压缩方法(推荐)
如果使用的SiliCompressor版本支持直接处理URI(需确认版本,部分新版本提供compressUri方法),可以直接传入URI进行压缩,省去路径转换步骤:
File compressedFile = SiliCompressor.with(getContext()).compressUri( imageuri, new File(getContext().getCacheDir(), "temp" + i) ); compresseduri = Uri.fromFile(compressedFile);
额外注意事项
- Android 10及以上版本推荐使用MediaStore API处理媒体文件,避免直接操作文件路径,适配Scoped Storage。
- 压缩完成后记得清理临时文件,防止占用过多缓存空间。
内容的提问来源于stack exchange,提问作者Puru Chaudhary
相关产品推荐
相关产品推荐

