Does Null always return after cropping a photo from Uri in Android Lollipop?
I tried cropping the image from the Uri after taking a photo or selecting an image. And my codes are like this:
public static void cropImage(Uri uri, Activity activity, int action_code) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 600);
intent.putExtra("outputY", 600);
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
if (intent.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivityForResult(intent, action_code);
} else {
Toast.makeText(activity, "No Crop App Available", Toast.LENGTH_SHORT).show();
}
}
And reinstalling onActivityResult()
like this:
if (resultCode == Activity.RESULT_OK && requestCode == Utils.CODE_CROP_IMAGE) {
Bundle extras = data.getExtras();
showCenterToast("ccc");
if (extras != null) {
showCenterToast("CCC");
Bitmap photo = extras.getParcelable("data");
ivAvatar.setImageBitmap(photo); // display image in ImageView
FileOutputStream fos = null;
try {
fos = new FileOutputStream(Utils.AVATAR_FILE);
photo.compress(Bitmap.CompressFormat.PNG, 100, fos);// (0-100)compressing file
showCenterToast("DDD");
Utils.AVATAR_FILE_TMP.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
IoUtil.closeSilently(fos);
}
}
}
On devices in Android Pre-Lollipop, I was able to get Bitmap photo
and display it in ImageView
. But on Android Lollipop I always got null
from data.getExtras();
.
I walked a lot but got a few useful things about cropping an image on Android Lollipop .
Android changed its trim return mechanism com.android.camera.action.CROP
to Lollipop. So what's the new mechanism? How can I get returned Bitmap
after trimming on Lollipop?
Any advice would be appreciated. Thanks in advance.
source to share
I think your problem has nothing to do with the Android version, but the image you want to crop. Cropping an image processed in class com.android.gallery3d.filtershow.crop.CropActivity#BitmapIOTask
. When the image is too big to return, it will try to return the image's thumb and will sometimes return null. To avoid this, you can get the uri of the cropped image instead of the bitmap by setting intent.putExtra(MediaStore.EXTRA_OUTPUT, tmpUri);
where tmpUri
is the uri created to hold the result. And then you can get a bitmap with tmpUri
.
Sample code:
private static final String IMAGE_FILE_LOCATION = "file:///sdcard/temp.jpg";//temp file
private static Uri tmpUri = Uri.parse(IMAGE_FILE_LOCATION);//The Uri to store the big bitmap
public static void cropImage(Uri uri, Activity activity, int action_code) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 600);
intent.putExtra("outputY", 600);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, tmpUri);
if (intent.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivityForResult(intent, action_code);
} else {
Toast.makeText(activity, "No Crop App Available", Toast.LENGTH_SHORT).show();
}
}
And in the onActivityResult function:
if (resultCode == Activity.RESULT_OK && requestCode == Utils.CODE_CROP_IMAGE) {
// Bundle extras = data.getExtras();
Uri uri = data.getData();
showCenterToast("ccc");
if (uri != null) {
showCenterToast("CCC");
// Bitmap photo = null;
// if (tmpUri != null) {
// photo = decodeBitmapFromUri(tmpUri); // Get bitmap from uri.
// }
Bitmap photo = decodeUriAsBitmap(uri);
ivAvatar.setImageBitmap(photo); // display image in ImageView
FileOutputStream fos = null;
try {
fos = new FileOutputStream(Utils.AVATAR_FILE);
photo.compress(Bitmap.CompressFormat.PNG, 100, fos);// (0-100)compressing file
showCenterToast("DDD");
Utils.AVATAR_FILE_TMP.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
IoUtil.closeSilently(fos);
}
} else {
showCenterToast("Uri is NULL");
}
}
private Bitmap decodeUriAsBitmap(Uri uri){
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
return bitmap;
}
I didn't check if my code was correct, but I think you can fix the errors.
source to share
-
Use the intent to get the image:
Intent pickImageIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); pickImageIntent.setType("image/*"); startActivityForResult(pickImageIntent, 100);
-
Use Result operation for recipient data and get Uri.
-
Use android crop to crop and get the image.
source to share
I solved it and am working now
Basically when cropping an image in a fragment, the problem here is when you are using an activity you have to pass the intent in this way as a result of the action for the best cropping approach, follow this library
compile 'com.theartofdev.edmodo: android-image-cropper: 2.5. + '.
CropImage.activity(imageUri)
.setGuidelines(CropImageView.Guidelines.ON)
.start(getActivity());
When using Fragment, you must use:
Uri selectedImageUri = data.getData();
CropImage.activity(selectedImageUri)
.setGuidelines(CropImageView.Guidelines.ON)
.start(getContext(), this);
Sometimes getcontext requires api 23, this is because you are using app.fragment, so use android.support.v4.app.
Cropping an image with activity and fragment is different, see here. I have completed this thing successfully. Follow the link here for guidance. how to crop image using activity and fragment !!!
I was having difficulty cropping an image in a slice so that it could not be resolved. First, you take an image from a camera or gallery.
private void openGallery() {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, REQUEST_CODE_GALLERY);
}
In case of capturing an image from a camera, be sure to include the manifest file, if you have any problems, please follow this link before doing the following.
private String mCurrentPhotoPath;
private void openCameranoughat() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
Uri photoURI = null;
try {
File photoFile = createImageFile();
path = photoFile.getAbsolutePath();
photoURI = FileProvider.getUriForFile(getActivity(),
BuildConfig.APPLICATION_ID + ".provider",
createImageFile());
} catch (IOException ex) {
Log.e("TakePicture", ex.getMessage());
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
takePictureIntent.setClipData(ClipData.newRawUri("", photoURI));
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
startActivityForResult(takePictureIntent, REQUEST_CODE_CAPTURE);
}
}
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
try {
// Make sure the Pictures directory exists.
path.mkdirs();
} catch (Exception e) {
}
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + file.getAbsolutePath();
return file;
}
Now about the action for the Fragment Activity, you need to write this code.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case ACTION_REQUEST_EDITIMAGE://
handleEditorImage(data);
break;
case REQUEST_CODE_GALLERY:
if (mCurrentPhotoPath == null) {
Uri selectedImageUri = data.getData();
CropImage.activity(selectedImageUri)
.setGuidelines(CropImageView.Guidelines.ON)
.start(getContext(), this);
}
break;
case REQUEST_CODE_CAPTURE:
try {
Uri imageUri = Uri.parse(mCurrentPhotoPath);
if (imageUri == null) {
} else {
CropImage.activity(imageUri)
.setGuidelines(CropImageView.Guidelines.ON)
.start(getContext(), this);
MediaScannerConnection.scanFile(getActivity(),
new String[]{imageUri.getPath()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
mCurrentPhotoPath = null;
}
} catch (Exception e) {
}
break;
case CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE:
CropImage.ActivityResult result = CropImage.getActivityResult(data);
Uri resultUri = result.getUri();
if (resultUri != null) {
path = resultUri.getPath();
if (TextUtils.isEmpty(path)) {
return;
}
Intent it = new Intent(getActivity(), EditImageActivity.class);
it.putExtra(EditImageActivity.FILE_PATH, path);
File outputFile = FileUtils.getEmptyFile("tietu"
+ System.currentTimeMillis() + ".jpg");
it.putExtra(EditImageActivity.EXTRA_OUTPUT,
outputFile.getAbsolutePath());
startActivityForResult(it,
ACTION_REQUEST_EDITIMAGE);
}
break;
case CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE:
Toast.makeText(getActivity(), "error in cropping", Toast.LENGTH_SHORT).show();
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
source to share