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