Working with Still Images - Android

We illustrated how to display still images such as bitmaps by using the ImageView widget in Chapter “Exploring User Interface Screen Elements.” If the user’s handset has built in camera hardware, the user can also capture still images using the Camera object of the Android SDK. In addition, you can assign images as the home screen wallpaper using the WallpaperManager class.

Capturing Still Images Using the Camera

The Camera object (android.hardware.Camera) controls the camera on handsets that have camera support enabled. The preview feature of the camera relies on the assignment of a SurfaceHolder of an appropriate type. This enables applications to control the placement and size of the preview area that the camera can use.

Follow these steps to add camera capture capability to an application without having to draw preview frames (the CameraSurfaceView displays the camera view):

  1. Create a new class extending SurfaceView and implement SurfaceHolder.Callback. For this example,we name this class CameraSurfaceView.
  2. In the surfaceCreated() method, get an instance of the Camera object.
  3. In the surfaceChanged() method, configure and apply the Camera.Parameters; then call the startPreview() method.
  4. Add a method in CameraSurfaceView for capturing images.
  5. Add the CameraSurfaceView to an appropriate layout.
  6. Include some way, such as a button, for the user to trigger the capturing of images.
  7. Implement a PictureCallback class to handle storing of the captured image.
  8. Add the android.permission.CAMERA permission to the AndroidManifest.xml file.
  9. Release the Camera object in the surfaceDestroyed() method.

Let’s start by looking at the CameraSurfaceView class:

