Amazon Gift Cards

Saturday, October 30, 2010

Take Picture in Android with MediaStore.ACTION_IMAGE_CAPTURE

Previously in Android when you want to capture an Image, you have to use SurfaceView and SurfaceHolder to preview the camera. MediaStore.ACTION_IMAGE_CAPTURE was introduced in Cupcake, Android 1.5, and has been the default way to capture images captured in Android.

What Do I Need
In Manafiest.xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

In your activity
private static final int TAKE_PHOTO_CODE = 1;

private void takePhoto(){
  final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(this)) ); 
  startActivityForResult(intent, TAKE_PHOTO_CODE);
}

private File getTempFile(Context context){
  //it will return /sdcard/image.tmp
  final File path = new File( Environment.getExternalStorageDirectory(), context.getPackageName() );
  if(!path.exists()){
    path.mkdir();
  }
  return new File(path, "image.tmp");
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (resultCode == RESULT_OK) {
    switch(requestCode){
      case TAKE_PHOTO_CODE:
        final File file = getTempFile(this);
        try {
          Bitmap captureBmp = Media.getBitmap(getContentResolver(), Uri.fromFile(file) );
          // do whatever you want with the bitmap (Resize, Rename, Add To Gallery, etc)
        } catch (FileNotFoundException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        }
      break;
    }
  }
}


Ads from Amazon:
Explanation
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempFile(this) );
startActivityForResult(intent, TAKE_PHOTO_CODE);

This is the core of the code, here we call an intent from the MediaStore which would open up the camera app, then we pass the output path of the captured image to a temporary location (Always use a safe location to store the image). Here we use the Environment.getExternalStorageDirectory() which is our SDCard, again for safety reason check if the SDCard is present or not. Then we start the activity, expecting a result with code TAKE_PHOTO_CODE

final File file = getTempFile(this);
try {
Bitmap captureBmp = Media.getBitmap(getContentResolver(), Uri.fromFile(file) );
}...{}

Knowing where the output of the file will be, we would open that file and place it on a bitmap where we would do our magic

Conclusion
ACTION_IMAGE_CAPTURE has done a great job so that we wont implement our own implementation of the camera app, so use it.

Update History
   Jan 17, 2012 - Visual Update

12 comments:

lethargicpanda said...

Thanks for your article it's been very useful !

But it seems that you should use :

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(this)) );

in your MediaStore.ACTION_IMAGE_CAPTURE instead of :


intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempFile(this));

Cheers !

Anonymous said...

leaves a file not found exception:
11-05 14:50:07.929: WARN/System.err(5806): java.io.FileNotFoundException: /mnt/sdcard/packagename/image.tmp (No such file or directory)

Almond said...

@lethargicpanda thanks, updated the post :)

@anonymouse, what version of Android are you using? and are you using the emulator?

Anonymous said...

In the line
try {Bitmap captureBmp = Media.getBitmap(getContentResolver(), Uri.fromFile(file) );

You mention you could rename the file, how would you do that? The images are being saved onto my phone with an odd format, which makes it difficult to recall them later in the app i'm creating. I appreciate the help.

Almond said...

@anonymous the line new File(path, "image.tmp"); would make the file into .tmp format, just change this one to .png or .jpg :)

Anonymous said...

After adding the .png or .jpg instead of the tmp and i take a picture, the picture is stored on my phone but with a crazy name. Searchign the phone for the image name comes up blank.

I'm attemping to store the names of pictures in a database, but without knowing the exact name this is very difficult. any help is appreciated.

Almond said...

@Anonymous when you save an image the file is saved on the storage but not the on the gallery application, see this stackoverflow answer http://stackoverflow.com/questions/2170214/image-saved-to-sdcard-doesnt-appear-in-androids-gallery-app

José Luis said...

Hi, thank you very much for the tutorial. I've implemented this on my app and tested in my wildfire (Android 2.1) and the image is automatically added to the Gallery. But that's the opposite of what I want, because I need my application to be the only one with access to those photos. Is it any way to intercept the file and just store in the SD card without add to the Gallery?

Anonymous said...

How to get the orientation of the captured image?

Gaurav said...

I am getting FileNotFoundException





java.io.FileNotFoundException: /mnt/sdcard/com.clarice.corel/image.png (No such file or directory)
W/System.err(11167): at org.apache.harmony.luni.platform.OSFileSystem.openImpl(Native Method)
W/System.err(11167): at org.apache.harmony.luni.platform.OSFileSystem.open(OSFileSystem.java:152)
W/System.err(11167): at java.io.FileInputStream.(FileInputStream.java:82)

Mike said...

Hi why TAKE_PHOTO_CODE is in red line in my eclipse? thanks

spierala said...

Hey thanks,
that was the first example that worked from the beginning. I had problems to capture picture directly at full resolution. that does not seem to work. but your way is exactly what i needed!
cheers,
flo