Working with Camera on Android SDK

I wanted to write a quick custom camera android app.
Before we start to write your custom camera app, here are the things we have to aware of.
1. Detect and access Camera
2. Create a preview class
3. Build a preview layout
4. Setup Listeners for Capture
5. Capture and Save files

Lets Start…
Detecting and access Camera
In the Android project, we will have to add Camera permission and feature.
Add following lines in the Manifest.xml

<manifest> 
 <application>
 .....
 </application>
 <uses-feature android:name="android.hardware.camera" />
 <uses-permission android:name="android.permission.CAMERA" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>

This will get the Camera permission for the application.
(we are asking for permission to write to external storage so we can save image there)
Devices running android 2.3 or higher, we can access specific camera as devices could have more than 1 camera. In this example we will use the back facing camera.

Create a preview class
We create a preview class that simply extends “SurfaceView” which will allow us to show what the ‘camera’ sees.
Also, in order to capture the callback events for creating and destroying the view, which are needed for assigning the camera preview input, we will implement “SurfaceHolder.Callback” interface.

Here is the code for preview class

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

	private SurfaceHolder mSurfaceHolder;
	private Camera mCamera;

	//Constructor that obtains context and camera
	public CameraPreview(Context context, Camera camera) {
		super(context);
		this.mCamera = camera;
		
		this.mSurfaceHolder = this.getHolder();
		this.mSurfaceHolder.addCallback(this); // we get notified when underlying surface is created and destroyed
		this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //this is a deprecated method, is not requierd after 3.0
	}

	@Override
	public void surfaceCreated(SurfaceHolder surfaceHolder) {
		try {
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.startPreview();
        } catch (IOException e) {
          // left blank for now
        }

	}
	
	@Override
	public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
		mCamera.stopPreview();
		mCamera.release();
	}

	@Override
	public void surfaceChanged(SurfaceHolder surfaceHolder, int format,
			int width, int height) {
		// start preview with new settings
		try {
			mCamera.setPreviewDisplay(surfaceHolder);
			mCamera.startPreview();
		} catch (Exception e) {
			// intentionally left blank for a test
		}
	}
	
}

Build a preview layout
Let’s create a Layout where the preview is displayed and the user can click on a button to take a picture.
Change the content of the “main.xml” under the layout directory in your android app.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <FrameLayout
    android:id="@+id/camera_preview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    />

  <Button
    android:id="@+id/button_capture"
    android:text="Capture"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    />
</LinearLayout>

Now, lets wire up the Camera Activity

public class DVCameraActivity extends Activity {
	
	private Camera mCamera;
	private CameraPreview mCameraPreview;
    
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mCamera = getCameraInstance();
        mCameraPreview = new CameraPreview(this, mCamera);
        
        FrameLayout preview = (FrameLayout) findViewById(id.camera_preview);
        preview.addView(mCameraPreview);
        
    }

    /**
     * Helper method to access the camera returns null if
     * it cannot get the camera or does not exist
     * @return
     */
	private Camera getCameraInstance() {
		Camera camera = null;

		try {
			camera = Camera.open();
		} catch (Exception e) {
			// cannot get camera or does not exist
		}
		return camera;
	}
}

At this point if you run your application, you will see what the camera sees.
To make something meaningful, lets add listener to capture the image.

Setup Listeners for Capture
In order for us to take the picture, we will have to setup the listeners.
Lets make a inner class inside the Activity we created above,

PictureCallback mPicture = new PictureCallback() {

		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
			 File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
		        if (pictureFile == null){
		            return;
		        }

		        try {
		            FileOutputStream fos = new FileOutputStream(pictureFile);
		            fos.write(data);
		            fos.close();
		        } catch (FileNotFoundException e) {

		        } catch (IOException e) {
		        
		        }
			
		}
		
	};

It is using a helper method called, “getOutputMediaFile”, here is the code for that

/** Create a File for saving the image */
	private static File getOutputMediaFile(){

	    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
	              Environment.DIRECTORY_PICTURES), "MyCameraApp");

	    if (! mediaStorageDir.exists()){
	        if (! mediaStorageDir.mkdirs()){
	            Log.d("MyCameraApp", "failed to create directory");
	            return null;
	        }
	    }

	    // Create a media file name
	    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
	    File mediaFile;
	        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
	        "IMG_"+ timeStamp + ".jpg");

	    return mediaFile;
	}

Let’s wire up the listener onCreate method

 //Adding listener
        Button captureButton = (Button) findViewById(id.button_capture);
        captureButton.setOnClickListener(
        		new View.OnClickListener() {
					
					@Override
					public void onClick(View v) {
						mCamera.takePicture(null, null, mPicture);
						
					}
				});

After you have all this wired, the application i ready to fire up some pictures.

Resources:
http://developer.android.com/guide/topics/media/camera.html
http://developer.android.com/guide/topics/media/camera.html#custom-camera

Advertisements

9 thoughts on “Working with Camera on Android SDK

  1. Thanks! Very Helpful for me.
    would you tell me how can I start the camera to capture a video and access eatch frame. Thanks in Advance. 🙂

  2. Thank you! But can you suggest some way to save the image as a BITMAP image… and also if I don’t want to save the picture on external sd card, what changes should I make.?

  3. i run the code in nexus 4(kitkat)…camera preview is not proper.preview shifted to angle 90 degree,, i do not have any other phone to run

    1. this is normal missing just one little thing :
      add “mCamera.startPreview();” AFTER the catch in the inner class PictureCallback ….
      you also can try this (aalways AFTER the catch):
      try {
      Thread.sleep(2000);//see the picture taken during 2 sec
      }
      catch (InterruptedException e) {
      e.printStackTrace();
      }
      mCamera.startPreview();//back to see in real time

      sorry for my english 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s