安卓图片裁剪无法进入裁剪页面

只要使用了return-data为true就会在选择图片后直接回到软件页面,根本没进入裁剪页面,这是怎么回事呢(不考虑图片大小问题)
并且尝试过保存到本地的私有存储下,可以进入裁剪页面,但是裁剪结束后相册提示保存失败,不是权限问题(大概),主要关心的是为何不能用直接返回Bitmap形式的返回方式

@Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        
        if(requestCode == CHOOSE_CODE && data != null && resultCode == -1){
            Uri uri = data.getData();
            cropImage(uri);
        } else if (requestCode == CROP_CODE && data != null && resultCode ==0) {

            Bitmap bitmap = data.getExtras().getParcelable("data");
            test.setImageBitmap(bitmap);
        }

    }

    public void cropImage(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        intent.setDataAndType(uri, "image/*");
        //设置裁剪为true
        intent.putExtra("crop", "true");
        //设置大小
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", 300);
        intent.putExtra("outputY", 300);

        intent.putExtra("return-data",true);
        startActivityForResult(intent,CROP_CODE);
    }

图片

img

在 Android 中,return-data 标志用于将裁剪后的图像数据作为 Bitmap 对象返回给调用应用程序。当设置该标志时,系统将在裁剪完成后将图像数据直接返回,而不是将其保存在文件中。由于 Bitmap 对象可能非常大,所以当图像过大时,该标志可能会导致应用程序崩溃或无法正常工作。

在你的代码中,你设置了 return-data 标志为 true,这可能导致在选择图像后直接返回裁剪后的图像数据,而没有进入裁剪页面。要解决这个问题,你可以尝试使用 Uri 对象将裁剪后的图像数据保存到文件中,然后将文件路径作为数据返回给调用应用程序。这样做可以避免将大量数据存储在内存中,从而减少应用程序的内存使用量。

关于你的第二个问题,保存到本地的私有存储下可以进入裁剪页面,但是裁剪结束后相册提示保存失败。这可能是由于你没有正确处理文件访问权限的问题。在 Android 中,如果你想将数据保存到外部存储器上,你需要在运行时请求外部存储器权限,并在运行时处理访问权限。

在你的代码中,你将 Uri 对象作为参数传递给 cropImage() 方法,这意味着你可能正在使用外部存储器上的图像文件进行裁剪。如果你没有正确处理文件访问权限,你可能会遇到保存失败的问题。为了解决这个问题,你可以尝试将图像文件保存到应用程序的私有存储空间中,然后再将其传递给裁剪操作。

以下是一种可能的实现方式:

private Uri mCropUri; // 保存裁剪后的图像文件的 Uri

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    
    if (requestCode == CHOOSE_CODE && data != null && resultCode == -1) {
        Uri uri = data.getData();
        cropImage(uri);
    } else if (requestCode == CROP_CODE && resultCode == RESULT_OK) {
        // 获取裁剪后的图像数据 Uri
        Uri uri = mCropUri;
        // 将 Uri 转换为 Bitmap
        Bitmap bitmap = null;
        try {
            bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (bitmap != null) {
            test.setImageBitmap(bitmap);
        }
    }
}

private void cropImage(Uri uri) {
    // 创建裁剪后的图像文件的 Uri
    mCropUri = Uri.fromFile(new File(getExternalFilesDir(null), "crop.jpg"));
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    intent.setDataAndType(uri, "image/*");
    // 设置裁剪为 true
    intent.putExtra("crop", "true");
    // 设置大小
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    intent.putExtra("outputX", 300);
    intent.putExtra("outputY", 300);
    // 设置输出文件的 Uri
    intent.putExtra(MediaStore.EXTRA_OUTPUT, mCropUri);
    intent.putExtra("return-data", false);
    startActivityForResult(intent, CROP_CODE);
}

在上面的代码中,我们在 cropImage() 方法中创建了一个 Uri对象 mCropUri,该对象用于保存裁剪后的图像数据。我们将裁剪后的图像数据保存到应用程序的私有存储空间中,以确保我们有访问权限。在 onActivityResult() 方法中,我们从 mCropUri 中读取图像数据,并将其转换为 Bitmap 对象。请注意,我们将 return-data 标志设置为 false,以便系统将图像数据保存到 mCropUri 中,而不是将其返回给我们的应用程序。

希望这些信息可以帮助你解决问题。如果仍有问题,请提供更多详细信息,以便我们更好地帮助你。

参考我得

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
 if (resultCode == Activity.RESULT_OK) { 
  switch (requestCode) { 
  case TAKE_PICTURE_FROM_ALBUM: 
   if (data != null) { 
    cropPictureFromAlbum(data.getData()); 
   } 
   break; 
  case PICTURE_CROP_CODE: 
   if (data != null) { 
    // 这是裁剪后图片的bitmap 
    Bitmap bitmap = data.getParcelableExtra("data"); 
   } 
   break; 
  default: 
   break; 
  } 
 } 
} 
  
private static final int TAKE_PICTURE_FROM_ALBUM = 1; 
  
private void takePictureFromAlbum() { 
 Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
 intent.setType("image/*"); 
 startActivityForResult(intent, TAKE_PICTURE_FROM_ALBUM); 
} 
  
private static final int PICTURE_CROP_CODE = 2; 
  
private void cropPictureFromAlbum(Uri pictureUri) { 
 Intent intent = new Intent("com.android.camera.action.CROP"); 
 intent.setDataAndType(pictureUri, "image/*"); 
 intent.putExtra("crop", "true"); 
 // 裁剪框比例 
 intent.putExtra("aspectX", 1); 
 intent.putExtra("aspectY", 2); 
  
 // 裁剪后输入图片的尺寸大小 
 intent.putExtra("outputX", 300); 
 intent.putExtra("outputY", 300); 
  
 // 取消人脸识别 
 intent.putExtra("noFaceDetection", true); 
  
 intent.putExtra("return-data", true); 
  
 startActivityForResult(intent, PICTURE_CROP_CODE); 
} 

这样修改后,裁剪后的图像将保存在getCacheDir()方法返回的目录下的cropped_image.jpg文件中,并且在onActivityResult方法中使用cropFile进行后续处理。


@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(requestCode == CHOOSE_CODE && data != null && resultCode == -1){
        Uri uri = data.getData();
        cropImage(uri);
    } else if (requestCode == CROP_CODE && resultCode == RESULT_OK) {
        // 处理裁剪后的图像文件
        File cropFile = new File(getCacheDir(), "cropped_image.jpg");
        // 使用cropFile进行后续处理,如显示到ImageView等
        test.setImageURI(Uri.fromFile(cropFile));
    }
}

public void cropImage(Uri uri) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    intent.setDataAndType(uri, "image/*");
    // 设置裁剪为true
    intent.putExtra("crop", "true");
    // 设置大小
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    intent.putExtra("outputX", 300);
    intent.putExtra("outputY", 300);

    // 指定裁剪后的图像保存路径
    File cropFile = new File(getCacheDir(), "cropped_image.jpg");
    Uri cropUri = Uri.fromFile(cropFile);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);

    startActivityForResult(intent, CROP_CODE);
}

试试使用return-data为false,并使用Uri来传递选择的图片,然后在相册中打开具有裁剪选项的Intent。一旦用户完成裁剪,在onActivityResult回调中获取裁剪后的Uri对象。这种方式可以确保进入裁剪页面,并在裁剪完成后获取高质量的裁剪图片