同一代码在两款App中异常:多图选择触发NumberFormatException崩溃
问题根源
崩溃是因为SiliCompressor内置的FileUtils.getPath()方法无法处理格式为msf:xxx的Content Uri——该方法试图将Uri的部分内容转换为Long类型,但字符串带有msf:前缀,导致抛出NumberFormatException。
这种情况通常发生在:
- 选择的图片来自第三方相册或特定系统文件选择器,返回了非标准格式的Uri
- 应用目标SDK版本较高,适配Scoped Storage后,传统路径解析逻辑失效
解决方案
方案1:替换路径解析逻辑,通过ContentResolver复制文件到本地缓存
避免直接解析Uri路径,改用ContentResolver将Uri对应的文件复制到应用缓存目录,再对本地文件进行压缩:
- 实现Uri转本地缓存文件的工具方法:
private File uriToCacheFile(Context context, Uri uri, String fileName) throws IOException { File cacheFile = new File(context.getCacheDir(), fileName); try (InputStream inputStream = context.getContentResolver().openInputStream(uri); OutputStream outputStream = new FileOutputStream(cacheFile)) { byte[] buffer = new byte[1024]; int readLength; while ((readLength = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, readLength); } } return cacheFile; }
- 修改原图片处理逻辑:
// 批量选择图片处理 for (int i = 0; i < countofImages; i++) { if (imageList.size() < 8) { Uri imageUri = result.getData().getClipData().getItemAt(i).getUri(); try { // 将Uri文件复制到本地缓存 File originalFile = uriToCacheFile(getContext(), imageUri, "origin_temp_" + i); // 压缩缓存中的原始文件 String compressedPath = SiliCompressor.with(getContext()) .compress(originalFile.getAbsolutePath(), new File(getContext().getCacheDir(), "temp" + i)); File compressedFile = new File(compressedPath); Uri compressedUri = Uri.fromFile(compressedFile); imageList.add(new CustomModel(getfilename(imageUri), compressedUri)); } catch (IOException e) { e.printStackTrace(); Toast.makeText(getContext(), "图片处理失败", Toast.LENGTH_SHORT).show(); } catch (NumberFormatException e) { e.printStackTrace(); Toast.makeText(getContext(), "无法识别该图片格式", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getContext(), "最多选择8张图片", Toast.LENGTH_SHORT).show(); break; // 避免重复提示 } }
方案2:使用SiliCompressor的Uri直接压缩API(如果支持)
检查SiliCompressor版本,若库提供了直接压缩Uri的方法(如compressUri()),可跳过路径解析步骤:
Uri imageUri = result.getData().getClipData().getItemAt(i).getUri(); File compressedFile = SiliCompressor.with(getContext()) .compressUri(imageUri, new File(getContext().getCacheDir(), "temp" + i)); Uri compressedUri = Uri.fromFile(compressedFile);
额外说明
两款应用表现不同的原因大概率是:其中一款测试场景中遇到了返回msf:格式Uri的文件选择器/相册,而另一款未覆盖该场景;或两者的目标SDK版本、设备系统版本存在差异,导致Uri解析逻辑的兼容性问题暴露程度不同。
内容的提问来源于stack exchange,提问作者Puru Chaudhary
相关产品推荐
相关产品推荐

