Você está na página 1de 8

Android Application Development Training Tutorial

For more info visit http://www.zybotech.in

A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

Tutorial: Creating a Camera Application


There are a few concepts that would be helpful in starting to make the camera interface. In general, to make any such application, we need to find the specific programming through which the device is exposed to us.

It is CameraDevice class in Android. Various parameters can be passed to the CameraDevice to customize how the picture is taken. The output should be projected on some sort of View Class, which is provided by SurfaceView, an extension of the View class. Saving the file to the file system uses an OutputStream to create the required files in the system. JPG and PNG are allowed. The image quality needs to be assigned at the time though.

Contents

1 Starting out 2 Understanding the code 3 Modifications o 3.1 Runnable methods o 3.2 Listening to KeyStrokes

Starting out
Create a new Project in Eclipse titled "MyCamera". Follow the instructions at Creating a project in Eclipse for Android. Select the MyCamera.java file and copy the text of into it. Another method: look into the Graphics section of your android_installation_directory/samples for the same file. Change the class name from CameraPreview to MyCamera. Remember to change the package name to org.hfoss.MyCamera Test 1: You should be able to see the moving box in front of the checkered background.

Understanding the code


It is necessary to understand the code here.

Open up the eclipse outline view from Window>Show View>Outline. You should be able to see that

there are two classes defined here. MyCamera and Preview; Preview being the subclass of MyCamera here.

Expand Preview. You should be able to see PreviewThread class here. Take a look at the following method.

public void run() { // We first open the CameraDevice and configure it. CameraDevice camera = CameraDevice.open(); if (camera != null) { CameraDevice.CaptureParams param = new CameraDevice.CaptureParams(); param.type = 1; // preview param.srcWidth = 1280; param.srcHeight = 960; param.leftPixel = 0;

A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

param.topPixel = 0; param.outputWidth = 320; param.outputHeight = 240; param.dataFormat = 2; // RGB_565 camera.setCaptureParams(param); } // This is our main acquisition thread's loop, we go until // asked to quit. SurfaceHolder holder = mHolder; while (!mDone) { // Lock the surface, this returns a Canvas that can // be used to render into. Canvas canvas = holder.lockCanvas(); // Capture directly into the Surface if (camera != null) { camera.capture(canvas); } // And finally unlock and post the surface. holder.unlockCanvasAndPost(canvas); } // Make sure to release the CameraDevice if (camera != null) camera.close(); }

The CameraDevice class is used to open the camera driver, set image parameters and to capture a preview frame or full resolution image (Currently 1280*1024 pixels). Calling the open() static class will return a CameraDevice object. For more detailed information, see CameraDevice Documentation The following code in Preview installs a SurfaceHolder.Callback to notify for any changes in the surface. {
mHolder = getHolder(); mHolder.addCallback(this);

} In line 156:161 in the code, you'd find this code(Hint: use Ctrl+L in eclipse) which gets a Canvas object from the SurfaceHolder and captures the image from the camera. Then the camera device is closed and the surface is posted.

Modifications
To save a file, we need to make a new Canvas. Unlike the SurfaceView one, it wont be displayed on the screen but it will point to a Bitmap object that will be saved to the device. Copy the following code to the file:
private void takePicture() { if (camera != null) { camera.setCaptureParams(param); Bitmap myPic = Bitmap.createBitmap(param.outputWidth, param.outputHeight, false); Canvas canvas = new Canvas(myPic); camera.capture(canvas);

try { OutputStream outStream = this.openFileOutput("pic" + count + ".png", Context.MODE_WORLD_READABLE); myPic.compress(Bitmap.CompressFormat.PNG, 100, outStream); outStream.close(); } catch (IOException e) { Log.e(TAG, e.toString()); } camera.close(); } else { Log.e(TAG, "Failed to open camera device"); return; } } Here, we take the same approach that the thread takes in displaying the picture but instead of displaying it to a screen object we are saving it into a Bitmap and then to a file using the OutputStream.
A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

Runnable methods
Whenever we design a dynamic application like this, especially something that deals with hardware(I/O) and we want our application be robust during the transaction, we run these objects as threads. Android provides the Runnable class for this where a Runnable Object is declared with the threads that need to be run. Hence, we declare a mTakePicture object with the following actions, first we want to pause the preview, take the picture and resume. final Runnable mTakePicture = new Runnable() { public void run() {
mPreview.pause(); takePicture(); mPreview.resume(); } };

Listening to KeyStrokes
We need to have some way to Listen for user interactivity. For this, we need to add a onKeyDown method. Right Click anywhere in eclipse editor and select Source>Override/Implement methods ... Type onKeyDown, until public boolean onKeyDown(int, KeyEvent). Click the checkbox and click the ok button, the new overriden method should be added there. We detect key events in android by comparing the key Codes supplied to the onKeyDown method. The code goes like this: switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER: mPreview.post(mTakePicture); break; case KeyEvent.KEYCODE_BACK: finish(); break;

} return false; Here mPreview.post() method adds the Runnable object in the queue of the activity to be run. It runs the Runnable function declared in the earlier step which saves the files to the file system. Test2: To check if your file is saved. To check if your file is actually saved, open the DDMS perspective in eclipse. Click the button beside [Java] button at the top right (tooltip: Open Perspective), below the menu bar. If you don't see DDMS there, select Other and select DDMS from the dialog box to use the DDMS perspective. You can also use Window>Open Perspective to accomplish the same task. Now, check if your file Explorer view is open, with data, system and tmp folders showing. That's the view of the root folder. Now, go to data/data/org.hfoss.camera/files to get your file. To see the file, select the "pull file from the device icon" at the top right of the file Explorer view and save it to your desired location.

