Monday, November 24, 2008

Camera Capture

Source code can be downloaded below.

Before creating the Image Capture application, the SDCard must be configured first in order to be able to save in the Picture Gallery of the emulator.

Creating the SDCARD

1. See the emulator -help-sdcard to see where the default sdcard.img is located. Create if necessary.



2. Type mksdcard in the command line to know the required switches in the command-line.


3. Make SD Card.


4. For my SD Card, I just went to the default folder on step#1 and created the default SD-Card.
-cd to the default sd directory
-mksdcard 16M sdcard.img

*Note: the minumum SD required by the emulator is 8Megabytes, I just used 16M to make sure. Also, the higher the size of the SD, the longer it takes to create. So, when you create a 4GB SD, the command line might seem unresponsive.


I've been trying to figure out how to capture images in android and storing it in the picture gallery for 2 weeks now.

I just discovered, that there is nothing wrong with the code, but there's something wrong with the emulator.

For one thing, I keep on getting this image, even when using the built in Camera Application on the main menu. But, I think it is normal. Is it?


The problem I am having is that when I capture an image in the application, the File Explorer (sdcard/dcim/Camera) does save the image file. But when I check the gallery, it does not seem to exist. I then try to push an image to the emulator's file system (sdcard/dcim/Camera), but still the Picture Gallery does not reflect. Below, is a screenshot of what (sdcard/dcim/Camera) contains and what shows in the emulator's picture gallery.



When I restarted the emulator, the Picture Gallery reflected the content's of the file system. Is this a bug or did I just missed a step?


Anyways, here's the code I compiled from various sources using Google Android SDK 1R1.

http://www.anddev.org/viewtopic.php?p=704#704
http://www.anddev.org/viewtopic.php?p=645#645

I also used another site but I forgot the link. So if you see your code here, just drop me a message and I'll link you up as reference. I think the file I downloaded was CameraTestApi.zip but was based on an older SDK. I apologize for the author of the code that I based my revised Image Capture application.


Here the code for the Image Capture Application.

1. Create two classes.
ImageCapture.java


public class ImageCapture extends Activity implements SurfaceHolder.Callback
{
private Camera camera;
private boolean isPreviewRunning = false;
private SimpleDateFormat timeStampFormat = new SimpleDateFormat("yyyyMMddHHmmssSS");

private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Uri target = Media.EXTERNAL_CONTENT_URI;

public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
Log.e(getClass().getSimpleName(), "onCreate");
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.main);
surfaceView = (SurfaceView)findViewById(R.id.surface);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public boolean onCreateOptionsMenu(android.view.Menu menu) {
MenuItem item = menu.add(0, 0, 0, "goto gallery");
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(Intent.ACTION_VIEW, target);
startActivity(intent);
return true;
}
});
return true;
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
}

Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
Log.e(getClass().getSimpleName(), "PICTURE CALLBACK RAW: " + data);
camera.startPreview();
}
};

Camera.PictureCallback mPictureCallbackJpeg= new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
}
};

Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
Log.e(getClass().getSimpleName(), "SHUTTER CALLBACK");
}
};


public boolean onKeyDown(int keyCode, KeyEvent event)
{
ImageCaptureCallback iccb = null;
if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
try {
String filename = timeStampFormat.format(new Date());
ContentValues values = new ContentValues();
values.put(Media.TITLE, filename);
values.put(Media.DESCRIPTION, "Image capture by camera");
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
//String filename = timeStampFormat.format(new Date());
iccb = new ImageCaptureCallback( getContentResolver().openOutputStream(uri));
} catch(Exception ex ){
ex.printStackTrace();
Log.e(getClass().getSimpleName(), ex.getMessage(), ex);
}
}
if (keyCode == KeyEvent.KEYCODE_BACK) {
return super.onKeyDown(keyCode, event);
}

if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
camera.takePicture(mShutterCallback, mPictureCallbackRaw, iccb);
return true;
}

return false;
}

protected void onResume()
{
Log.e(getClass().getSimpleName(), "onResume");
super.onResume();
}

protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
}

protected void onStop()
{
Log.e(getClass().getSimpleName(), "onStop");
super.onStop();
}

public void surfaceCreated(SurfaceHolder holder)
{
Log.e(getClass().getSimpleName(), "surfaceCreated");
camera = Camera.open();
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.e(getClass().getSimpleName(), "surfaceChanged");
if (isPreviewRunning) {
camera.stopPreview();
}
Camera.Parameters p = camera.getParameters();
p.setPreviewSize(w, h);
camera.setParameters(p);
camera.setPreviewDisplay(holder);
camera.startPreview();
isPreviewRunning = true;
}

