| page.title=Camera |
| page.tags=photo,video,picture,mediarecorder |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#considerations">Considerations</a></li> |
| <li><a href="#basics">The Basics</a> |
| <li><a href="#manifest">Manifest Declarations</a></li> |
| <li><a href="#camera-apps">Using Existing Camera Apps</a> |
| <li><a href="#custom-camera">Building a Camera App</a> |
| <ol> |
| <li><a href="#detect-camera">Detecting camera hardware</a></li> |
| <li><a href="#access-camera">Accessing cameras</a></li> |
| <li><a href="#check-camera-features">Checking camera features</a></li> |
| <li><a href="#camera-preview">Creating a preview class</a></li> |
| <li><a href="#preview-layout">Placing preview in a layout</a></li> |
| <li><a href="#capture-picture">Capturing pictures</a></li> |
| <li><a href="#capture-video">Capturing videos</a></li> |
| <li><a href="#release-camera">Releasing the camera</a></li> |
| </ol> |
| </li> |
| <li><a href="#saving-media">Saving Media Files</a></li> |
| <li><a href="#camera-features">Camera Features</a> |
| <ol> |
| <li><a href="#check-feature">Checking feature availability</a></li> |
| <li><a href="#using-features">Using camera features</a></li> |
| <li><a href="#metering-focus-areas">Metering and focus areas</a></li> |
| <li><a href="#face-detection">Face detection</a></li> |
| <li><a href="#time-lapse-video">Time lapse video</a></li> |
| </ol> |
| </li> |
| </ol> |
| <h2>Key Classes</h2> |
| <ol> |
| <li>{@link android.hardware.Camera}</li> |
| <li>{@link android.view.SurfaceView}</li> |
| <li>{@link android.media.MediaRecorder}</li> |
| <li>{@link android.content.Intent}</li> |
| </ol> |
| <h2>See also</h2> |
| <ol> |
| <li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li> |
| <li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| |
| <p>The Android framework includes support for various cameras and camera features available on |
| devices, allowing you to capture pictures and videos in your applications. This document discusses a |
| quick, simple approach to image and video capture and outlines an advanced approach for creating |
| custom camera experiences for your users.</p> |
| |
| <h2 id="considerations">Considerations</h2> |
| <p>Before enabling your application to use cameras on Android devices, you should consider a few |
| questions about how your app intends to use this hardware feature.</p> |
| |
| <ul> |
| <li><strong>Camera Requirement</strong> - Is the use of a camera so important to your |
| application that you do not want your application installed on a device that does not have a |
| camera? If so, you should declare the <a href="#manifest">camera requirement in your |
| manifest</a>.</li> |
| |
| <li><strong>Quick Picture or Customized Camera</strong> - How will your application use the |
| camera? Are you just interested in snapping a quick picture or video clip, or will your application |
| provide a new way to use cameras? For a getting a quick snap or clip, consider |
| <a href="#camera-apps">Using Existing Camera Apps</a>. For developing a customized camera feature, check |
| out the <a href="#custom-camera">Building a Camera App</a> section.</li> |
| |
| <li><strong>Storage</strong> - Are the images or videos your application generates intended to be |
| only visible to your application or shared so that other applications such as Gallery or other |
| media and social apps can use them? Do you want the pictures and videos to be available even if your |
| application is uninstalled? Check out the <a href="#saving-media">Saving Media Files</a> section to |
| see how to implement these options.</li> |
| </ul> |
| |
| |
| |
| <h2 id="basics">The Basics</h2> |
| <p>The Android framework supports capturing images and video through the |
| {@link android.hardware.camera2} API or camera {@link android.content.Intent}. Here are the relevant |
| classes:</p> |
| |
| <dl> |
| <dt>{@link android.hardware.camera2}</dt> |
| <dd>This package is the primary API for controlling device cameras. It can be used to take |
| pictures or videos when you are building a camera application.</dd> |
| |
| <dt>{@link android.hardware.Camera}</dt> |
| <dd>This class is the older deprecated API for controlling device cameras.</dd> |
| |
| <dt>{@link android.view.SurfaceView}</dt> |
| <dd>This class is used to present a live camera preview to the user.</dd> |
| |
| <dt>{@link android.media.MediaRecorder}</dt> |
| <dd>This class is used to record video from the camera.</dd> |
| |
| <dt>{@link android.content.Intent}</dt> |
| <dd>An intent action type of {@link android.provider.MediaStore#ACTION_IMAGE_CAPTURE |
| MediaStore.ACTION_IMAGE_CAPTURE} or {@link android.provider.MediaStore#ACTION_VIDEO_CAPTURE |
| MediaStore.ACTION_VIDEO_CAPTURE} can be used to capture images or videos without directly |
| using the {@link android.hardware.Camera} object.</dd> |
| </dl> |
| |
| |
| <h2 id="manifest">Manifest Declarations</h2> |
| <p>Before starting development on your application with the Camera API, you should make sure |
| your manifest has the appropriate declarations to allow use of camera hardware and other |
| related features.</p> |
| |
| <ul> |
| <li><strong>Camera Permission</strong> - Your application must request permission to use a device |
| camera. |
| <pre> |
| <uses-permission android:name="android.permission.CAMERA" /> |
| </pre> |
| <p class="note"><strong>Note:</strong> If you are using the camera <a href="#camera-apps">by |
| invoking an existing camera app</a>, |
| your application does not need to request this permission.</p> |
| </li> |
| <li><strong>Camera Features</strong> - Your application must also declare use of camera features, |
| for example: |
| <pre> |
| <uses-feature android:name="android.hardware.camera" /> |
| </pre> |
| <p>For a list of camera features, see the manifest |
| <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features">Features |
| Reference</a>.</p> |
| <p>Adding camera features to your manifest causes Google Play to prevent your application from |
| being installed to devices that do not include a camera or do not support the camera features you |
| specify. For more information about using feature-based filtering with Google Play, see <a |
| href="{@docRoot}guide/topics/manifest/uses-feature-element.html#market-feature-filtering">Google |
| Play and Feature-Based Filtering</a>.</p> |
| <p>If your application <em>can use</em> a camera or camera feature for proper operation, but does |
| not <em>require</em> it, you should specify this in the manifest by including the {@code |
| android:required} attribute, and setting it to {@code false}:</p> |
| <pre> |
| <uses-feature android:name="android.hardware.camera" android:required="false" /> |
| </pre> |
| |
| </li> |
| <li><strong>Storage Permission</strong> - If your application saves images or videos to the |
| device's external storage (SD Card), you must also specify this in the manifest. |
| <pre> |
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
| </pre> |
| </li> |
| <li><strong>Audio Recording Permission</strong> - For recording audio with video capture, your |
| application must request the audio capture permission. |
| <pre> |
| <uses-permission android:name="android.permission.RECORD_AUDIO" /> |
| </pre> |
| </li> |
| <li> |
| <p><strong>Location Permission</strong> - If your application tags images |
| with GPS location information, you must request the {@code ACCESS_FINE_LOCATION} |
| permission. Note that, if your app targets Android 5.0 (API level 21) or |
| higher, you also need to declare that your app uses the device's GPS:</p> |
| <pre> |
| <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
| ... |
| <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --> |
| <uses-feature android:name="android.hardware.location.gps" /> |
| </pre> |
| <p>For more information about getting user location, see |
| <a href="{@docRoot}guide/topics/location/strategies.html">Location Strategies</a>.</p> |
| </li> |
| </ul> |
| |
| |
| <h2 id="camera-apps">Using Existing Camera Apps</h2> |
| <p>A quick way to enable taking pictures or videos in your application without a lot of extra code |
| is to use an {@link android.content.Intent} to invoke an existing Android camera application. |
| The details are described in the training lessons |
| <a href="{@docRoot}training/camera/photobasics.html">Taking Photos Simply</a> and |
| <a href="{@docRoot}training/camera/videobasics.html">Recording Videos Simply</a>.</p> |
| |
| <h2 id="custom-camera">Building a Camera App</h2> |
| <p>Some developers may require a camera user interface that is customized to the look of their |
| application or provides special features. Writing your own picture-taking code |
| can provide a more compelling experience for your users.</p> |
| |
| <p><strong> Note: The following guide is for the older, deprecated {@link android.hardware.Camera} |
| API. For new or advanced camera applications, the newer {@link android.hardware.camera2} API is |
| recommended.</strong></p> |
| |
| <p>The general steps for creating a custom camera interface for your application are as follows:</p> |
| |
| <ul> |
| <li><strong>Detect and Access Camera</strong> - Create code to check for the existence of |
| cameras and request access.</li> |
| <li><strong>Create a Preview Class</strong> - Create a camera preview class that extends {@link |
| android.view.SurfaceView} and implements the {@link android.view.SurfaceHolder} interface. This |
| class previews the live images from the camera.</li> |
| <li><strong>Build a Preview Layout</strong> - Once you have the camera preview class, create a |
| view layout that incorporates the preview and the user interface controls you want.</li> |
| <li><strong>Setup Listeners for Capture</strong> - Connect listeners for your interface |
| controls to start image or video capture in response to user actions, such as pressing a |
| button.</li> |
| <li><strong>Capture and Save Files</strong> - Setup the code for capturing pictures or |
| videos and saving the output.</li> |
| <li><strong>Release the Camera</strong> - After using the camera, your application must |
| properly release it for use by other applications.</li> |
| </ul> |
| |
| <p>Camera hardware is a shared resource that must be carefully managed so your application does |
| not collide with other applications that may also want to use it. The following sections discusses |
| how to detect camera hardware, how to request access to a camera, how to capture pictures or video |
| and how to release the camera when your application is done using it.</p> |
| |
| <p class="caution"><strong>Caution:</strong> Remember to release the {@link android.hardware.Camera} |
| object by calling the {@link android.hardware.Camera#release() Camera.release()} when your |
| application is done using it! If your application does not properly release the camera, all |
| subsequent attempts to access the camera, including those by your own application, will fail and may |
| cause your or other applications to be shut down.</p> |
| |
| |
| <h3 id="detect-camera">Detecting camera hardware</h3> |
| <p>If your application does not specifically require a camera using a manifest declaration, you |
| should check to see if a camera is available at runtime. To perform this check, use the {@link |
| android.content.pm.PackageManager#hasSystemFeature(java.lang.String) |
| PackageManager.hasSystemFeature()} method, as shown in the example code below:</p> |
| |
| <pre> |
| /** Check if this device has a camera */ |
| private boolean checkCameraHardware(Context context) { |
| if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ |
| // this device has a camera |
| return true; |
| } else { |
| // no camera on this device |
| return false; |
| } |
| } |
| </pre> |
| |
| <p>Android devices can have multiple cameras, for example a back-facing camera for photography and a |
| front-facing camera for video calls. Android 2.3 (API Level 9) and later allows you to check the |
| number of cameras available on a device using the {@link |
| android.hardware.Camera#getNumberOfCameras() Camera.getNumberOfCameras()} method.</p> |
| |
| <h3 id="access-camera">Accessing cameras</h3> |
| <p>If you have determined that the device on which your application is running has a camera, you |
| must request to access it by getting an instance of {@link android.hardware.Camera} (unless you |
| are using an <a href="camera-apps">intent to access the camera</a>). </p> |
| |
| <p>To access the primary camera, use the {@link android.hardware.Camera#open() Camera.open()} method |
| and be sure to catch any exceptions, as shown in the code below:</p> |
| |
| <pre> |
| /** A safe way to get an instance of the Camera object. */ |
| public static Camera getCameraInstance(){ |
| Camera c = null; |
| try { |
| c = Camera.open(); // attempt to get a Camera instance |
| } |
| catch (Exception e){ |
| // Camera is not available (in use or does not exist) |
| } |
| return c; // returns null if camera is unavailable |
| } |
| </pre> |
| |
| <p class="caution"><strong>Caution:</strong> Always check for exceptions when using {@link |
| android.hardware.Camera#open() Camera.open()}. Failing to check for exceptions if the camera is in |
| use or does not exist will cause your application to be shut down by the system.</p> |
| |
| <p>On devices running Android 2.3 (API Level 9) or higher, you can access specific cameras using |
| {@link android.hardware.Camera#open(int) Camera.open(int)}. The example code above will access |
| the first, back-facing camera on a device with more than one camera.</p> |
| |
| <h3 id="check-camera-features">Checking camera features</h3> |
| <p>Once you obtain access to a camera, you can get further information about its capabilities using |
| the {@link android.hardware.Camera#getParameters() Camera.getParameters()} method and checking the |
| returned {@link android.hardware.Camera.Parameters} object for supported capabilities. When using |
| API Level 9 or higher, use the {@link android.hardware.Camera#getCameraInfo(int, |
| android.hardware.Camera.CameraInfo) Camera.getCameraInfo()} to determine if a camera is on the front |
| or back of the device, and the orientation of the image.</p> |
| |
| |
| |
| <h3 id="camera-preview">Creating a preview class</h3> |
| <p>For users to effectively take pictures or video, they must be able to see what the device camera |
| sees. A camera preview class is a {@link android.view.SurfaceView} that can display the live image |
| data coming from a camera, so users can frame and capture a picture or video.</p> |
| |
| <p>The following example code demonstrates how to create a basic camera preview class that can be |
| included in a {@link android.view.View} layout. This class implements {@link |
| android.view.SurfaceHolder.Callback SurfaceHolder.Callback} in order to capture the callback events |
| for creating and destroying the view, which are needed for assigning the camera preview input.</p> |
| |
| <pre> |
| /** A basic Camera preview class */ |
| public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { |
| private SurfaceHolder mHolder; |
| private Camera mCamera; |
| |
| public CameraPreview(Context context, Camera camera) { |
| super(context); |
| mCamera = camera; |
| |
| // Install a SurfaceHolder.Callback so we get notified when the |
| // underlying surface is created and destroyed. |
| mHolder = getHolder(); |
| mHolder.addCallback(this); |
| // deprecated setting, but required on Android versions prior to 3.0 |
| mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); |
| } |
| |
| public void surfaceCreated(SurfaceHolder holder) { |
| // The Surface has been created, now tell the camera where to draw the preview. |
| try { |
| mCamera.setPreviewDisplay(holder); |
| mCamera.startPreview(); |
| } catch (IOException e) { |
| Log.d(TAG, "Error setting camera preview: " + e.getMessage()); |
| } |
| } |
| |
| public void surfaceDestroyed(SurfaceHolder holder) { |
| // empty. Take care of releasing the Camera preview in your activity. |
| } |
| |
| public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { |
| // If your preview can change or rotate, take care of those events here. |
| // Make sure to stop the preview before resizing or reformatting it. |
| |
| if (mHolder.getSurface() == null){ |
| // preview surface does not exist |
| return; |
| } |
| |
| // stop preview before making changes |
| try { |
| mCamera.stopPreview(); |
| } catch (Exception e){ |
| // ignore: tried to stop a non-existent preview |
| } |
| |
| // set preview size and make any resize, rotate or |
| // reformatting changes here |
| |
| // start preview with new settings |
| try { |
| mCamera.setPreviewDisplay(mHolder); |
| mCamera.startPreview(); |
| |
| } catch (Exception e){ |
| Log.d(TAG, "Error starting camera preview: " + e.getMessage()); |
| } |
| } |
| } |
| </pre> |
| |
| <p>If you want to set a specific size for your camera preview, set this in the {@code |
| surfaceChanged()} method as noted in the comments above. When setting preview size, you |
| <em>must use</em> values from {@link android.hardware.Camera.Parameters#getSupportedPreviewSizes}. |
| <em>Do not</em> set arbitrary values in the {@link |
| android.hardware.Camera.Parameters#setPreviewSize setPreviewSize()} method.</p> |
| |
| |
| <h3 id="preview-layout">Placing preview in a layout</h3> |
| <p>A camera preview class, such as the example shown in the previous section, must be placed in the |
| layout of an activity along with other user interface controls for taking a picture or video. This |
| section shows you how to build a basic layout and activity for the preview.</p> |
| |
| <p>The following layout code provides a very basic view that can be used to display a camera |
| preview. In this example, the {@link android.widget.FrameLayout} element is meant to be the |
| container for the camera preview class. This layout type is used so that additional picture |
| information or controls can be overlayed on the live camera preview images.</p> |
| |
| <pre> |
| <?xml version="1.0" encoding="utf-8"?> |
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| android:orientation="horizontal" |
| android:layout_width="fill_parent" |
| android:layout_height="fill_parent" |
| > |
| <FrameLayout |
| android:id="@+id/camera_preview" |
| android:layout_width="fill_parent" |
| android:layout_height="fill_parent" |
| android:layout_weight="1" |
| /> |
| |
| <Button |
| android:id="@+id/button_capture" |
| android:text="Capture" |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:layout_gravity="center" |
| /> |
| </LinearLayout> |
| </pre> |
| |
| <p>On most devices, the default orientation of the camera preview is landscape. This example layout |
| specifies a horizontal (landscape) layout and the code below fixes the orientation of the |
| application to landscape. For simplicity in rendering a camera preview, you should change your |
| application's preview activity orientation to landscape by adding the following to your |
| manifest.</p> |
| |
| <pre> |
| <activity android:name=".CameraActivity" |
| android:label="@string/app_name" |
| |
| android:screenOrientation="landscape"> |
| <!-- configure this activity to use landscape orientation --> |
| |
| <intent-filter> |
| <action android:name="android.intent.action.MAIN" /> |
| <category android:name="android.intent.category.LAUNCHER" /> |
| </intent-filter> |
| </activity> |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> A camera preview does not have to be in landscape mode. |
| Starting in Android 2.2 (API Level 8), you can use the {@link |
| android.hardware.Camera#setDisplayOrientation(int) setDisplayOrientation()} method to set the |
| rotation of the preview image. In order to change preview orientation as the user re-orients the |
| phone, within the {@link |
| android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int) |
| surfaceChanged()} method of your preview class, first stop the preview with {@link |
| android.hardware.Camera#stopPreview() Camera.stopPreview()} change the orientation and then |
| start the preview again with {@link android.hardware.Camera#startPreview() |
| Camera.startPreview()}.</p> |
| |
| <p>In the activity for your camera view, add your preview class to the {@link |
| android.widget.FrameLayout} element shown in the example above. Your camera activity must also |
| ensure that it releases the camera when it is paused or shut down. The following example shows how |
| to modify a camera activity to attach the preview class shown in <a href="#camera-preview">Creating |
| a preview class</a>.</p> |
| |
| <pre> |
| public class CameraActivity extends Activity { |
| |
| private Camera mCamera; |
| private CameraPreview mPreview; |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.main); |
| |
| // Create an instance of Camera |
| mCamera = getCameraInstance(); |
| |
| // Create our Preview view and set it as the content of our activity. |
| mPreview = new CameraPreview(this, mCamera); |
| FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); |
| preview.addView(mPreview); |
| } |
| } |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> The {@code getCameraInstance()} method in the example above |
| refers to the example method shown in <a href="#access-camera">Accessing cameras</a>.</p> |
| |
| |
| <h3 id="capture-picture">Capturing pictures</h3> |
| <p>Once you have built a preview class and a view layout in which to display it, you are ready to |
| start capturing images with your application. In your application code, you must set up listeners |
| for your user interface controls to respond to a user action by taking a picture.</p> |
| |
| <p>In order to retrieve a picture, use the {@link |
| android.hardware.Camera#takePicture(android.hardware.Camera.ShutterCallback, |
| android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback) |
| Camera.takePicture()} method. This method takes three parameters which receive data from the camera. |
| In order to receive data in a JPEG format, you must implement an {@link |
| android.hardware.Camera.PictureCallback} interface to receive the image data and |
| write it to a file. The following code shows a basic implementation of the {@link |
| android.hardware.Camera.PictureCallback} interface to save an image received from the camera.</p> |
| |
| <pre> |
| private PictureCallback mPicture = new PictureCallback() { |
| |
| @Override |
| public void onPictureTaken(byte[] data, Camera camera) { |
| |
| File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); |
| if (pictureFile == null){ |
| Log.d(TAG, "Error creating media file, check storage permissions: " + |
| e.getMessage()); |
| return; |
| } |
| |
| try { |
| FileOutputStream fos = new FileOutputStream(pictureFile); |
| fos.write(data); |
| fos.close(); |
| } catch (FileNotFoundException e) { |
| Log.d(TAG, "File not found: " + e.getMessage()); |
| } catch (IOException e) { |
| Log.d(TAG, "Error accessing file: " + e.getMessage()); |
| } |
| } |
| }; |
| </pre> |
| |
| <p>Trigger capturing an image by calling the {@link |
| android.hardware.Camera#takePicture(android.hardware.Camera.ShutterCallback, |
| android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback) |
| Camera.takePicture()} method. The following example code shows how to call this method from a |
| button {@link android.view.View.OnClickListener}.</p> |
| |
| <pre> |
| // Add a listener to the Capture button |
| Button captureButton = (Button) findViewById(id.button_capture); |
| captureButton.setOnClickListener( |
| new View.OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| // get an image from the camera |
| mCamera.takePicture(null, null, mPicture); |
| } |
| } |
| ); |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> The {@code mPicture} member in the following example refers |
| to the example code above.</p> |
| |
| <p class="caution"><strong>Caution:</strong> Remember to release the {@link android.hardware.Camera} |
| object by calling the {@link android.hardware.Camera#release() Camera.release()} when your |
| application is done using it! For information about how to release the camera, see <a |
| href="#release-camera">Releasing the camera</a>.</p> |
| |
| |
| <h3 id="capture-video">Capturing videos</h3> |
| |
| <p>Video capture using the Android framework requires careful management of the {@link |
| android.hardware.Camera} object and coordination with the {@link android.media.MediaRecorder} |
| class. When recording video with {@link android.hardware.Camera}, you must manage the {@link |
| android.hardware.Camera#lock() Camera.lock()} and {@link android.hardware.Camera#unlock() |
| Camera.unlock()} calls to allow {@link android.media.MediaRecorder} access to the camera hardware, |
| in addition to the {@link android.hardware.Camera#open() Camera.open()} and {@link |
| android.hardware.Camera#release() Camera.release()} calls.</p> |
| |
| <p class="note"><strong>Note:</strong> Starting with Android 4.0 (API level 14), the {@link |
| android.hardware.Camera#lock() Camera.lock()} and {@link android.hardware.Camera#unlock() |
| Camera.unlock()} calls are managed for you automatically.</p> |
| |
| <p>Unlike taking pictures with a device camera, capturing video requires a very particular call |
| order. You must follow a specific order of execution to successfully prepare for and capture video |
| with your application, as detailed below.</p> |
| |
| <ol> |
| <li><strong>Open Camera</strong> - Use the {@link android.hardware.Camera#open() Camera.open()} |
| to get an instance of the camera object.</li> |
| <li><strong>Connect Preview</strong> - Prepare a live camera image preview by connecting a {@link |
| android.view.SurfaceView} to the camera using {@link |
| android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder) Camera.setPreviewDisplay()}. |
| </li> |
| <li><strong>Start Preview</strong> - Call {@link android.hardware.Camera#startPreview() |
| Camera.startPreview()} to begin displaying the live camera images.</li> |
| <li><strong>Start Recording Video</strong> - The following steps must be completed <em>in |
| order</em> to successfully record video: |
| <ol style="list-style-type: lower-alpha;"> |
| <li><strong>Unlock the Camera</strong> - Unlock the camera for use by {@link |
| android.media.MediaRecorder} by calling {@link android.hardware.Camera#unlock() |
| Camera.unlock()}.</li> |
| <li><strong>Configure MediaRecorder</strong> - Call in the following {@link |
| android.media.MediaRecorder} methods <em>in this order</em>. For more information, see the {@link |
| android.media.MediaRecorder} reference documentation. |
| <ol> |
| <li>{@link android.media.MediaRecorder#setCamera(android.hardware.Camera) |
| setCamera()} - Set the camera to be used for video capture, use your application's current instance |
| of {@link android.hardware.Camera}.</li> |
| <li>{@link android.media.MediaRecorder#setAudioSource(int) setAudioSource()} - Set the |
| audio source, use {@link android.media.MediaRecorder.AudioSource#CAMCORDER |
| MediaRecorder.AudioSource.CAMCORDER}. </li> |
| <li>{@link android.media.MediaRecorder#setVideoSource(int) setVideoSource()} - Set |
| the video source, use {@link android.media.MediaRecorder.VideoSource#CAMERA |
| MediaRecorder.VideoSource.CAMERA}.</li> |
| <li>Set the video output format and encoding. For Android 2.2 (API Level 8) and |
| higher, use the {@link android.media.MediaRecorder#setProfile(android.media.CamcorderProfile) |
| MediaRecorder.setProfile} method, and get a profile instance using {@link |
| android.media.CamcorderProfile#get(int) CamcorderProfile.get()}. For versions of Android prior to |
| 2.2, you must set the video output format and encoding parameters: |
| <ol style="list-style-type: lower-roman;"> |
| <li>{@link android.media.MediaRecorder#setOutputFormat(int) setOutputFormat()} - Set |
| the output format, specify the default setting or {@link |
| android.media.MediaRecorder.OutputFormat#MPEG_4 MediaRecorder.OutputFormat.MPEG_4}.</li> |
| <li>{@link android.media.MediaRecorder#setAudioEncoder(int) setAudioEncoder()} - Set |
| the sound encoding type, specify the default setting or {@link |
| android.media.MediaRecorder.AudioEncoder#AMR_NB MediaRecorder.AudioEncoder.AMR_NB}.</li> |
| <li>{@link android.media.MediaRecorder#setVideoEncoder(int) setVideoEncoder()} - Set |
| the video encoding type, specify the default setting or {@link |
| android.media.MediaRecorder.VideoEncoder#MPEG_4_SP MediaRecorder.VideoEncoder.MPEG_4_SP}.</li> |
| </ol> |
| </li> |
| <li>{@link android.media.MediaRecorder#setOutputFile(java.lang.String) setOutputFile()} - |
| Set the output file, use {@code getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()} from the example |
| method in the <a href="#saving-media">Saving Media Files</a> section.</li> |
| <li>{@link android.media.MediaRecorder#setPreviewDisplay(android.view.Surface) |
| setPreviewDisplay()} - Specify the {@link android.view.SurfaceView} preview layout element for |
| your application. Use the same object you specified for <strong>Connect Preview</strong>.</li> |
| </ol> |
| <p class="caution"><strong>Caution:</strong> You must call these {@link |
| android.media.MediaRecorder} configuration methods <em>in this order</em>, otherwise your |
| application will encounter errors and the recording will fail.</p> |
| </li> |
| <li><strong>Prepare MediaRecorder</strong> - Prepare the {@link android.media.MediaRecorder} |
| with provided configuration settings by calling {@link android.media.MediaRecorder#prepare() |
| MediaRecorder.prepare()}.</li> |
| <li><strong>Start MediaRecorder</strong> - Start recording video by calling {@link |
| android.media.MediaRecorder#start() MediaRecorder.start()}.</li> |
| </ol> |
| </li> |
| <li><strong>Stop Recording Video</strong> - Call the following methods <em>in order</em>, to |
| successfully complete a video recording: |
| <ol style="list-style-type: lower-alpha;"> |
| <li><strong>Stop MediaRecorder</strong> - Stop recording video by calling {@link |
| android.media.MediaRecorder#stop() MediaRecorder.stop()}.</li> |
| <li><strong>Reset MediaRecorder</strong> - Optionally, remove the configuration settings from |
| the recorder by calling {@link android.media.MediaRecorder#reset() MediaRecorder.reset()}.</li> |
| <li><strong>Release MediaRecorder</strong> - Release the {@link android.media.MediaRecorder} |
| by calling {@link android.media.MediaRecorder#release() MediaRecorder.release()}.</li> |
| <li><strong>Lock the Camera</strong> - Lock the camera so that future {@link |
| android.media.MediaRecorder} sessions can use it by calling {@link android.hardware.Camera#lock() |
| Camera.lock()}. Starting with Android 4.0 (API level 14), this call is not required unless the |
| {@link android.media.MediaRecorder#prepare() MediaRecorder.prepare()} call fails.</li> |
| </ol> |
| </li> |
| <li><strong>Stop the Preview</strong> - When your activity has finished using the camera, stop the |
| preview using {@link android.hardware.Camera#stopPreview() Camera.stopPreview()}.</li> |
| <li><strong>Release Camera</strong> - Release the camera so that other applications can use |
| it by calling {@link android.hardware.Camera#release() Camera.release()}.</li> |
| </ol> |
| |
| <p class="note"><strong>Note:</strong> It is possible to use {@link android.media.MediaRecorder} |
| without creating a camera preview first and skip the first few steps of this process. However, |
| since users typically prefer to see a preview before starting a recording, that process is not |
| discussed here.</p> |
| |
| <p class="note"><strong>Tip:</strong> If your application is typically used for recording video, set |
| {@link android.hardware.Camera.Parameters#setRecordingHint} to {@code true} prior to starting your |
| preview. This setting can help reduce the time it takes to start recording.</p> |
| |
| <h4 id="configuring-mediarecorder">Configuring MediaRecorder</h4> |
| <p>When using the {@link android.media.MediaRecorder} class to record video, you must perform |
| configuration steps in a <em>specific order</em> and then call the {@link |
| android.media.MediaRecorder#prepare() MediaRecorder.prepare()} method to check and implement the |
| configuration. The following example code demonstrates how to properly configure and prepare the |
| {@link android.media.MediaRecorder} class for video recording.</p> |
| |
| <pre> |
| private boolean prepareVideoRecorder(){ |
| |
| mCamera = getCameraInstance(); |
| mMediaRecorder = new MediaRecorder(); |
| |
| // Step 1: Unlock and set camera to MediaRecorder |
| mCamera.unlock(); |
| mMediaRecorder.setCamera(mCamera); |
| |
| // Step 2: Set sources |
| mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); |
| mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); |
| |
| // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) |
| mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); |
| |
| // Step 4: Set output file |
| mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); |
| |
| // Step 5: Set the preview output |
| mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface()); |
| |
| // Step 6: Prepare configured MediaRecorder |
| try { |
| mMediaRecorder.prepare(); |
| } catch (IllegalStateException e) { |
| Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage()); |
| releaseMediaRecorder(); |
| return false; |
| } catch (IOException e) { |
| Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage()); |
| releaseMediaRecorder(); |
| return false; |
| } |
| return true; |
| } |
| </pre> |
| |
| <p>Prior to Android 2.2 (API Level 8), you must set the output format and encoding formats |
| parameters directly, instead of using {@link android.media.CamcorderProfile}. This approach is |
| demonstrated in the following code:</p> |
| |
| <pre> |
| // Step 3: Set output format and encoding (for versions prior to API Level 8) |
| mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); |
| mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); |
| mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT); |
| </pre> |
| |
| <p>The following video recording parameters for {@link android.media.MediaRecorder} are given |
| default settings, however, you may want to adjust these settings for your application:</p> |
| |
| <ul> |
| <li>{@link android.media.MediaRecorder#setVideoEncodingBitRate(int) |
| setVideoEncodingBitRate()}</li> |
| <li>{@link android.media.MediaRecorder#setVideoSize(int, int) setVideoSize()}</li> |
| <li>{@link android.media.MediaRecorder#setVideoFrameRate(int) setVideoFrameRate()}</li> |
| <li>{@link android.media.MediaRecorder#setAudioEncodingBitRate(int) |
| setAudioEncodingBitRate()}</li> <li>{@link android.media.MediaRecorder#setAudioChannels(int) |
| setAudioChannels()}</li> |
| <li>{@link android.media.MediaRecorder#setAudioSamplingRate(int) setAudioSamplingRate()}</li> |
| </ul> |
| |
| <h4 id="start-stop-mediarecorder">Starting and stopping MediaRecorder</h4> |
| <p>When starting and stopping video recording using the {@link android.media.MediaRecorder} class, |
| you must follow a specific order, as listed below.</p> |
| |
| <ol> |
| <li>Unlock the camera with {@link android.hardware.Camera#unlock() Camera.unlock()}</li> |
| <li>Configure {@link android.media.MediaRecorder} as shown in the code example above</li> |
| <li>Start recording using {@link android.media.MediaRecorder#start() |
| MediaRecorder.start()}</li> |
| <li>Record the video</li> |
| <li>Stop recording using {@link |
| android.media.MediaRecorder#stop() MediaRecorder.stop()}</li> |
| <li>Release the media recorder with {@link android.media.MediaRecorder#release() |
| MediaRecorder.release()}</li> |
| <li>Lock the camera using {@link android.hardware.Camera#lock() Camera.lock()}</li> |
| </ol> |
| |
| <p>The following example code demonstrates how to wire up a button to properly start and stop |
| video recording using the camera and the {@link android.media.MediaRecorder} class.</p> |
| |
| <p class="note"><strong>Note:</strong> When completing a video recording, do not release the camera |
| or else your preview will be stopped.</p> |
| |
| <pre> |
| private boolean isRecording = false; |
| |
| // Add a listener to the Capture button |
| Button captureButton = (Button) findViewById(id.button_capture); |
| captureButton.setOnClickListener( |
| new View.OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| if (isRecording) { |
| // stop recording and release camera |
| mMediaRecorder.stop(); // stop the recording |
| releaseMediaRecorder(); // release the MediaRecorder object |
| mCamera.lock(); // take camera access back from MediaRecorder |
| |
| // inform the user that recording has stopped |
| setCaptureButtonText("Capture"); |
| isRecording = false; |
| } else { |
| // initialize video camera |
| if (prepareVideoRecorder()) { |
| // Camera is available and unlocked, MediaRecorder is prepared, |
| // now you can start recording |
| mMediaRecorder.start(); |
| |
| // inform the user that recording has started |
| setCaptureButtonText("Stop"); |
| isRecording = true; |
| } else { |
| // prepare didn't work, release the camera |
| releaseMediaRecorder(); |
| // inform user |
| } |
| } |
| } |
| } |
| ); |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> In the above example, the {@code prepareVideoRecorder()} |
| method refers to the example code shown in <a |
| href="#configuring-mediarecorder">Configuring MediaRecorder</a>. This method takes care of locking |
| the camera, configuring and preparing the {@link android.media.MediaRecorder} instance.</p> |
| |
| |
| <h3 id="release-camera">Releasing the camera</h3> |
| <p>Cameras are a resource that is shared by applications on a device. Your application can make |
| use of the camera after getting an instance of {@link android.hardware.Camera}, and you must be |
| particularly careful to release the camera object when your application stops using it, and as |
| soon as your application is paused ({@link android.app.Activity#onPause() Activity.onPause()}). If |
| your application does not properly release the camera, all subsequent attempts to access the camera, |
| including those by your own application, will fail and may cause your or other applications to be |
| shut down.</p> |
| |
| <p>To release an instance of the {@link android.hardware.Camera} object, use the {@link |
| android.hardware.Camera#release() Camera.release()} method, as shown in the example code below.</p> |
| |
| <pre> |
| public class CameraActivity extends Activity { |
| private Camera mCamera; |
| private SurfaceView mPreview; |
| private MediaRecorder mMediaRecorder; |
| |
| ... |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| releaseMediaRecorder(); // if you are using MediaRecorder, release it first |
| releaseCamera(); // release the camera immediately on pause event |
| } |
| |
| private void releaseMediaRecorder(){ |
| if (mMediaRecorder != null) { |
| mMediaRecorder.reset(); // clear recorder configuration |
| mMediaRecorder.release(); // release the recorder object |
| mMediaRecorder = null; |
| mCamera.lock(); // lock camera for later use |
| } |
| } |
| |
| private void releaseCamera(){ |
| if (mCamera != null){ |
| mCamera.release(); // release the camera for other applications |
| mCamera = null; |
| } |
| } |
| } |
| </pre> |
| |
| <p class="caution"><strong>Caution:</strong> If your application does not properly release the |
| camera, all subsequent attempts to access the camera, including those by your own application, will |
| fail and may cause your or other applications to be shut down.</p> |
| |
| |
| <h2 id="saving-media">Saving Media Files</h2> |
| <p>Media files created by users such as pictures and videos should be saved to a device's external |
| storage directory (SD Card) to conserve system space and to allow users to access these files |
| without their device. There are many possible directory locations to save media files on a device, |
| however there are only two standard locations you should consider as a developer:</p> |
| |
| <ul> |
| <li><strong>{@link android.os.Environment#getExternalStoragePublicDirectory(java.lang.String) |
| Environment.getExternalStoragePublicDirectory}({@link android.os.Environment#DIRECTORY_PICTURES |
| Environment.DIRECTORY_PICTURES})</strong> - This method returns the standard, shared and recommended |
| location for saving pictures and videos. This directory is shared (public), so other applications |
| can easily discover, read, change and delete files saved in this location. If your application is |
| uninstalled by the user, media files saved to this location will not be removed. To avoid |
| interfering with users existing pictures and videos, you should create a sub-directory for your |
| application's media files within this directory, as shown in the code sample below. This method is |
| available in Android 2.2 (API Level 8), for equivalent calls in earlier API versions, see <a |
| href="{@docRoot}guide/topics/data/data-storage.html#SavingSharedFiles">Saving Shared Files</a>.</li> |
| <li><strong>{@link android.content.Context#getExternalFilesDir(java.lang.String) |
| Context.getExternalFilesDir}({@link android.os.Environment#DIRECTORY_PICTURES |
| Environment.DIRECTORY_PICTURES})</strong> - This method returns a standard location for saving |
| pictures and videos which are associated with your application. If your application is uninstalled, |
| any files saved in this location are removed. Security is not enforced for files in this |
| location and other applications may read, change and delete them.</li> |
| </ul> |
| |
| <p>The following example code demonstrates how to create a {@link java.io.File} or {@link |
| android.net.Uri} location for a media file that can be used when invoking a device's camera with |
| an {@link android.content.Intent} or as part of a <a href="#custom-camera">Building a Camera |
| App</a>.</p> |
| |
| <pre> |
| public static final int MEDIA_TYPE_IMAGE = 1; |
| public static final int MEDIA_TYPE_VIDEO = 2; |
| |
| /** Create a file Uri for saving an image or video */ |
| private static Uri getOutputMediaFileUri(int type){ |
| return Uri.fromFile(getOutputMediaFile(type)); |
| } |
| |
| /** Create a File for saving an image or video */ |
| private static File getOutputMediaFile(int type){ |
| // To be safe, you should check that the SDCard is mounted |
| // using Environment.getExternalStorageState() before doing this. |
| |
| File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( |
| Environment.DIRECTORY_PICTURES), "MyCameraApp"); |
| // This location works best if you want the created images to be shared |
| // between applications and persist after your app has been uninstalled. |
| |
| // Create the storage directory if it does not exist |
| if (! mediaStorageDir.exists()){ |
| if (! mediaStorageDir.mkdirs()){ |
| Log.d("MyCameraApp", "failed to create directory"); |
| return null; |
| } |
| } |
| |
| // Create a media file name |
| String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); |
| File mediaFile; |
| if (type == MEDIA_TYPE_IMAGE){ |
| mediaFile = new File(mediaStorageDir.getPath() + File.separator + |
| "IMG_"+ timeStamp + ".jpg"); |
| } else if(type == MEDIA_TYPE_VIDEO) { |
| mediaFile = new File(mediaStorageDir.getPath() + File.separator + |
| "VID_"+ timeStamp + ".mp4"); |
| } else { |
| return null; |
| } |
| |
| return mediaFile; |
| } |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> {@link |
| android.os.Environment#getExternalStoragePublicDirectory(java.lang.String) |
| Environment.getExternalStoragePublicDirectory()} is available in Android 2.2 (API Level 8) or |
| higher. If you are targeting devices with earlier versions of Android, use {@link |
| android.os.Environment#getExternalStorageDirectory() Environment.getExternalStorageDirectory()} |
| instead. For more information, see <a |
| href="{@docRoot}guide/topics/data/data-storage.html#SavingSharedFiles">Saving Shared Files</a>.</p> |
| |
| <p>For more information about saving files on an Android device, see <a |
| href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a>.</p> |
| |
| |
| <h2 id="camera-features">Camera Features</h2> |
| <p>Android supports a wide array of camera features you can control with your camera application, |
| such as picture format, flash mode, focus settings, and many more. This section lists the common |
| camera features, and briefly discusses how to use them. Most camera features can be accessed and set |
| using the through {@link android.hardware.Camera.Parameters} object. However, there are several |
| important features that require more than simple settings in {@link |
| android.hardware.Camera.Parameters}. These features are covered in the following sections:<p> |
| |
| <ul> |
| <li><a href="#metering-focus-areas">Metering and focus areas</a></li> |
| <li><a href="#face-detection">Face detection</a></li> |
| <li><a href="#time-lapse-video">Time lapse video</a></li> |
| </ul> |
| |
| <p>For general information about how to use features that are controlled through {@link |
| android.hardware.Camera.Parameters}, review the <a href="#using-features">Using camera |
| features</a> section. For more detailed information about how to use features controlled through the |
| camera parameters object, follow the links in the feature list below to the API reference |
| documentation.</p> |
| |
| <p class="table-caption" id="table1"> |
| <strong>Table 1.</strong> Common camera features sorted by the Android API Level in which they |
| were introduced.</p> |
| <table> |
| <tr> |
| <th>Feature</th> <th>API Level</th> <th>Description</th> |
| </tr> |
| <tr> |
| <td><a href="#face-detection">Face Detection</a></td> |
| <td>14</td> |
| <td>Identify human faces within a picture and use them for focus, metering and white |
| balance</td> |
| </tr> |
| <tr> |
| <td><a href="#metering-focus-areas">Metering Areas</a></td> |
| <td>14</td> |
| <td>Specify one or more areas within an image for calculating white balance</td> |
| </tr> |
| <tr> |
| <td><a href="#metering-focus-areas">Focus Areas</a></td> |
| <td>14</td> |
| <td>Set one or more areas within an image to use for focus</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock White Balance Lock}</td> |
| <td>14</td> |
| <td>Stop or start automatic white balance adjustments</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setAutoExposureLock Exposure Lock}</td> |
| <td>14</td> |
| <td>Stop or start automatic exposure adjustments</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera#takePicture Video Snapshot}</td> |
| <td>14</td> |
| <td>Take a picture while shooting video (frame grab)</td> |
| </tr> |
| <tr> |
| <td><a href="#time-lapse-video">Time Lapse Video</a></td> |
| <td>11</td> |
| <td>Record frames with set delays to record a time lapse video</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera#open(int) Multiple Cameras}</td> |
| <td>9</td> |
| <td>Support for more than one camera on a device, including front-facing and back-facing |
| cameras</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#getFocusDistances Focus Distance}</td> |
| <td>9</td> |
| <td>Reports distances between the camera and objects that appear to be in focus</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setZoom Zoom}</td> |
| <td>8</td> |
| <td>Set image magnification</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setExposureCompensation Exposure |
| Compensation}</td> |
| <td>8</td> |
| <td>Increase or decrease the light exposure level</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setGpsLatitude GPS Data}</td> |
| <td>5</td> |
| <td>Include or omit geographic location data with the image</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setWhiteBalance White Balance}</td> |
| <td>5</td> |
| <td>Set the white balance mode, which affects color values in the captured image</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setFocusMode Focus Mode}</td> |
| <td>5</td> |
| <td>Set how the camera focuses on a subject such as automatic, fixed, macro or infinity</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setSceneMode Scene Mode}</td> |
| <td>5</td> |
| <td>Apply a preset mode for specific types of photography situations such as night, beach, snow |
| or candlelight scenes</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setJpegQuality JPEG Quality}</td> |
| <td>5</td> |
| <td>Set the compression level for a JPEG image, which increases or decreases image output file |
| quality and size</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setFlashMode Flash Mode}</td> |
| <td>5</td> |
| <td>Turn flash on, off, or use automatic setting</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setColorEffect Color Effects}</td> |
| <td>5</td> |
| <td>Apply a color effect to the captured image such as black and white, sepia tone or negative. |
| </td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setAntibanding Anti-Banding}</td> |
| <td>5</td> |
| <td>Reduces the effect of banding in color gradients due to JPEG compression</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setPictureFormat Picture Format}</td> |
| <td>1</td> |
| <td>Specify the file format for the picture</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Camera.Parameters#setPictureSize Picture Size}</td> |
| <td>1</td> |
| <td>Specify the pixel dimensions of the saved picture</td> |
| </tr> |
| </table> |
| |
| <p class="note"><strong>Note:</strong> These features are not supported on all devices due to |
| hardware differences and software implementation. For information on checking the availability |
| of features on the device where your application is running, see <a href="#check-feature">Checking |
| feature availability</a>.</p> |
| |
| |
| <h3 id="check-feature">Checking feature availability</h3> |
| <p>The first thing to understand when setting out to use camera features on Android devices is that |
| not all camera features are supported on all devices. In addition, devices that support a particular |
| feature may support them to different levels or with different options. Therefore, part of your |
| decision process as you develop a camera application is to decide what camera features you want to |
| support and to what level. After making that decision, you should plan on including code in your |
| camera application that checks to see if device hardware supports those features and fails |
| gracefully if a feature is not available.</p> |
| |
| <p>You can check the availabilty of camera features by getting an instance of a camera's parameters |
| object, and checking the relevant methods. The following code sample shows you how to obtain a |
| {@link android.hardware.Camera.Parameters} object and check if the camera supports the autofocus |
| feature:</p> |
| |
| <pre> |
| // get Camera parameters |
| Camera.Parameters params = mCamera.getParameters(); |
| |
| List<String> focusModes = params.getSupportedFocusModes(); |
| if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { |
| // Autofocus mode is supported |
| } |
| </pre> |
| |
| <p>You can use the technique shown above for most camera features. The |
| {@link android.hardware.Camera.Parameters} object provides a {@code getSupported...()}, {@code |
| is...Supported()} or {@code getMax...()} method to determine if (and to what extent) a feature is |
| supported.</p> |
| |
| <p>If your application requires certain camera features in order to function properly, you can |
| require them through additions to your application manifest. When you declare the use of specific |
| camera features, such as flash and auto-focus, Google Play restricts your application from |
| being installed on devices which do not support these features. For a list of camera features that |
| can be declared in your app manifest, see the manifest |
| <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features"> Features |
| Reference</a>.</p> |
| |
| <h3 id="using-features">Using camera features</h3> |
| <p>Most camera features are activated and controlled using a {@link |
| android.hardware.Camera.Parameters} object. You obtain this object by first getting an instance of |
| the {@link android.hardware.Camera} object, calling the {@link |
| android.hardware.Camera#getParameters getParameters()} method, changing the returned parameter |
| object and then setting it back into the camera object, as demonstrated in the following example |
| code:</p> |
| |
| <pre> |
| // get Camera parameters |
| Camera.Parameters params = mCamera.getParameters(); |
| // set the focus mode |
| params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); |
| // set Camera parameters |
| mCamera.setParameters(params); |
| </pre> |
| |
| <p>This technique works for nearly all camera features, and most parameters can be changed at any |
| time after you have obtained an instance of the {@link android.hardware.Camera} object. Changes to |
| parameters are typically visible to the user immediately in the application's camera preview. |
| On the software side, parameter changes may take several frames to actually take effect as the |
| camera hardware processes the new instructions and then sends updated image data.</p> |
| |
| <p class="caution"><strong>Important:</strong> Some camera features cannot be changed at will. In |
| particular, changing the size or orientation of the camera preview requires that you first stop the |
| preview, change the preview size, and then restart the preview. Starting with Android 4.0 (API |
| Level 14) preview orientation can be changed without restarting the preview.</p> |
| |
| <p>Other camera features require more code in order to implement, including:</p> |
| <ul> |
| <li>Metering and focus areas</li> |
| <li>Face detection</li> |
| <li>Time lapse video</li> |
| </ul> |
| <p>A quick outline of how to implement these features is provided in the following sections.</p> |
| |
| |
| <h3 id="metering-focus-areas">Metering and focus areas</h3> |
| <p>In some photographic scenarios, automatic focusing and light metering may not produce the |
| desired results. Starting with Android 4.0 (API Level 14), your camera application can provide |
| additional controls to allow your app or users to specify areas in an image to use for determining |
| focus or light level settings and pass these values to the camera hardware for use in capturing |
| images or video.</p> |
| |
| <p>Areas for metering and focus work very similarly to other camera features, in that you control |
| them through methods in the {@link android.hardware.Camera.Parameters} object. The following code |
| demonstrates setting two light metering areas for an instance of |
| {@link android.hardware.Camera}:</p> |
| |
| <pre> |
| // Create an instance of Camera |
| mCamera = getCameraInstance(); |
| |
| // set Camera parameters |
| Camera.Parameters params = mCamera.getParameters(); |
| |
| if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported |
| List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); |
| |
| Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image |
| meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60% |
| Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image |
| meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40% |
| params.setMeteringAreas(meteringAreas); |
| } |
| |
| mCamera.setParameters(params); |
| </pre> |
| |
| <p>The {@link android.hardware.Camera.Area} object contains two data parameters: A {@link |
| android.graphics.Rect} object for specifying an area within the camera's field of view and a weight |
| value, which tells the camera what level of importance this area should be given in light metering |
| or focus calculations.</p> |
| |
| <p>The {@link android.graphics.Rect} field in a {@link android.hardware.Camera.Area} object |
| describes a rectangular shape mapped on a 2000 x 2000 unit grid. The coordinates -1000, -1000 |
| represent the top, left corner of the camera image, and coordinates 1000, 1000 represent the |
| bottom, right corner of the camera image, as shown in the illustration below.</p> |
| |
| <img src='images/camera-area-coordinates.png' /> |
| <p class="img-caption"> |
| <strong>Figure 1.</strong> The red lines illustrate the coordinate system for specifying a |
| {@link android.hardware.Camera.Area} within a camera preview. The blue box shows the location and |
| shape of an camera area with the {@link android.graphics.Rect} values 333,333,667,667. |
| </p> |
| |
| <p>The bounds of this coordinate system always correspond to the outer edge of the image visible in |
| the camera preview and do not shrink or expand with the zoom level. Similarly, rotation of the image |
| preview using {@link android.hardware.Camera#setDisplayOrientation Camera.setDisplayOrientation()} |
| does not remap the coordinate system.</p> |
| |
| |
| <h3 id="face-detection">Face detection</h3> |
| <p>For pictures that include people, faces are usually the most important part of the picture, and |
| should be used for determining both focus and white balance when capturing an image. The Android 4.0 |
| (API Level 14) framework provides APIs for identifying faces and calculating picture settings using |
| face recognition technology.</p> |
| |
| <p class="note"><strong>Note:</strong> While the face detection feature is running, |
| {@link android.hardware.Camera.Parameters#setWhiteBalance}, |
| {@link android.hardware.Camera.Parameters#setFocusAreas} and |
| {@link android.hardware.Camera.Parameters#setMeteringAreas} have no effect.</p> |
| |
| <p>Using the face detection feature in your camera application requires a few general steps:</p> |
| <ul> |
| <li>Check that face detection is supported on the device</li> |
| <li>Create a face detection listener</li> |
| <li>Add the face detection listener to your camera object</li> |
| <li>Start face detection after preview (and after <em>every</em> preview restart)</li> |
| </ul> |
| |
| <p>The face detection feature is not supported on all devices. You can check that this feature is |
| supported by calling {@link android.hardware.Camera.Parameters#getMaxNumDetectedFaces}. An |
| example of this check is shown in the {@code startFaceDetection()} sample method below.</p> |
| |
| <p>In order to be notified and respond to the detection of a face, your camera application must set |
| a listener for face detection events. In order to do this, you must create a listener class that |
| implements the {@link android.hardware.Camera.FaceDetectionListener} interface as shown in the |
| example code below.</p> |
| |
| <pre> |
| class MyFaceDetectionListener implements Camera.FaceDetectionListener { |
| |
| @Override |
| public void onFaceDetection(Face[] faces, Camera camera) { |
| if (faces.length > 0){ |
| Log.d("FaceDetection", "face detected: "+ faces.length + |
| " Face 1 Location X: " + faces[0].rect.centerX() + |
| "Y: " + faces[0].rect.centerY() ); |
| } |
| } |
| } |
| </pre> |
| |
| <p>After creating this class, you then set it into your application's |
| {@link android.hardware.Camera} object, as shown in the example code below:</p> |
| |
| <pre> |
| mCamera.setFaceDetectionListener(new MyFaceDetectionListener()); |
| </pre> |
| |
| <p>Your application must start the face detection function each time you start (or restart) the |
| camera preview. Create a method for starting face detection so you can call it as needed, as shown |
| in the example code below.</p> |
| |
| <pre> |
| public void startFaceDetection(){ |
| // Try starting Face Detection |
| Camera.Parameters params = mCamera.getParameters(); |
| |
| // start face detection only *after* preview has started |
| if (params.getMaxNumDetectedFaces() > 0){ |
| // camera supports face detection, so can start it: |
| mCamera.startFaceDetection(); |
| } |
| } |
| </pre> |
| |
| <p>You must start face detection <em>each time</em> you start (or restart) the camera preview. If |
| you use the preview class shown in <a href="#camera-preview">Creating a preview class</a>, add your |
| {@link android.hardware.Camera#startFaceDetection startFaceDetection()} method to both the |
| {@link android.view.SurfaceHolder.Callback#surfaceCreated surfaceCreated()} and {@link |
| android.view.SurfaceHolder.Callback#surfaceChanged surfaceChanged()} methods in your preview class, |
| as shown in the sample code below.</p> |
| |
| <pre> |
| public void surfaceCreated(SurfaceHolder holder) { |
| try { |
| mCamera.setPreviewDisplay(holder); |
| mCamera.startPreview(); |
| |
| startFaceDetection(); // start face detection feature |
| |
| } catch (IOException e) { |
| Log.d(TAG, "Error setting camera preview: " + e.getMessage()); |
| } |
| } |
| |
| public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { |
| |
| if (mHolder.getSurface() == null){ |
| // preview surface does not exist |
| Log.d(TAG, "mHolder.getSurface() == null"); |
| return; |
| } |
| |
| try { |
| mCamera.stopPreview(); |
| |
| } catch (Exception e){ |
| // ignore: tried to stop a non-existent preview |
| Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); |
| } |
| |
| try { |
| mCamera.setPreviewDisplay(mHolder); |
| mCamera.startPreview(); |
| |
| startFaceDetection(); // re-start face detection feature |
| |
| } catch (Exception e){ |
| // ignore: tried to stop a non-existent preview |
| Log.d(TAG, "Error starting camera preview: " + e.getMessage()); |
| } |
| } |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> Remember to call this method <em>after</em> calling |
| {@link android.hardware.Camera#startPreview startPreview()}. Do not attempt to start face detection |
| in the {@link android.app.Activity#onCreate onCreate()} method of your camera app's main activity, |
| as the preview is not available by this point in your application's the execution.</p> |
| |
| |
| <h3 id="time-lapse-video">Time lapse video</h3> |
| <p>Time lapse video allows users to create video clips that combine pictures taken a few seconds or |
| minutes apart. This feature uses {@link android.media.MediaRecorder} to record the images for a time |
| lapse sequence. </p> |
| |
| <p>To record a time lapse video with {@link android.media.MediaRecorder}, you must configure the |
| recorder object as if you are recording a normal video, setting the captured frames per second to a |
| low number and using one of the time lapse quality settings, as shown in the code example below.</p> |
| |
| <pre> |
| // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) |
| mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); |
| ... |
| // Step 5.5: Set the video capture rate to a low number |
| mMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds |
| </pre> |
| |
| <p>These settings must be done as part of a larger configuration procedure for {@link |
| android.media.MediaRecorder}. For a full configuration code example, see <a |
| href="#configuring-mediarecorder">Configuring MediaRecorder</a>. Once the configuration is complete, |
| you start the video recording as if you were recording a normal video clip. For more information |
| about configuring and running {@link android.media.MediaRecorder}, see <a |
| href="#capture-video">Capturing videos</a>.</p> |