You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用返回的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权限:

  1. 在Manifest中添加权限声明:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
  1. 动态申请权限(可在启动CutOut前或保存前执行):
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:15:27