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

如何在Yalantis UCrop中加载指定图片而非从相册选择

安卓UCrop裁剪:用已知Uri/Bitmap替代相册选择逻辑

我正在开发一款安卓计时管理应用,需对图片执行OCR识别,希望先通过Yalantis UCrop裁剪图片。目前已选定目标图片,可获取其相关信息,但现有代码需从相册选择图片,且裁剪后的Uri经过修改,无法获取所需的原图信息。请问如何使用已知的Uri或Bitmap替代代码中mGetContent.launch("image/*")的相册选择逻辑?


现有主Activity代码

ActivityResultLauncher<String> mGetContent;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ActivityResultLauncher<String> mGetContent=registerForActivityResult(new ActivityResultContracts.GetContent(), result -> {
        Intent intent= new Intent(this, CropperActivity.class);
        intent.putExtra("DATA", result.toString());
        startActivityForResult(intent, 101);
    });

    mGetContent.launch("image/*");
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Log.v("onActivityResult", "requestCode: " + requestCode);
    Log.v("onActivityResult", "resultCode: " + resultCode);

    if (requestCode == 101 && resultCode == -1 && data != null) {
        Uri selectedImage = data.getData();
        imgCap.setImageURI(selectedImage);
        //getOCR(selectedImage.toString());
    } else {
        Log.e("capture error", "error: no image!!!!!!!");
    }
}

CropperActivity代码

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.yalantis.ucrop.UCrop;
import com.yalantis.ucrop.model.AspectRatio;

import java.io.File;
import java.util.UUID;

public class CropperActivity extends AppCompatActivity {

    String result;
    Uri fileUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.v_cropper);

        readIntent();

        String dest_uri= UUID.randomUUID().toString() + ".jpg";

        UCrop.Options options=new UCrop.Options();
        options.setAspectRatioOptions(3,
                new AspectRatio("1:1", 1, 1),
                new AspectRatio("2:1", 2, 1),
                new AspectRatio("3:1", 3, 1),
                new AspectRatio("5:1", 5, 1),
                new AspectRatio("8:1", 8, 1),
                new AspectRatio("10:1", 10, 1));

        UCrop.of(fileUri, Uri.fromFile(new File(getCacheDir(),dest_uri)))
                .withOptions(options)
                .withMaxResultSize(2000,2000)
                .start(CropperActivity.this);
    }

    private void readIntent() {
        Intent intent=getIntent();
        if(intent.getExtras()!=null) {
            result=intent.getStringExtra("DATA");
            fileUri=Uri.parse(result);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==RESULT_OK && requestCode==UCrop.REQUEST_CROP){
            final Uri resultURI=UCrop.getOutput(data);
            Intent returnIntent=new Intent();
            returnIntent.putExtra("RESULT", String.valueOf(resultURI));
            setResult(-1, returnIntent);
            finish();
        } else if(resultCode==UCrop.RESULT_ERROR) {
            final Throwable cropError=UCrop.getError(data);
        }
    }
}

解决方案

一、直接使用已知Uri启动裁剪

完全移除相册选择相关的ActivityResultLauncher代码,直接将已知Uri传入CropperActivity:

修改主Activity的onCreate方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.你的主布局); // 确保设置了布局

    // 替换为你已获取到的目标图片Uri
    Uri targetImageUri = ...; // 示例:Uri.parse("content://media/external/images/media/123") 或本地文件Uri

    // 直接启动裁剪页面
    Intent intent = new Intent(this, CropperActivity.class);
    intent.putExtra("DATA", targetImageUri.toString());
    startActivityForResult(intent, 101);
}

二、使用Bitmap生成Uri后启动裁剪

如果只有Bitmap对象,先将Bitmap保存到应用缓存目录生成Uri,再传入CropperActivity:

  1. 添加Bitmap转Uri的工具方法:
private Uri bitmapToUri(Bitmap bitmap) {
    // 将Bitmap保存到缓存文件
    File cacheFile = new File(getCacheDir(), "temp_image_" + System.currentTimeMillis() + ".jpg");
    try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
        fos.flush();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    // Android 7.0+用FileProvider避免FileUriExposedException
    return FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", cacheFile);
}
  1. 在onCreate中调用方法并启动裁剪:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.你的主布局);

    // 替换为你已获取到的Bitmap
    Bitmap targetBitmap = ...;

    Uri bitmapUri = bitmapToUri(targetBitmap);
    if (bitmapUri != null) {
        Intent intent = new Intent(this, CropperActivity.class);
        intent.putExtra("DATA", bitmapUri.toString());
        startActivityForResult(intent, 101);
    } else {
        Log.e("BitmapError", "Bitmap转Uri失败");
    }
}

注意事项

  • 若使用FileProvider,需在AndroidManifest.xml中注册:
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
  • 在res/xml目录下创建file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <cache-path name="cache_images" path="/" />
</paths>

内容的提问来源于stack exchange,提问作者Nuggzy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:01:03