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         // 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
    166 level to exposure compensation. This example changes only the preview size;
    167 see the source code of the Camera application for many more.</p>
    168 
    169 <pre>
    170 public 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
    188 orientation of the camera sensor. This setting does not prevent you from taking portrait-mode
    189 photos, because the orientation of the device is recorded in the EXIF header. The {@link
    190 android.hardware.Camera#setDisplayOrientation setCameraDisplayOrientation()} method lets you change
    191 how the preview is displayed without affecting how the image is recorded. However, in Android prior
    192 to 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()}
    198 method to take a picture once the preview is started. You can create {@link
    199 android.hardware.Camera.PictureCallback} and {@link
    200 android.hardware.Camera.ShutterCallback} objects and pass them into {@link
    201 android.hardware.Camera#takePicture Camera.takePicture()}.</p>
    202 
    203 <p>If you want to grab images continously, you can create a {@link
    204 android.hardware.Camera.PreviewCallback} that implements {@link
    205 android.hardware.Camera.PreviewCallback#onPreviewFrame onPreviewFrame()}. For
    206 something in between, you can capture only selected preview frames, or set up a
    207 delayed action to call {@link android.hardware.Camera#takePicture
    208 takePicture()}.</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
    214 can take another picture. In this example, the restart is done by overloading
    215 the shutter button.</p>
    216 
    217 <pre>
    218 &#64;Override
    219 public 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
    238 particular, you must release the {@link android.hardware.Camera} object, or you risk crashing other
    239 applications, including new instances of your own application.</p>
    240 
    241 <p>When should you stop the preview and release the camera? Well, having your
    242 preview surface destroyed is a pretty good hint that its time to stop the
    243 preview and release the camera, as shown in these methods from the {@code
    244 Preview} class.</p>
    245 
    246 <pre>
    247 public 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  */
    258 private 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
    275 setCamera()} method, so initializing a camera always begins with stopping the
    276 preview.</p>
    277 
    278