如何利用返回的Uri保存图片?GitHub背景移除库保存失败问题
通过Uri保存处理后的图片到本地存储
要把返回的Uri对应的图片保存到设备存储,你可以通过读取Uri对应的输入流,再写入到本地文件来实现。下面分两种场景给出适配不同Android版本的代码:
方案1:适配Android 10(API 29)及以上(推荐)
Android 10及以上推荐使用MediaStore保存图片,无需申请外部存储权限(针对媒体文件):
首先在onActivityResult的RESULT_OK分支中添加保存调用:
case Activity.RESULT_OK: Uri imageUri = CutOut.getUri(data); // 调用保存方法 saveImageToMediaStore(this, imageUri); Intent intent1=new Intent(BackgroundRemover.this,MainActivity.class); startActivity(intent1); break;
然后添加对应的保存方法:
private void saveImageToMediaStore(Context context, Uri sourceUri) { ContentResolver resolver = context.getContentResolver(); // 配置图片元数据 ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DISPLAY_NAME, "removed_bg_" + System.currentTimeMillis() + ".png"); values.put(MediaStore.Images.Media.MIME_TYPE, "image/png"); values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/CutOutImages"); // 插入到MediaStore获取目标Uri Uri targetUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); if (targetUri == null) return; try (InputStream inputStream = resolver.openInputStream(sourceUri); OutputStream outputStream = resolver.openOutputStream(targetUri)) { if (inputStream == null || outputStream == null) return; // 复制流完成保存 byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } // 通知系统图库更新 context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, targetUri)); } catch (IOException e) { e.printStackTrace(); // 保存失败,清理空记录 resolver.delete(targetUri, null, null); } }
方案2:Android 9(API 28)及以下(需权限)
如果要兼容低版本,需先申请WRITE_EXTERNAL_STORAGE权限:
- 在Manifest中添加权限声明:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
- 动态申请权限(可在启动CutOut前或保存前执行):
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); }
- 在
onActivityResult的RESULT_OK分支中添加保存逻辑:
case Activity.RESULT_OK: Uri imageUri = CutOut.getUri(data); // 权限校验后保存 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { saveImageToExternalStorage(this, imageUri); } Intent intent1=new Intent(BackgroundRemover.this,MainActivity.class); startActivity(intent1); break;
对应的保存方法:
private void saveImageToExternalStorage(Context context, Uri sourceUri) { File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File cutOutDir = new File(picturesDir, "CutOutImages"); if (!cutOutDir.exists()) { cutOutDir.mkdirs(); } File targetFile = new File(cutOutDir, "removed_bg_" + System.currentTimeMillis() + ".png"); ContentResolver resolver = context.getContentResolver(); try (InputStream inputStream = resolver.openInputStream(sourceUri); FileOutputStream outputStream = new FileOutputStream(targetFile)) { if (inputStream == null) return; // 复制流完成保存 byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } // 通知系统更新图库 MediaScannerConnection.scanFile(context, new String[]{targetFile.getAbsolutePath()}, null, null); } catch (IOException e) { e.printStackTrace(); } }
注意事项
- 若不确定图片格式,可根据实际情况修改MIME类型和文件后缀(如改为
.jpg)。 - 保存完成后通知系统图库更新,用户才能在图库中看到新图片。
内容的提问来源于stack exchange,提问作者Fawad
相关产品推荐
相关产品推荐