import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
private class CameraSurfaceView extends SurfaceView
implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera camera = null;
public CameraSurfaceView(Context context) {
mHolder = getHolder();
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
public void surfaceCreated(SurfaceHolder holder) {
public void surfaceDestroyed(SurfaceHolder holder) {
public boolean capture(Camera.PictureCallback
jpegHandler) {

The constructor for the CameraSurfaceView configures the SurfaceHolder, including setting the SurfaceHolder type to SURFACE_TYPE_PUSH_BUFFERS, which is used by the camera internals. The constructor is appropriate for calling from an activity’s onCreate() method. When the display is ready, the surfaceCreated() method is called. Here we instantiate the Camera object:

public void surfaceCreated(SurfaceHolder holder) {
camera =;

The Camera object has a static method to retrieve a usable instance. Because the Surface is now available, the configured holder can now be assigned to it. Information about the Surface might not yet be available, but at the next call to the surfaceChanged() method, the camera parameters will be assigned and the preview will start, as shown here:

public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
Camera.Size pickedSize = getBestFit(sizes, width, height);
if (pickedSize != null) {
params.setPreviewSize(pickedSize.width, pickedSize.height);

The surfaceChanged() method provides the application with the proper width and height for use with the camera preview. After assigning this to the Camera object, the preview starts. At this point, the users see whatever is in front of the camera on their device. If, however, you debug this within the emulator, you see a black- and- white checkerboard with an animated square on it, as shown in Figure.This is the simulated camera preview, so camera testing can take place, to some extent, on the emulator.

When the Surface is no longer displayed, the surfaceDestroyed() method is called.Here is an implementation of the surfaceDestroyed() method suitable for this example:

public void surfaceDestroyed(SurfaceHolder holder) {
camera = null;

In the surfaceDestroyed() method, the application stops the preview and releases the Camera object. If the CameraSurfaceView is used again, the surfaceCreated() method is called again, so this is the appropriate place to perform this operation.

The final step required to capture a still image is to add some way to call the takePicture() method of the Camera object. CameraSurfaceView could provide public access to the Camera object, but in this example, we provide a method to perform this within the CameraSurfaceView class:

public boolean capture(Camera.PictureCallback jpegHandler) {
if (camera != null) {
camera.takePicture(null, null, jpegHandler);
return true;
} else {
return false;

Emulator screen showing simulated

Emulator screen showing simulated

camera view.
You can also use the takePicture() method to assign a callback suitable to play a shutte sound, or any other action just before the image is collected from the sensor. In addition, you can assign a PictureCallback to get raw data from the camera.

The CameraSurfaceView object is now ready for use within an Activity. For this example, an Activity with a layout that contains a FrameLayout widget for positioning the preview is used. Here is a sample implementation of assigning the cameraView to the layout:

final CameraSurfaceView cameraView = new
FrameLayout frame = (FrameLayout) findViewById(;

Next, a button click handler calls the capture() method of the CameraSurfaceView object. A sample implementation is shown here:

public void onClick(View v) {
cameraView.capture(new Camera.PictureCallback() {
public void onPictureTaken(byte[] data,
Camera camera) {
FileOutputStream fos;
try {
String filename = “capture.jpg”;
fos = openFileOutput(“capture.jpg”,
} catch (Exception e) { Log.e(“Still”, “Error writing file”, e);

The data that comes back from the callback can be written out directly to a JPEG file within the application file directory. If written as shown, though, the captured image is usable only by the application. In some cases, this might be suitable. However, the application might want to share the image with the rest of the handset, for example, by including it within the Pictures application, which uses the MediaStore content provider. You do this by using the ContentResolver object to place an entry for the image in the media library.

Configuring Camera Mode Settings

You can use the Camera class to configure the specific capture settings for a picture. Many of the capture settings are stored in the Camera. Parameters class, and set in the Camera using the setParameters() method.

Working with Common Camera Parameters

Let’s take a closer look at the Camera. Parameters class. Some of the most interesting camera parameters are

  • Flash modes (where flash hardware is available)
  • Focus types (fixed point, depth of field, infinity, and so on)
  • White balance settings (fluorescent, incandescent, and so on)
  • Scene modes (snow, beach, fireworks, and so on)
  • Effects (photo negative, sepia, and so on)
  • Anti-banding settings (noise reduction)

Different parameters are supported by different devices, so always check for support before trying to enable parameters. Use the Camera. Parameters class to determine what camera features are supported. For example, you can use the set of methods called getSupportedFlashModes(), getSupportedFocusModes(), and so on. Also, the Camera. Parameters class contains methods to access more technical camera settings, such as exposure compensation and EXIF information.

Zooming the Camera

The camera zoom setting is controlled using the startSmooth Zoom() and stopSmooth Zoom() methods of the Camera class. As you might expect, you can set zoom parameters using the Camera.Parameters class. Useful zoom methods in the Camera. Parameters class include

  • Determining if zooming is supported with isZoomSupported()
  • Determining if smooth zooming is supported with isSmoothZoomSupported()
  • Determining the maximum zoom value with getMaxZoom()
  • Retrieving the current zoom value with getZoom()
  • Setting the current zoom value with setZoom()
  • Calculating the zoom increments (for example, 1x, 2x, 10x) with getZoomRatios()

Depending on the features available for a specific camera, zoom might be digital, optical, or some combination of the two.

Sharing Images

Storing an image in the local application directory, as demonstrated, might work for some applications; however, other applications might find it useful if the image goes in the shared image library on the device. The ContentResolver can be used in conjunction with the MediaStore object to push the image into the shared image library. The following example demonstrates storing the still image taken by the camera as an image file within the MediaStore content provider, using the same camera image callback:

public void onPictureTaken(byte[] data, Camera camera) {
Log.v(“Still”, “Image data received from camera”);
try {
Bitmap bm = BitmapFactory.decodeByteArray(
data, 0, data.length);
String fileUrl = MediaStore.Images.Media.
insertImage(getContentResolver(), bm,
“Camera Still Image”,
“Camera Pic Sample App Took”);
if (fileUrl == null) {
Log.d(“Still”, “Image Insert failed”);
} else {
Uri picUri = Uri.parse(fileUrl);
sendBroadcast(new Intent(
} catch (Exception e) {
Log.e(“Still”, “Error writing file”, e);

The image is turned into a Bitmap object, which is passed into the insertImage() method. This method creates an entry in the shared image library. After the image is inserted, we use the returned URL to create a Uri object representing the new image’s location, which we instruct the Media Scanner to pick up by broadcasting a specialized intent. To determine if the scan completed successfully, you can make a call to the static MediaScanner Connection.scanFile() method, and provide a MediaScanner Connection.OnScanCompleted Listener class implementation.

Now the image is available to all applications that use the MediaStore content provider, such as the Pictures application.

Assigning Images as Wallpapers

Wallpapers are a great way for users to personalize their phones with interesting and fun images. The WallpaperManager class is used for all wallpaper interaction. You learn more about it in Chapter “Extending Android Reach,” when you create Live Wallpaper. For now, use it to set still image wallpapers.

The current wallpaper can be retrieved with a call to the getDrawable() or peekDrawable() methods.The methods getDesiredMinimumHeight() and getDesired MinimumWidth() enable the application to programmatically determine the size that a wallpaper should be on the particular handset. Finally, you can assign wallpaper through the setResource(), setBitmap(), and setStream() methods.

The following callback of the Camera object sets the wallpaper:

public void onPictureTaken(byte[] data, Camera camera) {
Bitmap recordedImage =
BitmapFactory.decodeByteArray(data, 0, data.length);
try {
WallpaperManager wpManager = WallpaperManager
} catch (Exception e) {
Log.e(“Still”, “Setting wallpaper failed.”, e);

The image is copied locally for the wallpaper, so the original doesn’t need to be kept, which is good in this case because it was never written to disk. You can remove the wallpaper completely with a call to the clear() method.

Finally, your application needs the android.permission.SET_WALLPAPER permission within the AndroidManifest.xml file.

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd Protection Status

Android Topics