blob: 03ad119bbde6cb74b893a9d1b389464ee2ba37ae [file] [log] [blame]
Scott Main564e8aa2011-12-15 15:59:34 -08001page.title=Controlling the Camera
Scott Main580f0142011-12-15 16:47:26 -08002parent.title=Capturing Photos
Scott Main564e8aa2011-12-15 15:59:34 -08003parent.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 or
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
Sparky Rhodeabe2dec2011-12-15 16:53:35 -080048since 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
Scott Main564e8aa2011-12-15 15:59:34 -080050android.app.Activity#onResume onResume()} method to facilitate code reuse and keep the flow of
51control simple.</p>
52
Scott Main564e8aa2011-12-15 15:59:34 -080053<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();
Sparky Rhodeabe2dec2011-12-15 16:53:35 -080063 mCamera = Camera.open(id);
Scott Main564e8aa2011-12-15 15:59:34 -080064 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
Sparky Rhodeabe2dec2011-12-15 16:53:35 -080082<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
Scott Main564e8aa2011-12-15 15:59:34 -080086
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 the application.</p>
99
100<pre>
101class Preview extends ViewGroup implements SurfaceHolder.Callback {
Scott Main564e8aa2011-12-15 15:59:34 -0800102
103 SurfaceView mSurfaceView;
104 SurfaceHolder mHolder;
105
Scott Main564e8aa2011-12-15 15:59:34 -0800106 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
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800123image preview can be started, as shown in the next section.</p>
Scott Main564e8aa2011-12-15 15:59:34 -0800124
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
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800129order, with the camera object being first. In the snippet below, the
Scott Main564e8aa2011-12-15 15:59:34 -0800130process 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 /*
156 Important: Call startPreview() to start updating the preview surface. Preview must
157 be started before you can take a picture.
158 */
159 mCamera.startPreview();
160 }
161}
162</pre>
163
164
165<h2 id="TaskSettings">Modify Camera Settings</h2>
166
167<p>Camera settings change the way that the camera takes pictures, from the zoom
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800168level to exposure compensation. This example changes only the preview size;
169see the source code of the Camera application for many more.</p>
Scott Main564e8aa2011-12-15 15:59:34 -0800170
171<pre>
172public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
173 // Now that the size is known, set up the camera parameters and begin
174 // the preview.
175 Camera.Parameters parameters = mCamera.getParameters();
176 parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
177 requestLayout();
178 mCamera.setParameters(parameters);
179
180 /*
181 Important: Call startPreview() to start updating the preview surface. Preview must be
182 started before you can take a picture.
183 */
184 mCamera.startPreview();
185}
186</pre>
187
188
189<h2 id="TaskOrientation">Set the Preview Orientation</h2>
190
191<p>Most camera applications lock the display into landscape mode because that is the natural
192orientation of the camera sensor. This setting does not prevent you from taking portrait-mode
193photos, because the orientation of the device is recorded in the EXIF header. The {@link
194android.hardware.Camera#setDisplayOrientation setCameraDisplayOrientation()} method lets you change
195how the preview is displayed without affecting how the image is recorded. However, in Android prior
196to API level 14, you must stop your preview before changing the orientation and then restart it.</p>
197
198
199<h2 id="TaskTakePicture">Take a Picture</h2>
200
201<p>Use the {@link android.hardware.Camera#takePicture Camera.takePicture()}
202method to take a picture once the preview is started. You can create {@link
203android.hardware.Camera.PictureCallback} and {@link
204android.hardware.Camera.ShutterCallback} objects and pass them into {@link
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800205android.hardware.Camera#takePicture Camera.takePicture()}.</p>
Scott Main564e8aa2011-12-15 15:59:34 -0800206
207<p>If you want to grab images continously, you can create a {@link
208android.hardware.Camera.PreviewCallback} that implements {@link
209android.hardware.Camera.PreviewCallback#onPreviewFrame onPreviewFrame()}. For
210something in between, you can capture only selected preview frames, or set up a
211delayed action to call {@link android.hardware.Camera#takePicture
212takePicture()}.</p>
213
214
215<h2 id="TaskRestartPreview">Restart the Preview</h2>
216
217<p>After a picture is taken, you must to restart the preview before the user
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800218can take another picture. In this example, the restart is done by overloading
219the shutter button.</p>
Scott Main564e8aa2011-12-15 15:59:34 -0800220
221<pre>
222&#64;Override
223public void onClick(View v) {
224 switch(mPreviewState) {
225 case K_STATE_FROZEN:
226 mCamera.startPreview();
227 mPreviewState = K_STATE_PREVIEW;
228 break;
229
230 default:
231 mCamera.takePicture( null, rawCallback, null);
232 mPreviewState = K_STATE_BUSY;
233 } // switch
234 shutterBtnConfig();
235}
236</pre>
237
238
239<h2 id="TaskReleaseCamera">Stop the Preview and Release the Camera</h2>
240
241<p>Once your application is done using the camera, it's time to clean up. In
242particular, you must release the {@link android.hardware.Camera} object, or you risk crashing other
243applications, including new instances of your own application.</p>
244
245<p>When should you stop the preview and release the camera? Well, having your
246preview surface destroyed is a pretty good hint that it’s time to stop the
247preview and release the camera, as shown in these methods from the {@code
248Preview} class.</p>
249
250<pre>
251public void surfaceDestroyed(SurfaceHolder holder) {
252 // Surface will be destroyed when we return, so stop the preview.
253 if (mCamera != null) {
254 /*
255 Call stopPreview() to stop updating the preview surface.
256 */
257 mCamera.stopPreview();
258 }
259}
260
261/**
262 * When this function returns, mCamera will be null.
263 */
264private void stopPreviewAndFreeCamera() {
265
266 if (mCamera != null) {
267 /*
268 Call stopPreview() to stop updating the preview surface.
269 */
270 mCamera.stopPreview();
271
272 /*
273 Important: Call release() to release the camera for use by other applications.
274 Applications should release the camera immediately in onPause() (and re-open() it in
275 onResume()).
276 */
277 mCamera.release();
278
279 mCamera = null;
280 }
281}
282</pre>
283
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800284<p>Earlier in the lesson, this procedure was also part of the {@code
Scott Main564e8aa2011-12-15 15:59:34 -0800285setCamera()} method, so initializing a camera always begins with stopping the
286preview.</p>
287