public void surfaceDestroyed(SurfaceHolder holder)
{
Log.e(getClass().getSimpleName(), "surfaceDestroyed");
camera.stopPreview();
isPreviewRunning = false;
camera.release();
}
}


ImageCaptureCallback.java


public class ImageCaptureCallback implements PictureCallback {

private OutputStream filoutputStream;
public ImageCaptureCallback(OutputStream filoutputStream) {
this.filoutputStream = filoutputStream;
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
Log.v(getClass().getSimpleName(), "onPictureTaken=" + data + " length = " + data.length);
filoutputStream.write(data);
filoutputStream.flush();
filoutputStream.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}


2. Create the main.xml as shown below









3. Add a camera permission to the ApplicationManifest




Source Code

21 comments:

Mikey said...

hmm, yeah its a bit difficult to code in the new sdk when your resources are old like in the net hahaha, im also doing android for some time

shak said...

I heard the solution for your problem is to update sdcard with 'MediaScannerConnection'. Have you been able to fix with that?

Unknown said...

Hi ,

I cant view the pictures taken by the camera in pictures gallery.
Also i am unable to open sdcard folder using eclipse plugin.

java.padawan said...

Hi Chetan,

"I heard the solution for your problem is to update sdcard with 'MediaScannerConnection'. Have you been able to fix with that?"

This is what shak said, but I have not tested it yet as I am losing interest in programming the Camera API until I get the HTC Dream.

I'll create more tutorial though, once the G2 or HTC Dream is available.

refactor said...

Have you ever tried Google's Camera app?
Its pictures are reflected to the gallery without reboot.

Anyway, this article helps me a lot. Thanks.

srikanth said...

When I run above code on mobile I am getting error.Could you please solve my problem.
"The application Image capture has stopped unexpectedly"

sri_reddy523@yahoo.com

java.padawan said...

Hi srikanth,
I have not encountered your problem. Check your DDMS persepective logs, and post the exception/error here.

srikanth said...

errors in log are:
Could not read initial storage
flash_image : Cant find recovery partition
Memory/Heap base : error opening dev/mem no such memory or directory
System : Failure starting status service
System : Security exception
Android Runtime : Crash logging skipped
Android Runtime : at javapadawn.Imagecapture.oncreate(Image capture:37)

srikanth said...

In emulator Display error message as follows

The application Image capture(process javapadwan.android) has stopped unexpectedly.Please try again

java.padawan said...

Email me at java.padawan@androidph.com, with the screenshots and stack trace etc.

Anyways, did you do the steps in creating the sdcard?

I'll try to look at it over the weekend.

srikanth said...

Thanks for reply

ya i have created sd card steps as you have given in slide.
SD card directory located in SDk_1.1 folder

Unknown said...

I have tried this code in my application. it is running perfectly fine.. the only problem i am getting is of focus. camera is not getting focused properly before we click for a image.As a result I m getting all blurt images. how do I fix it?

java.padawan said...

Hi pranav,

I'm sorry, I don't have an android phone yet, and I'm probably getting one soon. So until then, I cannot debug/fix anything.

I'll fix my post as soon as the G2 is available here.

-ice

K20 said...

Hi,

I use your code for my application, i use SDK 1.5r3

It work but i have a problem ...

The picture file name is the timestamp of the taken date of the picture not the title that i have entered oO

Have you a solution ?

And for the problem of no refresh of gallery picture you must use MediaScannerConnectionClient, it works with G2 ;)

wahib_techi said...

i have worked out the sdcard instructions and used the code exactly as given. The image is taken from app but it isnt saved or not shown in the gallery :( i am unable what do u mean by "update sdcard with MediaScannerConnection". Kindly help as i am a newbie.

Regards,
wahib

Bob Penrod said...

You can read some discussion about the MediaScannerConnection at http://groups.google.com/group/android-developers/browse_thread/thread/61f14ee847bb64e5

The code posted there fixed the image-missing-in-the-gallery problem on the HTC Hero.

Unknown said...

The file (jpg) is stored with future date (1h+). It is not UTC time beacuse UTC is 1h- (for me)

Anonymous said...

Android 1.6 sdk version 4: epic fail
Code doesn't work. Force quits.

Anonymous said...

It took me a while to make this work... I found this tutorial very useful:
http://develnetwork.blogspot.com/2010/11/how-to-take-full-size-picture-in.html

Anonymous said...

i tryed it it works but i cant see the views from my web cam i can just see the black and white patterns

md jawad said...

hey friends i m mohammed i have tried camera with the help of intent but i m not getting an camera viewer so any one want to help plz sent the code in this id md_jawad30@yahoo.com

Email

java.padawan@androidph.com