I want my Android app to take a picture, as part of something larger it is doing.
Ideally, I would like to just send out an Intent saying "snap a picture" and get back an image file.
Is there an Activity that can handle that, or do I need to do all the low level work with the Camera class myself?
Thanks,
Peter
You can invoke the default camera activity using an Intent and startActivityForResult(). You can also construct a Uri and file name for the image and pass that to the photo capture activity. When the user takes a photo it will be saved with that name at the location you've specified.
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE );
intent.putExtra( MediaStore.EXTRA_OUTPUT, outputUri );
startActivityForResult( intent, 0 );
If the user cancels the capture then a result of 0 is returned, and if they take a photo and approve it, a result of -1 is returned.
Related
in my app i would like to have the user choose an image from the gallery and retrieve the result (thumbnail + full image uri). i would also like the user to be able to choose which gallery app to open (i.e. default gallery app or some other gallery app).
initially, according to this guide by google i copied and pasted this code:
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_IMAGE_GET);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
Bitmap thumbnail = data.getParcelable("data");
Uri fullPhotoUri = data.getData();
// Do work with photo saved at fullPhotoUri
...
}
}
while it does get me the thumbnail and the full Uri in onActivityResult(...), the problem is that it does not open a chooser for the user to select which gallery app to use and instead it opens this thing (see images below), which i assume is a default "image-chooser" thing where you could select another app via a menu.
i feel it's silly that the user would have to open this default "image chooser" first and once they are already in an "image chooser", select the gallery app that they actually want to use (sure, the user could just choose the image from this thing, but i want to give them a convenient choice).
so i changed my code to this and it does indeed display a proper chooser for the user and he can go straight to hes favorite gallery app:
Intent intent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
if (intent.resolveActivity(getActivity().getPackageManager()) != null)
{
startActivityForResult(intent, Utils.REQUEST_CODE_OPEN_GALLERY);
}
however now i have a new problem: in onActivityResult(...) the line data.getParcelable("data"); returns null. in other words, i don't get back a thumbnail.
i also tried
Bundle extras = data.getExtras();
Bitmap thumbnail = (Bitmap) extras.get("data");
but "extras" is null.
is it possible to have a proper "app chooser" AND get back a thumbnail?
however now i have a new problem: in onActivityResult(...) the line data.getParcelable("data"); returns null. in other words, i don't get back a thumbnail.
You do not get that from ACTION_GET_CONTENT, either. You can tell this by reading the documentation for ACTION_GET_CONTENT. It is certainly possible that there are some buggy ACTION_GET_CONTENT activities that happen to return a thumbnail Bitmap in a "data" extra, but you should not assume that any user will have such a buggy ACTION_GET_CONTENT activity, let alone choose it. Besides, ACTION_GET_CONTENT is not limited to images; what would a "thumbnail" be of application/json or text/csv be?
Likewise, if you read the documentation for ACTION_PICK, you will see that there is no discussion of a thumbnail.
is it possible to have a proper "app chooser" AND get back a thumbnail?
No, insofar as you do not get a thumbnail back from anything except ACTION_IMAGE_CAPTURE, and that is for taking photos.
I'm currently creating a functionnality for the user to upload images to my server. He can either takes pictures with his camera or from his gallery.
I'm using this code to take a picture with the camera :
// create Intent to take a picture and return control to the calling application
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
tempFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), ".jpeg", ContextCompat.getExternalCacheDirs(a)[0]);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
// start the image capture Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
And then to manipulate the image I use onActivityResult as such :
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// use tempFile to recreate bitmap and do some heavy-wooshy-wishy stuff
...
}
}
It works totally fine but I'm confused with the Intent data parameter when using the camera. In this case it is null and to use the taken picture I need to re-create it from the path I gave to the ... intent.
What I find especially confusing is that if I don't put any EXTRA_OUTPUT parameter, then the Intent data isn't null and I can easily get the path of the picture with data.getData().
BUT THEN I just get a thumbnail from the original picture.
Is there any way to get the original picture from the camera and the path from the intent ? I don't have any real use case, but let's say the tempFile field gets modified or destroyed when you're taking the picture. Then on onActivityResult you will not be able to use the just taken picture.
What I find especially confusing is that if I don't put any EXTRA_OUTPUT parameter, then the Intent data isn't null and I can easily get the path of the picture with data.getData().
Not generally. There is no requirement for ACTION_IMAGE_CAPTURE to provide you a path to anything. Getting a thumbnail back via the data extra, if you do not provide EXTRA_OUTPUT, is the only "result" that you are supposed to get back in onActivityResult().
Is there any way to get the original picture from the camera and the path from the intent ?
No, because you never get the path from the Intent. It may be that a few camera apps leak this information. Not all will.
but let's say the tempFile field gets modified or destroyed when you're taking the picture
It is your job to not make that sort of mistake. For example, make sure that you retain this value across configuration changes and short-lived process termination, via onSavedInstanceState().
I am using the ACTION_EDIT intent to launch the Android image editor in order to edit an image:
Intent editIntent = new Intent(Intent.ACTION_EDIT);
editIntent.setDataAndType(uri, "image/*");
When launching the intent with result, how do I retrieve the path of the edited / saved image?
I am using the ACTION_EDIT intent to launch the Android image editor in order to edit an image
Bear in mind that Android does not have an image editor. Some Android devices might ship with an image editor, and some users may have installed an image editor off of the Play Store or other distribution channels.
Also, since you know what the MIME type is of uri, you will have better results if you put the real MIME type into your Intent.
When launching the intent with result, how do I retrieve the path of the edited / saved image?
First, ACTION_EDIT does not support "launch the intent with result", which I am interpreting as meaning startActivityForResult(). As the ACTION_EDIT documentation states, there is no output. Just use startActivity().
Beyond that, you are the one who provided the Uri in the Intent for the editor, so at that point in time, you already knew what the Uri was that you handed to the editor. Hang onto that Uri in your saved instance state, so that you can ensure that you have the Uri even if Android terminates your process while the user is editing the image. While there is no requirement that an ACTION_EDIT Intent save the edited image back to the location specified by the Uri used to load the image, one hopes that most ACTION_EDIT activities do just that.
I have an app that a user will be able to take pictures with. Having the camera is a small, but necessary feature but I want it to only be able to take pictures (no video). Is there a way I can make it startIntentForResult with a pictures-only camera intent? Or perhaps make it only accept images as the result? Making my own custom camera for the app seems a bit overkill, but I will do it if I have to.
Thanks
This code has been working for me for ever
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.fromFile(File.createTempFile("image", ".jpg"));
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(Intent.createChooser(cameraIntent, "Take Picture", 0);
I'm trying to use a standard Intent that will take a picture, then allow approval or retake. Then I want to save the picture into a file.
Here's the Intent I am using:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE );
startActivityForResult( intent, 22 );
The documentation says:
The caller may pass an extra EXTRA_OUTPUT to control where this
image will be written. If the EXTRA_OUTPUT is not present, then a
small sized image is returned as a Bitmap object in the extra field. If
the EXTRA_OUTPUT is present, then the full-sized image will be
written to the Uri value of EXTRA_OUTPUT.
I don't pass extra output, I hope to get a Bitmap object in the extra field of the Intent passed into onActivityResult() (for this request). So where/how do you extract it? Intent has a getExtras(), but that returns a Bundle, and Bundle wants a key string to give you something back.
What do you invoke on the Intent to extract the bitmap?
Try calling getExtras().get("data") and casting the result to a Bitmap.
See here for an example.
On a related note, if you have the "crop" activity come up after taking the picture using intent.putExtra("crop", "true"), you'll get the cropped URI from getExtras().get("action").
I realize you've got this all fixed by now, just want to make sure no one tries to use this with crop and gets confused.
Reference: the apps-for-android LolCat activity.