1 page.title=Controlling the Camera 2 parent.title=Capturing Photos 3 parent.link=index.html 4 5 trainingnavtop=true 6 previous.title=Recording Videos Simply 7 previous.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 35 the framework APIs.</p> 36 37 <p>Directly controlling a device camera requires a lot more code than requesting pictures or videos 38 from existing camera applications. However, if you want to build a specialized camera application 39 or 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 45 process of directly controlling the camera. As Android's own Camera application does, the 46 recommended way to access the camera is to open {@link android.hardware.Camera} on a separate thread 47 that's launched from {@link android.app.Activity#onCreate onCreate()}. This approach is a good idea 48 since it can take a while and might bog down the UI thread. In a more basic implementation, 49 opening the camera can be deferred to the {@link 50 android.app.Activity#onResume onResume()} method to facilitate code reuse and keep the flow of 51 control simple.</p> 52 53 <p>Calling {@link android.hardware.Camera#open Camera.open()} throws an 54 exception if the camera is already in use by another application, so we wrap it 55 in a {@code try} block.</p> 56 57 <pre> 58 private 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 73 private 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 83 legacy API and call {@link android.hardware.Camera#open open()} without an 84 argument, 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 90 the shutter. To do so, you can use a {@link android.view.SurfaceView} to draw previews of what the 91 camera 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 96 preview requires an implementation of the {@code 97 android.view.SurfaceHolder.Callback} interface, which is used to pass image 98 data from the camera hardware to the application.</p> 99 100 <pre> 101 class 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 123 image 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 129 order, with the camera object being first. In the snippet below, the 130 process of initializing the camera is encapsulated so that {@link 131 android.hardware.Camera#startPreview Camera.startPreview()} is called by the 132 {@code setCamera()} method, whenever the user does something to change the 133 camera. The preview must also be restarted in the preview class {@code 134 surfaceChanged()} callback method.</p> 135 136 <pre> 137 public void setCamera(Camera camera) { 138 if (mCamera == camera) { return; } 139 140 stopPreviewAndFreeCamera(); 141 142 mCamera = camera; 143 144 if (mCamera != null) { 145 List<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 168 level to exposure compensation. This example changes only the preview size; 169 see the source code of the Camera application for many more.</p> 170 171 <pre> 172 public 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 192 orientation of the camera sensor. This setting does not prevent you from taking portrait-mode 193 photos, because the orientation of the device is recorded in the EXIF header. The {@link 194 android.hardware.Camera#setDisplayOrientation setCameraDisplayOrientation()} method lets you change 195 how the preview is displayed without affecting how the image is recorded. However, in Android prior 196 to 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()} 202 method to take a picture once the preview is started. You can create {@link 203 android.hardware.Camera.PictureCallback} and {@link 204 android.hardware.Camera.ShutterCallback} objects and pass them into {@link 205 android.hardware.Camera#takePicture Camera.takePicture()}.</p> 206 207 <p>If you want to grab images continously, you can create a {@link 208 android.hardware.Camera.PreviewCallback} that implements {@link 209 android.hardware.Camera.PreviewCallback#onPreviewFrame onPreviewFrame()}. For 210 something in between, you can capture only selected preview frames, or set up a 211 delayed action to call {@link android.hardware.Camera#takePicture 212 takePicture()}.</p> 213 214 215 <h2 id="TaskRestartPreview">Restart the Preview</h2> 216 217 <p>After a picture is taken, you must restart the preview before the user 218 can take another picture. In this example, the restart is done by overloading 219 the shutter button.</p> 220 221 <pre> 222 @Override 223 public 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 242 particular, you must release the {@link android.hardware.Camera} object, or you risk crashing other 243 applications, including new instances of your own application.</p> 244 245 <p>When should you stop the preview and release the camera? Well, having your 246 preview surface destroyed is a pretty good hint that its time to stop the 247 preview and release the camera, as shown in these methods from the {@code 248 Preview} class.</p> 249 250 <pre> 251 public 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 */ 264 private 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 284 <p>Earlier in the lesson, this procedure was also part of the {@code 285 setCamera()} method, so initializing a camera always begins with stopping the 286 preview.</p> 287 288