A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

Introduction
A simple guide for integrating the Camera Hardware inside your Android App.

Step 1: Create a class that extends SurfaceView and implements SurfaceHolder.Callback


Before you can integrate the Camera hardware with your Activity, you must provide a Preview screen. The camera's Preview output is supplied to this screen. The SurfaceView instance with a SurfaceHolder.Callback implementation provides such a View
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder holder; private Camera camera; public CameraSurfaceView(Context context) { super(context); //Initiate the Surface Holder properly this.holder = this.getHolder(); this.holder.addCallback(this); this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); }

Step 2: In the surfaceCreated method, get an instance of the Camera


@Override public void surfaceCreated(SurfaceHolder holder) { try { //Open the Camera in preview mode this.camera = Camera.open(); this.camera.setPreviewDisplay(this.holder); } catch(IOException ioe) { ioe.printStackTrace(System.out); } }

Step 3: In the surfaceChanged callback


@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(width, height); camera.setParameters(parameters); camera.startPreview(); }

A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

During this callback, you get an idea of how big your preview screen is going to be. Based on that, assign the proper size to the Camera.

Step 4: Implement surfaceDestroyed to cleanup


@Override public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when replaced with a new screen //Always make sure to release the Camera instance camera.stopPreview(); camera.release(); camera = null; }

When the preview screen is removed from view, this callback is used to perform cleanup. In this phase, make sure the preview is stopped and the Camera hardware is released

Step 5: Add the SurfaceView to your layout


//Setup the FrameLayout with the Camera Preview Screen final CameraSurfaceView cameraSurfaceView = new CameraSurfaceView(this); FrameLayout preview = (FrameLayout)ViewHelper.findViewById(this, "preview"); preview.addView(cameraSurfaceView);

Step 6: Add a Button for Taking the Picture


//Setup the 'Take Picture' button to take a picture Button takeAPicture = (Button)ViewHelper.findViewById(this, "buttonClick"); takeAPicture.setOnClickListener(new OnClickListener() { public void onClick(View v) { Camera camera = cameraSurfaceView.getCamera(); camera.takePicture(null, null, new HandlePictureStorage()); } });

You must supply a Callback to process the information that the camera sends back to your App
private class HandlePictureStorage implements PictureCallback { @Override public void onPictureTaken(byte[] picture, Camera camera) { //The picture can be stored or do something else with the data //in this callback such sharing with friends, upload to a Cloud component etc //This is invoked when picture is taken and the data needs to be processed System.out.println("Picture successfully taken: "+picture);

A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

String fileName = "shareme.jpg"; String mime = "image/jpeg"; MainActivity.this.shareme = new CloudPhoto(); MainActivity.this.shareme.setFullName(fileName); MainActivity.this.shareme.setMimeType(mime); MainActivity.this.shareme.setPhoto(picture); } }

Inside this callback, you can do whatever you need with the picture. You can store it on your local file system, in a sqlite database, or in this case, send it to a remote service located in the cloud.

Step 7: Acquire permission for using the Camera hardware


<uses-permission android:name="android.permission.CAMERA" />

You can do this in the AndroidManifest.xml by adding the above mentioned line

Full Source for CameraSurfaceView.java


package org.openmobster.app; import java.io.IOException; import import import import android.content.Context; android.view.SurfaceView; android.view.SurfaceHolder; android.hardware.Camera;

/** * * @author openmobster@gmail.com */ public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder holder; private Camera camera; public CameraSurfaceView(Context context) { super(context); //Initiate the Surface Holder properly this.holder = this.getHolder(); this.holder.addCallback(this); this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } @Override public void surfaceCreated(SurfaceHolder holder) { try { //Open the Camera in preview mode this.camera = Camera.open(); this.camera.setPreviewDisplay(this.holder); } catch(IOException ioe)

A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

{ ioe.printStackTrace(System.out); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(width, height); camera.setParameters(parameters); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when replaced with a new screen //Always make sure to release the Camera instance camera.stopPreview(); camera.release(); camera = null; } public Camera getCamera() { return this.camera; } }

A7, Stephanos Tower, Eachamukku, Kakkanadu,Kochi

Você também pode gostar