Android — Get camera thumbnail and full image

Hello, My name is Rodrigo and i'm a mobile developer, today i i'll teach you how to get images from android camera, there are two ways to get one picture from the native camera app from your device, get an thumbnail, small picture with low resolution just to show to user in tiny image view, and the full image resolution.

Fun fact, why you can’t use aways the full resolution image, well there are some problems around that, think in this situation, you get the full-sized image from the camera and you need to show in a another fullscreen activity this image, imagine you transfer one image 1080p or something better, to another activity by the intent, probably you will receive an exception OutOfMemmoryError (One of various exceptions) because android can’t handle large files like this, this is why exists the thumbnail, it is a tiny bitmap which you can handle and transfer like you wish.

You don't need to get angry anymore when you can't get one good resolution picture or even one picture of the camera, i already pass by a lot of problems with the Android camera and this is a good solution which i found to fix this.

Getting a thumbnail

First in your activity or fragment when you request a picture from camera you need to do this

final static int TAKE_PICTURE = 1;Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
startActivityForResult(cameraIntent, TAKE_PICTURE);

You will call a intent passing to call the camera, obviously you need to handle the Android permissions before this, otherwise the app will crash. I use the with the value 1, this variable is the request code, you will need him in onActivityResult method to catch the image.

Now you can implement the method onActivityResult like this

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

switch (requestCode) {
case TAKE_PICTURE:
if (resultCode == RESULT_OK && intent.hasExtra("data")) {
Bitmap bitmap = (Bitmap) intent.getExtras().get("data");
if (bitmap != null) {
ivThumbnailPhoto.setImageBitmap(bitmap);
}

}
break;
}
}

Well let's explain this, i use the switch to verify which case is, if the case is we need to check, only for safety reasons if the resultCode is RESULT_OK, this means everything work fine and the camera app give back one photo, and, also check with the intent have data, or your picture. After that you can get the bitmap and set in your imageView.

Getting the real picture

This way is more painful, but don't worry, to get the full-sized image you need to ask the user to WRITE_EXTERNAL_STORAGE permission also. after that you need to create a fileProvider to android know where he can save the picture file, go to your Manifest and add this code:

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>

Remember where is com.example.android, you need to change with your app package.

Now you need to create the resource telling the path to save the picture file, in the code above we use the name but you can change to one name as you wish, but remember to change in the provide you have create at Manifest:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>

Again you need to change com.example.package.name with the package of your app.

Ok now we can start to code, yhayy, first we need to create a file where the Android will save the picture after she was taken, ok i use the code bellow to create a random file with the name actual timeStamp, this guarantee that will never be two files with the same name:

String mCurrentPhotoPath;

private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);

// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}

You can use the with global access just to reuse the file path after. Ok now we will create the method which will call the camera to take the picture, it's like if you was trying to catch one thumbnail but with more things lol.

static final int REQUEST_TAKE_PHOTO = 1;

private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}

Like before you will have to pass a requestCode to catch the data after onActivityResult, i use the variable to do that. You need to check if the device have one camera to take the picture, you can do that with:

if (takePictureIntent.resolveActivity(getPackageManager()) != null) 

this guarantee the app will not crash if the camera is unavailable.

Again where is com.example.android you need to change to your app package!

Remember the method we created before to generate a new file? Well here we use him, to create a new file and generate an Uri where android will save the picture. Once you have create an new Uri with the path of the file you need to add this extra in your Intent to tell to Android where he can save the picture.

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);

ok now you just need to catch the data in onActivityResult:

Remember, if you try to catch the full-sized image android will not return the image or the url with the intent, to retrieve the image you need to use the file path you generate before.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
try {
switch (requestCode) {
case 0: {
if (resultCode == RESULT_OK) {
File file = new File(currentPhotoPath);
Bitmap bitmap = MediaStore.Images.Media
.getBitmap(context.getContentResolver(), Uri.fromFile(file));
if (bitmap != null) {
...Do your stuffs
}
}
break;
}
}

} catch (Exception error) {
error.printStackTrace();
}
}

Ok, remember the currentPhotoPath we save before well, here we use him to catch the file and generate an Uri which one we will transform in a Bitmap, if you need the file in another formats, you can easy find it on google.

Well done, it is not that hard ham?

Thats it. Thanks to read this post and i hope it help you. I use the Android Documentation to create the post, if you want more details about how the things work go there and enjoy.

Be brave and boldly go where no man has gone before. Let's discover the future!