blob: 6f358a52befc9295341c7f078ffd9a3ed55b5320 [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
Pin Ting6f5b5ee2012-03-03 00:13:32 +080038from existing camera applications. However, if you want to build a specialized camera application
Scott Main564e8aa2011-12-15 15:59:34 -080039or 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
Pin Ting6f5b5ee2012-03-03 00:13:32 +080098data from the camera hardware to the application.</p>
Scott Main564e8aa2011-12-15 15:59:34 -080099
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
Scott Main326ed252013-12-04 17:54:03 -0800155 // Important: Call startPreview() to start updating the preview
156 // surface. Preview must be started before you can take a picture.
Scott Main564e8aa2011-12-15 15:59:34 -0800157 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
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800166level to exposure compensation. This example changes only the preview size;
167see the source code of the Camera application for many more.</p>
Scott Main564e8aa2011-12-15 15:59:34 -0800168
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
Scott Main326ed252013-12-04 17:54:03 -0800178 // Important: Call startPreview() to start updating the preview surface.
179 // Preview must be started before you can take a picture.
Scott Main564e8aa2011-12-15 15:59:34 -0800180 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
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800201android.hardware.Camera#takePicture Camera.takePicture()}.</p>
Scott Main564e8aa2011-12-15 15:59:34 -0800202
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
Pin Ting6f5b5ee2012-03-03 00:13:32 +0800213<p>After a picture is taken, you must restart the preview before the user
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800214can take another picture. In this example, the restart is done by overloading
215the shutter button.</p>
Scott Main564e8aa2011-12-15 15:59:34 -0800216
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) {
Scott Main326ed252013-12-04 17:54:03 -0800250 // Call stopPreview() to stop updating the preview surface.
Scott Main564e8aa2011-12-15 15:59:34 -0800251 mCamera.stopPreview();
252 }
253}
254
255/**
Scott Main326ed252013-12-04 17:54:03 -0800256 * When this function returns, mCamera will be null.
257 */
Scott Main564e8aa2011-12-15 15:59:34 -0800258private void stopPreviewAndFreeCamera() {
259
260 if (mCamera != null) {
Scott Main326ed252013-12-04 17:54:03 -0800261 // Call stopPreview() to stop updating the preview surface.
Scott Main564e8aa2011-12-15 15:59:34 -0800262 mCamera.stopPreview();
263
Scott Main326ed252013-12-04 17:54:03 -0800264 // 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()).
Scott Main564e8aa2011-12-15 15:59:34 -0800267 mCamera.release();
268
269 mCamera = null;
270 }
271}
272</pre>
273
Sparky Rhodeabe2dec2011-12-15 16:53:35 -0800274<p>Earlier in the lesson, this procedure was also part of the {@code
Scott Main564e8aa2011-12-15 15:59:34 -0800275setCamera()} method, so initializing a camera always begins with stopping the
276preview.</p>
277