1page.title=Controlling the Camera
2parent.title=Capturing Photos
3parent.link=index.html
4
5trainingnavtop=true
6previous.title=Recording Videos Simply
7previous.link=videobasics.html
8
9@jd:body
10
11
12<div id="tb-wrapper">
13  <div id="tb">
14
15    <h2>This lesson teaches you to</h2>
16    <ol>
17      <li><a href="#TaskOpenCamera">Open the Camera Object</a></li>
18      <li><a href="#camera-preview">Create the Camera Preview</a></li>
19      <li><a href="#TaskSettings">Modify Camera Settings</a></li>
20      <li><a href="#TaskOrientation">Set the Preview Orientation</a></li>
21      <li><a href="#TaskTakePicture">Take a Picture</a></li>
22      <li><a href="#TaskRestartPreview">Restart the Preview</a></li>
23      <li><a href="#TaskReleaseCamera">Stop the Preview and Release the Camera</a></li>
24    </ol>
25
26    <h2>You should also read</h2>
27    <ul>
28      <li><a href="{@docRoot}guide/topics/media/camera.html#custom-camera">Building
29              a Camera App</a></li>
30    </ul>
31  </div>
32</div>
33
34<p>In this lesson, we discuss how to control the camera hardware directly using
35the framework APIs.</p>
36
37<p>Directly controlling a device camera requires a lot more code than requesting pictures or videos
38from existing camera applications. However, if you want to build a specialized camera application
39or something fully integrated in your app UI, this lesson shows you how.</p>
40
41
42<h2 id="TaskOpenCamera">Open the Camera Object</h2>
43
44<p>Getting an instance of the {@link android.hardware.Camera} object is the first step in the
45process of directly controlling the camera. As Android's own Camera application does, the
46recommended way to access the camera is to open {@link android.hardware.Camera} on a separate thread
47that's launched from {@link android.app.Activity#onCreate onCreate()}. This approach is a good idea
48since it can take a while and might bog down the UI thread. In a more basic implementation,
49opening the camera can be deferred to the {@link
50android.app.Activity#onResume onResume()} method to facilitate code reuse and keep the flow of
51control simple.</p>
52
53<p>Calling {@link android.hardware.Camera#open Camera.open()} throws an
54exception if the camera is already in use by another application, so we wrap it
55in a {@code try} block.</p>
56
57<pre>
58private boolean safeCameraOpen(int id) {
59    boolean qOpened = false;
60
61    try {
62        releaseCameraAndPreview();
63        mCamera = Camera.open(id);
64        qOpened = (mCamera != null);
65    } catch (Exception e) {
66        Log.e(getString(R.string.app_name), "failed to open Camera");
67        e.printStackTrace();
68    }
69
70    return qOpened;
71}
72
73private void releaseCameraAndPreview() {
74    mPreview.setCamera(null);
75    if (mCamera != null) {
76        mCamera.release();
77        mCamera = null;
78    }
79}
80</pre>
81
82<p>Since API level 9, the camera framework supports multiple cameras. If you use the
83legacy API and call {@link android.hardware.Camera#open open()} without an
84argument, you get the first rear-facing camera.</p>
85
86
87<h2 id="camera-preview">Create the Camera Preview</h2>
88
89<p>Taking a picture usually requires that your users see a preview of their subject before clicking
90the shutter. To do so, you can use a {@link android.view.SurfaceView} to draw previews of what the
91camera sensor is picking up.</p>
92
93<h3 id="TaskSetPreview">Preview Class</h3>
94
95<p>To get started with displaying a preview, you need preview class. The
96preview requires an implementation of the {@code
97android.view.SurfaceHolder.Callback} interface, which is used to pass image
98data from the camera hardware to the application.</p>
99
100<pre>
101class Preview extends ViewGroup implements SurfaceHolder.Callback {
102
103    SurfaceView mSurfaceView;
104    SurfaceHolder mHolder;
105
106    Preview(Context context) {
107        super(context);
108
109        mSurfaceView = new SurfaceView(context);
110        addView(mSurfaceView);
111
112        // Install a SurfaceHolder.Callback so we get notified when the
113        // underlying surface is created and destroyed.
114        mHolder = mSurfaceView.getHolder();
115        mHolder.addCallback(this);
116        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
117    }
118...
119}
120</pre>
121
122<p>The preview class must be passed to the {@link android.hardware.Camera} object before the live
123image preview can be started, as shown in the next section.</p>
124
125
126<h3 id="TaskStartPreview">Set and Start the Preview</h2>
127
128<p>A camera instance and its related preview must be created in a specific
129order, with the camera object being first. In the snippet below, the
130process of initializing the camera is encapsulated so that {@link
131android.hardware.Camera#startPreview Camera.startPreview()} is called by the
132{@code setCamera()} method, whenever the user does something to change the
133camera. The preview must also be restarted in the preview class {@code
134surfaceChanged()} callback method.</p>
135
136<pre>
137public void setCamera(Camera camera) {
138    if (mCamera == camera) { return; }
139
140    stopPreviewAndFreeCamera();
141
142    mCamera = camera;
143
144    if (mCamera != null) {
145        List&lt;Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
146        mSupportedPreviewSizes = localSizes;
147        requestLayout();
148
149        try {
150            mCamera.setPreviewDisplay(mHolder);
151        } catch (IOException e) {
152            e.printStackTrace();
153        }
154
155        // Important: Call startPreview() to start updating the preview
156        // surface. Preview must be started before you can take a picture.
157        mCamera.startPreview();
158    }
159}
160</pre>
161
162
163<h2 id="TaskSettings">Modify Camera Settings</h2>
164
165<p>Camera settings change the way that the camera takes pictures, from the zoom
166level to exposure compensation. This example changes only the preview size;
167see the source code of the Camera application for many more.</p>
168
169<pre>
170public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
171    // Now that the size is known, set up the camera parameters and begin
172    // the preview.
173    Camera.Parameters parameters = mCamera.getParameters();
174    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
175    requestLayout();
176    mCamera.setParameters(parameters);
177
178    // Important: Call startPreview() to start updating the preview surface.
179    // Preview must be started before you can take a picture.
180    mCamera.startPreview();
181}
182</pre>
183
184
185<h2 id="TaskOrientation">Set the Preview Orientation</h2>
186
187<p>Most camera applications lock the display into landscape mode because that is the natural
188orientation of the camera sensor. This setting does not prevent you from taking portrait-mode
189photos, because the orientation of the device is recorded in the EXIF header. The {@link
190android.hardware.Camera#setDisplayOrientation setCameraDisplayOrientation()} method lets you change
191how the preview is displayed without affecting how the image is recorded. However, in Android prior
192to API level 14, you must stop your preview before changing the orientation and then restart it.</p>
193
194
195<h2 id="TaskTakePicture">Take a Picture</h2>
196
197<p>Use the {@link android.hardware.Camera#takePicture Camera.takePicture()}
198method to take a picture once the preview is started. You can create {@link
199android.hardware.Camera.PictureCallback} and {@link
200android.hardware.Camera.ShutterCallback} objects and pass them into {@link
201android.hardware.Camera#takePicture Camera.takePicture()}.</p>
202
203<p>If you want to grab images continously, you can create a {@link
204android.hardware.Camera.PreviewCallback} that implements {@link
205android.hardware.Camera.PreviewCallback#onPreviewFrame onPreviewFrame()}. For
206something in between, you can capture only selected preview frames, or set up a
207delayed action to call {@link android.hardware.Camera#takePicture
208takePicture()}.</p>
209
210
211<h2 id="TaskRestartPreview">Restart the Preview</h2>
212
213<p>After a picture is taken, you must restart the preview before the user
214can take another picture. In this example, the restart is done by overloading
215the shutter button.</p>
216
217<pre>
218&#64;Override
219public void onClick(View v) {
220    switch(mPreviewState) {
221    case K_STATE_FROZEN:
222        mCamera.startPreview();
223        mPreviewState = K_STATE_PREVIEW;
224        break;
225
226    default:
227        mCamera.takePicture( null, rawCallback, null);
228        mPreviewState = K_STATE_BUSY;
229    } // switch
230    shutterBtnConfig();
231}
232</pre>
233
234
235<h2 id="TaskReleaseCamera">Stop the Preview and Release the Camera</h2>
236
237<p>Once your application is done using the camera, it's time to clean up. In
238particular, you must release the {@link android.hardware.Camera} object, or you risk crashing other
239applications, including new instances of your own application.</p>
240
241<p>When should you stop the preview and release the camera? Well, having your
242preview surface destroyed is a pretty good hint that it’s time to stop the
243preview and release the camera, as shown in these methods from the {@code
244Preview} class.</p>
245
246<pre>
247public void surfaceDestroyed(SurfaceHolder holder) {
248    // Surface will be destroyed when we return, so stop the preview.
249    if (mCamera != null) {
250        // Call stopPreview() to stop updating the preview surface.
251        mCamera.stopPreview();
252    }
253}
254
255/**
256 * When this function returns, mCamera will be null.
257 */
258private void stopPreviewAndFreeCamera() {
259
260    if (mCamera != null) {
261        // Call stopPreview() to stop updating the preview surface.
262        mCamera.stopPreview();
263
264        // Important: Call release() to release the camera for use by other
265        // applications. Applications should release the camera immediately
266        // during onPause() and re-open() it during onResume()).
267        mCamera.release();
268
269        mCamera = null;
270    }
271}
272</pre>
273
274<p>Earlier in the lesson, this procedure was also part of the {@code
275setCamera()} method, so initializing a camera always begins with stopping the
276preview.</p>
277
278