How to get result through intent from another activity - android

I am using this cropper library. I want to know from the following chunk of code, how do I get the result of the cropped image's path in a string?
Intent intent = new Intent(this, CropImage.class);
intent.putExtra(CropImage.IMAGE_PATH, imageFilePath);
intent.putExtra(CropImage.SCALE, true);
intent.putExtra("outputX", 200); //Set this to define the max size of the output bitmap
intent.putExtra("outputY", 150); //Set this to define the max size of the output bitmap
intent.putExtra(CropImage.ASPECT_X, 0);
intent.putExtra(CropImage.ASPECT_Y, 0);
startActivity(intent);

First you need to change startActivity with startActivityForResult.
If you're done with that, in your activity, override onActivityResult, then do
String path = data.getStringExtra(CropImage.IMAGE_PATH);
where data is the Intent object from onActivityResult(int requestCode, int resultCode, Intent data)

As per the documentation at the libraries github page, you should be using startActivityForResult instead of startActivity.
By calling startActivityForResult, once that Activity has finished, onActivityResult will be called which will then allow you to pull the result out.
The following code is from the README.md of this library:
To start the activity:
private void runCropImage() {
// create explicit intent
Intent intent = new Intent(this, CropImage.class);
// tell CropImage activity to look for image to crop
String filePath = ...;
intent.putExtra(CropImage.IMAGE_PATH, filePath);
// allow CropImage activity to rescale image
intent.putExtra(CropImage.SCALE, true);
// if the aspect ratio is fixed to ratio 3/2
intent.putExtra(CropImage.ASPECT_X, 3);
intent.putExtra(CropImage.ASPECT_Y, 2);
// start activity CropImage with certain request code and listen
// for result
startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
}
Waiting for a result:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case REQUEST_CODE_CROP_IMAGE:
String path = data.getStringExtra(CropImage.IMAGE_PATH);
// if nothing received
if (path == null) {
return;
}
// cropped bitmap
Bitmap bitmap = BitmapFactory.decodeFile(mFileTemp.getPath());
break;
}
super.onActivityResult(requestCode, resultCode, data);
}

Related

Google Photos vs Stock Gallery - Intent Picker

