Home | History | Annotate | Download | only in camera
      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&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
    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 &#64;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