How to use the Android Camera

I have now spent quite a few hours programming for my next app which needs to take pictures. I did not want to use the camera app that’s already there for several reasons. So I need to programm my own. The API is not all that difficult to understand. Here’s the basic version of how to talk to the camera:

[sourcecode language=”java” wraplines=”true”]
//creating the camera object
Camera camera = Camera.open();
camera.setPreviewDisplay(getSurfaceHolder());
final Camera.Parameters parameters = findBestParameters(w, h);
camera.setParameters(parameters);
camera.startPreview();
final PictureCallback callback = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
//async task for storing the photo
new SavePhotoTask(CameraView.this.ctx, data).execute();
} catch (final SavePhotoException e) {
//some exceptionhandling
}
}
};
//no need for shutter callback or raw callback, jpg callback is enough
camera.takePicture(null, null, callback);
[/sourcecode]

Doesn’t sound so hard? It only took me hours to get it right. Because I never got to the onPictureTaken(...) method. The callback never happend! I made the mistake wanting to do something else after taking the picture – who wouldn’t?

There are several issues with that. It takes the phone quite a while (~5 seconds) to actually take that picture once the camera.takePicture(...) method is called. Since the method is an asynchronous callback you can do all kinds of fun things(tm), while waiting for the result. For example I managed to execute some very important piece of code:

[sourcecode language=”java” wraplines=”true”]
public void clearCamera() {
if (this.camera != null) {
try {
this.camera.stopPreview();
this.camera.release();
this.camera = null;
} catch (final Exception e) {
//handle some exceptions
}
}
}
[/sourcecode]

This should be called by onPause() of your activity (and onResume() you should of course re-open the camera!). So if for some reason while you do the fun things(tm) I mentionned above your activity decides to take a break, the callback never happens! Ouch.

So how did I get my activity to wait for the callback and then do something?

In the first code sample you can see that the actual picture storing takes place in a class called SavePhotoTask. This class is an asynchronous task that offers the functionality I needed. Please notice that since the first code sample some things changed and the task now also implements the callback interface:

[sourcecode language=”java” wraplines=”true”]
public class SavePhotoTask
extends AsyncTask<Boolean, Void, File>
implements PictureCallback {

//fill in the rest as a light exercise at home
private final ProgressDialog dialog;

@Override
protected void onPreExecute() {
this.dialog.setMessage(String.format("Saving Picture"));
this.dialog.show();
}

@Override
protected File doInBackground(Boolean… params) {
this.camera.takePicture(null, null, this);
return this.spot.getPhoto();
}

@Override
protected void onPostExecute(final File success) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
if (success != null && success.exists()) {
DialogFactory.keepPhotoDialog(this.ctx, this.photo).show();
} else {
Toast.makeText(this.ctx, "You failed!", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
//I guess you know how to save a file
saveFile(data);
} catch (final Exception e) {
//capture flying shit
}
}
}
[/sourcecode]

So now I can execute my picture taking as an asynchronous task, that gets a callback to onPostExecute(...) when it is finished. I can then open another dialog prompting the user to do something. I introduced that additional dialog to get a break before leaving the original activity (remember how leaving will close the camera and we should not do it before the picture is stored safely on the sdcard).

So to keep it complete, here’s the final piece of code: the dialog.

[sourcecode language=”java” wraplines=”true”]
public static AlertDialog keepPhotoDialog(final Activity a, final MyPhoto photo) {
final AlertDialog.Builder builder = new AlertDialog.Builder(a);
builder.setMessage("Keep photo?");
builder.setCancelable(false);
builder.setPositiveButton("yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
final Intent i = new Intent(a, DoFunThingsActivity.class);
i.putExtra(DoFunThingsActivity.PHOTO, photo);
a.startActivity(i);
}
});
builder.setNegativeButton("no", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
final File file = new File(photo.getFilename());
if (file.exists()) {
file.delete();
}
dialog.dismiss();
//you might want to call startPreview() again at this point
}
});
return builder.create();
}
[/sourcecode]

So here’s it, I chained two dialogs to take a picture and do fun things(tm) with it later without having to start handle threads and all that stuff.

Any questions?

This entry was posted in android. Bookmark the permalink.

5 Responses to How to use the Android Camera

  1. Dake says:

    I’m browsing the internet to look for a very simple ready to run code of a camera example. So far I only find snippets with blanks. Suggestion, be complete and post your entire code.

    Going back to google.com

    • Sonja says:

      This is part of an on-going work-project of mine, I am very sorry that I am unable to provide you with complete “ready-to-run” code.

    • John says:

      What if you stopped being lazy and actually took the time to read developer.android.com. Sonja is simply trying to help and she did a great job demonstrating a “topic” few developers take into account.

  2. Pingback: Android : Method onPictureTaken never called, even with AsyncTask : Android Community - For Application Development

  3. Jakub says:

    hi, what does the line return this.spot.getPhoto(); do? I guess it is the key line is it?