Basically in a camera application, you need a camera surface and a button to take photos. First we start with getting required permission for Camera component. Also put a control into the activity tag to keep screen in landscape mode.
<uses-permission
android:name = "android.permission.CAMERA"/>
<activity .......
android:screenOrientation="landscape" ...... >
Then we create a simple layout includes a SurfaceView and a Button.
<?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">
<SurfaceView
android:id="@+id/preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
</SurfaceView>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/buttonTakePhoto"
android:text="Click"
android:gravity="center">
</Button>
</LinearLayout>
Now we are ready to build our application to put the camera preview into our SurfaceView and to set the button's behavior for taking photos. Our activity must implement the SurfaceHolder.Callback interface in order to provide a camera preview.
// Let's name our Activity as CamDroid.
public class CamDroid extends Activity implements SurfaceHolder.Callback
Then we create our Camera, Surface and Button fields which will be initialized when our activity is started.
private Camera mCamera;
private Button takePictureButton;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
After this fields we need to declare which actions will be performed when user takes a photo.
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
FileOutputStream outStream = null;
try {
// Directory and name of the photo. We put system time
// as a postfix, so all photos will have a unique file name.
outStream = new FileOutputStream("/sdcard/CamDroid_" +
System.currentTimeMillis()+".jpg");
outStream.write(data);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.e(TAG, "PICTURE CALLBACK: data.length = " + data.length);
mCamera.startPreview();
}
};
Now we can implement the onCreate method of the Activity to initialize our surface and Button.
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
// We don't need a title for our camera window.
// It makes our view smaller.
requestWindowFeature(Window.FEATURE_NO_TITLE);
Log.e(TAG, "onCreate");
getWindow().setFormat(PixelFormat.TRANSLUCENT);
// In my case, name of the layout file is camdroid.xml
setContentView(R.layout.camdroid);
// Initialize the surface
mSurfaceView = (SurfaceView)findViewById(R.id.preview);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// Initialize the Button
takePictureButton = (Button)findViewById(R.id.buttonTakePhoto);
// Set the button's behavior
takePictureButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mCamera.takePicture(null, null, mPictureCallback);
}
});
}
Then we must provide some methods for our surface to create first preview, change preview, and stop preview.
// Create camera preview.
public void surfaceCreated(SurfaceHolder holder)
{
Log.e(TAG, "surfaceCreated");
mCamera = Camera.open();
//mCamera.startPreview();
}
// Change preview's properties (i.e. size or format).
public void surfaceChanged(SurfaceHolder holder,
int format, int w, int h)
{
Log.e(TAG, "surfaceChanged");
// XXX stopPreview() will crash if preview is not running
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(w, h);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
// Stop the preview.
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.e(TAG, "surfaceDestroyed");
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
Now we have a basic camera application which has a camera preview and a button on screen. You can start taking photos with your applications by pressing the button on the screen. Or you can add this method to use your device's built-in "OK" Button (Trackpad for HTC, OK Button for Samsungs etc.) for taking photos.
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK) {
return super.onKeyDown(keyCode, event);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
mCamera.takePicture(null, null, mPictureCallback);
return true;
}
return false;
}
ScreenShot:
Enjoy your new camera applications and take good photos :)