In my app, I allow the user to pick a profile image from their gallery, like so:
When You click the first option, on my Android 5.0 device, I get this:
If I use the normal Gallery app that is based off the AOSP project, everything works fine and dandy. However, the Photo's app appears to use a different intent.
Here is how I handle code for the normal gallery:
Intent photoPickerIntent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
photoPickerIntent.putExtra("outputX", 300);
photoPickerIntent.putExtra("outputY", 300);
photoPickerIntent.putExtra("aspectX", 1);
photoPickerIntent.putExtra("aspectY", 1);
photoPickerIntent.putExtra("scale", true);
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
photoPickerIntent.putExtra("outputFormat",
Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(photoPickerIntent, RESULT_LOAD_IMAGE);
And then the intent result handler:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RESULT_LOAD_IMAGE
&& resultCode == Activity.RESULT_OK) {
if (data != null) {
tempFile = getTempFile();
filePath = Environment.getExternalStorageDirectory() + "/"
+ "temporary_holder.jpg";
Log.d("LOAD REQUEST filePath", filePath);
Bitmap selectedImage = BitmapFactory.decodeFile(filePath);
iPP.setImageBitmap(selectedImage);
}
imagePath = filePath;
new UploadImage().execute();
}
}
Some of the helper functions from above:
private static Uri getTempUri() {
return Uri.fromFile(getTempFile());
}
private static File getTempFile() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File file = new File(Environment.getExternalStorageDirectory(),
"temporary_holder.jpg");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
return null;
}
Some of that is probably not needed to show but I included it all in case it is interfering.
When I use Google Photos to pick a photo, my ImageView is blank (instead of filling with selected pick). The image is not selected and I can't go to the manual cropping view like I have it set with the Gallery. So basically, nothing happens.
NEW CODE IN RESPONSE TO ANSWER
photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
photoPickerIntent.putExtra("outputX", 300);
photoPickerIntent.putExtra("outputY", 300);
photoPickerIntent.putExtra("aspectX", 1);
photoPickerIntent.putExtra("aspectY", 1);
photoPickerIntent.putExtra("scale", true);
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
photoPickerIntent.putExtra("outputFormat",
Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(photoPickerIntent, RESULT_LOAD_IMAGE);
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
Log.i("data", data.toString());
switch (requestCode) {
case RESULT_LOAD_IMAGE:
Log.i("RESULT_LOAD_IMAGE", "MARK");
// Received an image from the picker, now send an Intent for cropping
final String CROP_ACTION = "com.android.camera.action.CROP";
Intent photoCropIntent = new Intent(CROP_ACTION);
photoCropIntent.putExtra("crop", "true");
photoCropIntent.putExtra("aspectX", 1);
photoCropIntent.putExtra("aspectY", 1);
photoCropIntent.putExtra("outputX", 300);
photoCropIntent.putExtra("outputY", 300);
photoCropIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
photoCropIntent.putExtra("outputFormat",
Bitmap.CompressFormat.JPEG.toString());
photoCropIntent.setData(data.getData());
startActivityForResult(photoPickerIntent, RESULT_CROP_IMAGE);
break;
case RESULT_CROP_IMAGE:
Log.i("RESULT_CROP_IMAGE", "MARK");
tempFile = getTempFile();
imagePath = Environment.getExternalStorageDirectory() + "/" + "temporary_holder.jpg";
Log.i("imagePath", imagePath);
Uri selectedImageURI = data.getData();
InputStream image_stream;
try {
image_stream = getActivity().getContentResolver().openInputStream(selectedImageURI);
Bitmap bitmap = BitmapFactory.decodeStream(image_stream);
iPP.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
new UploadImage().execute();
break;
default:
// Handle default case
}
}
}
}
The above code isn't working either. I tried to make it resemble the answer below. What happens is:
I click "Choose from Gallery". And it does not give me a choice anymore, now it opens directly from the stock Gallery (that is not a big deal). I click on the image, and it ... appears to start the same intent over again -- it brings back the gallery wanting me to pick another image: instead of the Cropping Activity. Then after the second time, it will set my ImageView with the selected file.
Solution
First, update the photoPickerIntent to use ACTION_GET_CONTENT, and remove the extras related to cropping, since cropping will be handled by another Intent later:
Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
photoPickerIntent.setType("image/*");
// Do not include the extras related to cropping here;
// this Intent is for selecting the image only.
startActivityForResult(photoPickerIntent, RESULT_LOAD_IMAGE);
Then, onActivityResult() will have to handle two results: RESULT_LOAD_IMAGE will send another intent for the crop, and RESULT_CROP_IMAGE will continue processing as you did before:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
switch (requestCode) {
case RESULT_LOAD_IMAGE:
// Received an image from the picker, now send an Intent for cropping
final String CROP_ACTION = "com.android.camera.action.CROP";
Intent photoCropIntent = new Intent(CROP_ACTION);
photoCropIntent.setData(data.getData());
// TODO: first get this running without extras, then test each one here
startActivityForResult(photoCropIntent, RESULT_CROP_IMAGE);
break;
case RESULT_CROP_IMAGE:
// Received the cropped image, continue processing. Note that this
// is just copied and pasted from your question and may have
// omissions.
tempFile = getTempFile();
filePath = Environment.getExternalStorageDirectory() + "/"
+ "temporary_holder.jpg";
Log.d("LOAD REQUEST filePath", filePath);
Bitmap selectedImage = BitmapFactory.decodeFile(filePath);
iPP.setImageBitmap(selectedImage);
imagePath = filePath;
new UploadImage().execute();
break;
default:
// Handle default case
}
}
}
Note that although I've tested parts of this code, I haven't tested this entire block of code at runtime. If it doesn't work right out-of-the-box, though, it should be pretty close. Please comment if you have any questions or issues, and I'll update my answer accordingly.
Background
On an Android 5.0.1 (API 21) device with both AOSP Gallery2 (com.android.gallery3d) and Photos installed, I ran your Intent. I was prompted to choose between Gallery or Photos.
When I chose Photos, a picker was presented, and I picked an image. I was immediately returned to my Activity, with no cropping options.
When I chose Gallery, a picker was presented, and I picked an image. I was then prompted to choose an app for cropping. Both Photos and Gallery were presented as options for cropping.
Here's the interesting log output when choosing Gallery:
// Send the Intent
3-07 15:20:10.347 719-817/? I/ActivityManager﹕ Displayed android/com.android.internal.app.ResolverActivity: +127ms
// Choose Gallery
03-07 15:20:27.762 719-735/? I/ActivityManager﹕ START u0 {act=android.intent.action.PICK typ=image/* flg=0x3000000 cmp=com.android.gallery3d/.app.GalleryActivity (has extras)} from uid 10084 on display 0
// (fixing highlighting after MIME type on previous line) */
03-07 15:20:27.814 22967-22967/? W/GalleryActivity﹕ action PICK is not supported
03-07 15:20:27.814 22967-22967/? V/StateManager﹕ startState class com.android.gallery3d.app.AlbumSetPage
03-07 15:20:27.967 719-817/? I/ActivityManager﹕ Displayed com.android.gallery3d/.app.GalleryActivity: +190ms
// Pick an image
3-07 15:21:45.993 22967-22967/? V/StateManager﹕ startStateForResult class com.android.gallery3d.app.AlbumPage, 1
03-07 15:21:46.011 22967-22967/? D/AlbumPage﹕ onSyncDone: ********* result=0
03-07 15:21:46.034 22967-24132/? I/GLRootView﹕ layout content pane 1080x1701 (compensation 0)
03-07 15:21:48.447 719-1609/? I/ActivityManager﹕ START u0 {act=com.android.camera.action.CROP dat=content://media/external/images/media/1000 flg=0x2000000 cmp=android/com.android.internal.app.ResolverActivity (has extras)} from uid 10100 on display 0
First, note W/GalleryActivity﹕ action PICK is not supported. I'm not sure why it works, but according to Dianne Hackborn, "...you should consider ACTION_PICK deprecated. The modern action is ACTION_GET_CONTENT which is much better supported..." I've addressed this in my solution above.
The good news is, however, it seems that after picking an image, .putExtra("crop", "true"); causes Gallery to send another Intent for cropping. And the log clearly shows the action and data to use.
I tested this cropping intent, and I was prompted to choose an app for cropping, just like before. And again, both Photos and Gallery were presented as options, and they both brought up cropping interfaces.
It seems that although Photos supports cropping by Intent, it just ignores the extras relating to cropping in ACTION_PICK, whereas Gallery responds by sending another Intent after picking an image. Regardless, having the details of a working cropping Intent leads to the solution above.
I have solved this problem this way.
Pick image:
private void pickUserImage() {
if (doHavePermission()) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
photoPickerIntent.putExtra("scale", true);
photoPickerIntent.putExtra("outputX", 256);
photoPickerIntent.putExtra("outputY", 256);
photoPickerIntent.putExtra("aspectX", 1);
photoPickerIntent.putExtra("aspectY", 1);
photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
startActivityForResult(photoPickerIntent, PICK_FROM_GALLERY);
}
}
used method getTempUri() is
private Uri getTempUri() {
return Uri.fromFile(getTempFile());
}
private File getTempFile() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File file = new File(Environment.getExternalStorageDirectory(),TEMP_PHOTO_FILE);
try {
file.createNewFile();
} catch (IOException e) {
Log.printStackTrace(e);
}
return file;
} else {
return null;
}
}
get the picked image
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PICK_FROM_GALLERY) {
if (data!=null) {
Uri selectedImageUri = data.getData();
//String tempPath = getPath(selectedImageUri, UserProfileActivity.this);
String url = data.getData().toString();
if (url.startsWith("content://com.google.android.apps.photos.content")){
try {
InputStream is = getContentResolver().openInputStream(selectedImageUri);
if (is != null) {
Bitmap selectedImage = BitmapFactory.decodeStream(is);
//You can use this bitmap according to your purpose or Set bitmap to imageview
if (selectedImage != null) {
isImageUpdated = true;
isImageUpdated = true;
Bitmap resizedBitmap = null;
if (selectedImage.getWidth() >= 256 && selectedImage.getHeight() >= 256) {
resizedBitmap = Bitmap.createBitmap(selectedImage,
selectedImage.getWidth() - 128,
selectedImage.getHeight() - 128,
256, 256);
}
if (resizedBitmap != null) {
imageViewUserImage.setImageDrawable(ImageHelper.getRoundedCornerImage(resizedBitmap, 20));
} else {
imageViewUserImage.setImageDrawable(ImageHelper.getRoundedCornerImage(selectedImage, 20));
}
}
}
} catch (FileNotFoundException e) {
Log.printStackTrace(e);
}
} else {
File tempFile = getTempFile();
String filePath = Environment.getExternalStorageDirectory() + "/" + TEMP_PHOTO_FILE;
Log.d(TAG, "path " + filePath);
Bitmap selectedImage = BitmapFactory.decodeFile(filePath);
if (selectedImage != null) {
isImageUpdated = true;
imageViewUserImage.setImageDrawable(ImageHelper.getRoundedCornerImage(selectedImage, 20));
}
if (tempFile.exists()) {
tempFile.delete();
}
}
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
Image converted to rounded corner image as follows:
public class ImageHelper {
public static RoundedBitmapDrawable getRoundedCornerImage(Bitmap bitmap, int cornerRadius) {
RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(null, bitmap);
dr.setCornerRadius(cornerRadius);
return dr;
}
}
Its too late to answer but it can help someone else.

catch `intent not found` and call another method

I want to crop an image and call com.android.camera.action.CROP. As this doesn't exist on all devices I want to have a fallback to catch this and simply add the image w/o cropping.
To do so I rename com.android.camera.action.CROP to xcom.android.camera.action.CROPfor testing purposes and call in the catch another method with another resultCode NO_CROPbut always the actual resultCode PICK_CROPis called also.
How can I ignore PICK_CROPin this case so that it doesn't jump to drawImage()always where data is of course null and avoid a null poiner exception and instead go to noCrop()?
Here's my code:
//Start cropping intent
private void performCrop(int requestCode, Intent data) {
// take care of exceptions
try {
// call the standard crop action intent (the user device may not
// support it)
Intent cropIntent = new Intent("xcom.android.camera.action.CROP");
// indicate image type and Uri
cropIntent.setDataAndType(imgUri, "image/*");
// set crop properties
cropIntent.putExtra("crop", "true");
// indicate aspect of desired crop
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
// indicate output X and Y
cropIntent.putExtra("outputX", 256);
cropIntent.putExtra("outputY", 256);
// retrieve data on return
cropIntent.putExtra("return-data", true);
// start the activity - we handle returning in onActivityResult
startActivityForResult(cropIntent, PIC_CROP);
}
// respond to users whose devices do not support the crop action
catch (ActivityNotFoundException anfe) {
// add chosen photo directly to imageview
Bundle extras = data.getExtras();
Bitmap photo = extras.getParcelable("data");
noCrop(photo, NO_CROP, requestCode, data);
}
}
// draw image in circle canvas w/o crop -> fallback if crop doesn't exist on users device
private void noCrop(Bitmap photo, int requestCode, int resultCode, Intent data) {
if (requestCode == NO_CROP) {
ImageView profilepic = (ImageView) findViewById(R.id.profilepic);
GraphicsUtil graphicUtil = new GraphicsUtil();
profilepic.setImageBitmap(graphicUtil.getCircleBitmap(photo, 16));
saveProfile(photo);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
// Draw cropped image to imageview with circle canvas
private void drawImage(int requestCode, int resultCode, Intent data) {
if (requestCode == PIC_CROP) {
Bundle extras = data.getExtras();
ImageView profilepic = (ImageView) findViewById(R.id.profilepic);
Bitmap photo = extras.getParcelable("data");
// display the returned cropped image
GraphicsUtil graphicUtil = new GraphicsUtil();
profilepic.setImageBitmap(graphicUtil.getCircleBitmap(photo, 16));
saveProfile(photo);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
As you said com.android.camera.action.CROP intent is not supported in all devices so why use it and write a fallback mechanism. There are many libraries available for cropping images. I have used Cropper and simple-image-crop library from github. Have a look at my answer here about simple-image-crop library.
OK, I did a mistake. It's actually working to catch if the intent is not available. After some deeper debugging I found out that it crashes at Bitmap photo = extras.getParcelable("data"); because I'm not passing the correct data :-(
Sorry for any inconvenience!

Take photo and save original size

How can get photo from intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
in onActivityResult not in URI format but JPG,PNG orginal size and save it gallery.
Need JPG,PNG because after shot I adding watermark on it.
I don't know why after bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); returned photo size from 2048x1536 is 256x192.
For saving the image in the gallery you have send a broadcast as shown in the code sample below.
If you need the image with orignal sizes you could simply catch the uri and set it to a ImageView directly. Although it is a good practice to scale it down and use a smaller version of your bitmap to avoid the OutOfMemory Exception.
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(requestCode==CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE){
if(resultCode==RESULT_OK){
saveToGallery(mImageUri);
yourImageView.setImageURI(mImageUri);
}
}
}
public void saveToGallery(Uri uri){
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,uri));
}

How to capture image thumbnail AND save file in a custom folder in Android

I am trying to capture an image from an existing camera application, save the image in a customized folder, and display the thumbnail in and imageView. The camera supplies the thumbnail as long as I haven't specified where to save the file:
I can get the thumbnail from the returned intent:
...
Intent i = = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i)
}
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
Bundle extras = intent.getExtras();
Bitmap mImageBitmap = (Bitmap) extras.get("data");
}
Or I can save the file in a specified folder (which works fine)
...
Intent i = = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra((MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(i)
}
but the thumbnail is no longer stored in the intent extra "data", and when I try to retrieve the thumbnail, I get an error (this is from my LogCat)
10-04 06:30:14.463: E/AndroidRuntime(1967): Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=null} to activity: java.lang.NullPointerException
As you can see, the field returned is null instead of the bitmap thumbnail. I have tried decoding the bitmap afterwards to generate a thumbnail from the file directly, but it takes too long (even when downsampled I get out of memory error) , and it seems counterintuitive to do the job twice. Any suggestions?
Okay. If you are passing an outputURI to the intent then you will not be able to receive the data back from the intent in onActivityResult().
I think only option is to use the same outputURI to display the thumbnail..
Try this.
void captureImage(){
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/MyFolder", "myImage"+ ".jpg");
mCapturedImagePath = file.getAbsolutePath();
Uri outputFileUri = Uri.fromFile(file);
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(i, CAMERA_REQUEST);
}
onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST) {
if (resultCode == RESULT_OK) {
File file = new File(mCapturedImagePath);
imageView.setImageURI(Uri.fromFile(file));
}
}
}
Your Bitmap mImageBitmap is a local variable, make that global if you want to use it outside the onActivityResultFunction otherwise set the image there as
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST) {
photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
}
}
try this
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);

how to get the images from device in android java application

In my application I want to upload the image.
For that I have to get images from gallery in android device.
How do I write code that accomplishes this?
Raise an Intent with Action as ACTION_GET_CONTENT and set the type to "image/*". This will start the photo picker Activity. When the user selects an image, you can use the onActivityResult callback to get the results.
Something like:
Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, 1);
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
{
Uri chosenImageUri = data.getData();
Bitmap mBitmap = null;
mBitmap = Media.getBitmap(this.getContentResolver(), chosenImageUri);
}
}

Categories

Resources