diff options
author | Scott Main <smain@google.com> | 2011-12-15 15:59:34 -0800 |
---|---|---|
committer | Scott Main <smain@google.com> | 2011-12-15 16:01:59 -0800 |
commit | 564e8aa41c29ebd10cb691851d4ecc347f8eee71 (patch) | |
tree | 5be6298b2991d3505fbc7b787deb38fbac2c04f5 /docs | |
parent | d25ad2fdbb4cf86e2a05dbc6b8afb50760c0fe1b (diff) | |
download | frameworks_base-564e8aa41c29ebd10cb691851d4ecc347f8eee71.zip frameworks_base-564e8aa41c29ebd10cb691851d4ecc347f8eee71.tar.gz frameworks_base-564e8aa41c29ebd10cb691851d4ecc347f8eee71.tar.bz2 |
docs: Android University - Camera class
Change-Id: Idc0c6ca88b42908289701c8367cd5c403d85f71e
Diffstat (limited to 'docs')
-rw-r--r-- | docs/html/shareables/training/PhotoIntentActivity.zip | bin | 0 -> 15261 bytes | |||
-rw-r--r-- | docs/html/training/camera/cameradirect.jd | 308 | ||||
-rw-r--r-- | docs/html/training/camera/index.jd | 60 | ||||
-rw-r--r-- | docs/html/training/camera/photobasics.jd | 258 | ||||
-rw-r--r-- | docs/html/training/camera/videobasics.jd | 118 |
5 files changed, 744 insertions, 0 deletions
diff --git a/docs/html/shareables/training/PhotoIntentActivity.zip b/docs/html/shareables/training/PhotoIntentActivity.zip Binary files differnew file mode 100644 index 0000000..9fcc0e1 --- /dev/null +++ b/docs/html/shareables/training/PhotoIntentActivity.zip diff --git a/docs/html/training/camera/cameradirect.jd b/docs/html/training/camera/cameradirect.jd new file mode 100644 index 0000000..d37f2c4 --- /dev/null +++ b/docs/html/training/camera/cameradirect.jd @@ -0,0 +1,308 @@ +page.title=Controlling the Camera +parent.title=Capturing Photos with the Camera +parent.link=index.html + +trainingnavtop=true +previous.title=Recording Videos Simply +previous.link=videobasics.html + +@jd:body + + +<div id="tb-wrapper"> + <div id="tb"> + + <h2>This lesson teaches you to</h2> + <ol> + <li><a href="#TaskOpenCamera">Open the Camera Object</a></li> + <li><a href="#camera-preview">Create the Camera Preview</a></li> + <li><a href="#TaskSettings">Modify Camera Settings</a></li> + <li><a href="#TaskOrientation">Set the Preview Orientation</a></li> + <li><a href="#TaskTakePicture">Take a Picture</a></li> + <li><a href="#TaskRestartPreview">Restart the Preview</a></li> + <li><a href="#TaskReleaseCamera">Stop the Preview and Release the Camera</a></li> + </ol> + + <h2>You should also read</h2> + <ul> + <li><a href="{@docRoot}guide/topics/media/camera.html#custom-camera">Building + a Camera App</a></li> + </ul> + </div> +</div> + +<p>In this lesson, we discuss how to control the camera hardware directly using +the framework APIs.</p> + +<p>Directly controlling a device camera requires a lot more code than requesting pictures or videos +from existing camera applications. However, if you want to build a specialized camera application or +or something fully integrated in your app UI, this lesson shows you how.</p> + + +<h2 id="TaskOpenCamera">Open the Camera Object</h2> + +<p>Getting an instance of the {@link android.hardware.Camera} object is the first step in the +process of directly controlling the camera. As Android's own Camera application does, the +recommended way to access the camera is to open {@link android.hardware.Camera} on a separate thread +that's launched from {@link android.app.Activity#onCreate onCreate()}. This approach is a good idea +since it can take a while and might bog down the UI thread. However, in the sample application +associated with this lesson, opening the camera is deferred to the {@link +android.app.Activity#onResume onResume()} method to facilitate code reuse and keep the flow of +control simple.</p> + +<pre> +private void openCameraPerIdAndSetPreview() { + if (! safeCameraOpen(mCameraId)) { + mCameraId = getFirstRearCameraID(); + safeCameraOpen(mCameraId); + } + + mPreview.setCamera(mCamera); +} +</pre> + +<p>Since API level 9, the camera framework supports multiple cameras. If you use the +legacy API and call {@link android.hardware.Camera#open open()} without an +argument, you get the first rear-facing camera. Dealing with multiple cameras +is an advanced topic and beyond the scope of this lesson. If you are really +interested, check out the implementation of {@code getFirstRearCameraID()} in +the sample app (downloadable at the top).</p> + +<p>Calling {@link android.hardware.Camera#open Camera.open()} throws an +exception if the camera is already in use by another application, so we wrap it +in a {@code try} block.</p> + +<pre> +private boolean safeCameraOpen(int id) { + boolean qOpened = false; + + try { + releaseCameraAndPreview(); + mCamera = Camera.open(mCameraId); + qOpened = (mCamera != null); + } catch (Exception e) { + Log.e(getString(R.string.app_name), "failed to open Camera"); + e.printStackTrace(); + } + + return qOpened; +} + +private void releaseCameraAndPreview() { + mPreview.setCamera(null); + if (mCamera != null) { + mCamera.release(); + mCamera = null; + } +} +</pre> + + +<h2 id="camera-preview">Create the Camera Preview</h2> + +<p>Taking a picture usually requires that your users see a preview of their subject before clicking +the shutter. To do so, you can use a {@link android.view.SurfaceView} to draw previews of what the +camera sensor is picking up.</p> + +<h3 id="TaskSetPreview">Preview Class</h3> + +<p>To get started with displaying a preview, you need preview class. The +preview requires an implementation of the {@code +android.view.SurfaceHolder.Callback} interface, which is used to pass image +data from the camera hardware the application.</p> + +<pre> +class Preview extends ViewGroup implements SurfaceHolder.Callback { +... + + SurfaceView mSurfaceView; + SurfaceHolder mHolder; + +... + + Preview(Context context) { + super(context); + + mSurfaceView = new SurfaceView(context); + addView(mSurfaceView); + + // Install a SurfaceHolder.Callback so we get notified when the + // underlying surface is created and destroyed. + mHolder = mSurfaceView.getHolder(); + mHolder.addCallback(this); + mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + } +... +} +</pre> + +<p>The preview class must be passed to the {@link android.hardware.Camera} object before the live +image preview can be started, as seen in {@code setCamera()} method of the sample, +as shown in the next section.</p> + + +<h3 id="TaskStartPreview">Set and Start the Preview</h2> + +<p>A camera instance and its related preview must be created in a specific +order, with the camera object being first. In the sample application, the +process of initializing the camera is encapsulated so that {@link +android.hardware.Camera#startPreview Camera.startPreview()} is called by the +{@code setCamera()} method, whenever the user does something to change the +camera. The preview must also be restarted in the preview class {@code +surfaceChanged()} callback method.</p> + +<pre> +public void setCamera(Camera camera) { + if (mCamera == camera) { return; } + + stopPreviewAndFreeCamera(); + + mCamera = camera; + + if (mCamera != null) { + List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes(); + mSupportedPreviewSizes = localSizes; + requestLayout(); + + try { + mCamera.setPreviewDisplay(mHolder); + } catch (IOException e) { + e.printStackTrace(); + } + + /* + Important: Call startPreview() to start updating the preview surface. Preview must + be started before you can take a picture. + */ + mCamera.startPreview(); + } +} +</pre> + + +<h2 id="TaskSettings">Modify Camera Settings</h2> + +<p>Camera settings change the way that the camera takes pictures, from the zoom +level to exposure compensation. This example doesn’t do a whole lot with camera +settings, but the APIs provide a wide array of options. The {@code surfaceChanged()} method in the +sample app demonstrates how to get and set camera parameters:</p> + +<pre> +public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + // Now that the size is known, set up the camera parameters and begin + // the preview. + Camera.Parameters parameters = mCamera.getParameters(); + parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); + requestLayout(); + mCamera.setParameters(parameters); + + /* + Important: Call startPreview() to start updating the preview surface. Preview must be + started before you can take a picture. + */ + mCamera.startPreview(); +} +</pre> + + +<h2 id="TaskOrientation">Set the Preview Orientation</h2> + +<p>Most camera applications lock the display into landscape mode because that is the natural +orientation of the camera sensor. This setting does not prevent you from taking portrait-mode +photos, because the orientation of the device is recorded in the EXIF header. The {@link +android.hardware.Camera#setDisplayOrientation setCameraDisplayOrientation()} method lets you change +how the preview is displayed without affecting how the image is recorded. However, in Android prior +to API level 14, you must stop your preview before changing the orientation and then restart it.</p> + + +<h2 id="TaskTakePicture">Take a Picture</h2> + +<p>Use the {@link android.hardware.Camera#takePicture Camera.takePicture()} +method to take a picture once the preview is started. You can create {@link +android.hardware.Camera.PictureCallback} and {@link +android.hardware.Camera.ShutterCallback} objects and pass them into {@link +android.hardware.Camera#takePicture Camera.takePicture()}. Since the Android +Camera application already does a great job capturing JPEG images, you should +probably implement the raw-image callback.</p> + +<p>If you want to grab images continously, you can create a {@link +android.hardware.Camera.PreviewCallback} that implements {@link +android.hardware.Camera.PreviewCallback#onPreviewFrame onPreviewFrame()}. For +something in between, you can capture only selected preview frames, or set up a +delayed action to call {@link android.hardware.Camera#takePicture +takePicture()}.</p> + + +<h2 id="TaskRestartPreview">Restart the Preview</h2> + +<p>After a picture is taken, you must to restart the preview before the user +can take another picture. In the example, the restart is done by overloading +the shutter button, as shown below.</p> + +<pre> +@Override +public void onClick(View v) { + switch(mPreviewState) { + case K_STATE_FROZEN: + mCamera.startPreview(); + mPreviewState = K_STATE_PREVIEW; + break; + + default: + mCamera.takePicture( null, rawCallback, null); + mPreviewState = K_STATE_BUSY; + } // switch + shutterBtnConfig(); +} +</pre> + + +<h2 id="TaskReleaseCamera">Stop the Preview and Release the Camera</h2> + +<p>Once your application is done using the camera, it's time to clean up. In +particular, you must release the {@link android.hardware.Camera} object, or you risk crashing other +applications, including new instances of your own application.</p> + +<p>When should you stop the preview and release the camera? Well, having your +preview surface destroyed is a pretty good hint that it’s time to stop the +preview and release the camera, as shown in these methods from the {@code +Preview} class.</p> + +<pre> +public void surfaceDestroyed(SurfaceHolder holder) { + // Surface will be destroyed when we return, so stop the preview. + if (mCamera != null) { + /* + Call stopPreview() to stop updating the preview surface. + */ + mCamera.stopPreview(); + } +} + +/** + * When this function returns, mCamera will be null. + */ +private void stopPreviewAndFreeCamera() { + + if (mCamera != null) { + /* + Call stopPreview() to stop updating the preview surface. + */ + mCamera.stopPreview(); + + /* + Important: Call release() to release the camera for use by other applications. + Applications should release the camera immediately in onPause() (and re-open() it in + onResume()). + */ + mCamera.release(); + + mCamera = null; + } +} +</pre> + +<p>In the example application, this procedure is also part of the {@code +setCamera()} method, so initializing a camera always begins with stopping the +preview.</p> + diff --git a/docs/html/training/camera/index.jd b/docs/html/training/camera/index.jd new file mode 100644 index 0000000..400f636 --- /dev/null +++ b/docs/html/training/camera/index.jd @@ -0,0 +1,60 @@ +page.title=Capturing Photos with the Camera + +trainingnavtop=true +startpage=true +next.title=Taking Photos Simply +next.link=photobasics.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + + +<h2>Dependencies and prerequisites</h2> +<ul> + <li>Android 1.5 (API level 3) or higher</li> + <li>A device with a camera</li> +</ul> + + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}guide/topics/media/camera.html">Camera</a></li> + <li><a href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a></li> +</ul> + + +<h2>Try it out</h2> + +<div class="download-box"> + <a href="{@docRoot}shareables/training/PhotoIntentActivity.zip" class="button">Download the Intent sample</a> + <p class="filename">PhotoIntentActivity.zip</p> +</div> + +</div> +</div> + +<p>The world was a dismal and featureless place before rich media became +prevalent. Remember Gopher? We don't, either. For your app to become +part of your users' lives, give them a way to put their lives into it. +Using the on-board cameras, your application can enable users to augment what +they see around them, make unique avatars, look for zombies around the corner, +or simply share their experiences.</p> + +<p>This class gets you clicking fast with some super-easy ways of +leveraging existing camera applications. In later lessons, you dive deeper +and learn how to control the camera hardware directly.</p> + + +<h2>Lessons</h2> + +<dl> + <dt><b><a href="photobasics.html">Taking Photos Simply</a></b></dt> + <dd>Leverage other applications and capture photos with just a few lines of code.</dd> + <dt><b><a href="videobasics.html">Recording Videos Simply</a></b></dt> + <dd>Leverage other applications and record videos with just a few lines of code.</dd> + <dt><b><a href="cameradirect.html">Controlling the Camera</a></b></dt> + <dd>Control the camera hardware directly and implement your own camera application.</dd> +</dl> + diff --git a/docs/html/training/camera/photobasics.jd b/docs/html/training/camera/photobasics.jd new file mode 100644 index 0000000..002dec7 --- /dev/null +++ b/docs/html/training/camera/photobasics.jd @@ -0,0 +1,258 @@ +page.title=Taking Photos Simply +parent.title=Capturing Photos with the Camera +parent.link=index.html + +trainingnavtop=true +next.title=Recording Videos Simply +next.link=videobasics.html + +@jd:body + + +<div id="tb-wrapper"> + <div id="tb"> + + <h2>This lesson teaches you to</h2> + <ol> + <li><a href="#TaskManifest">Request Camera Permission</a></li> + <li><a href="#TaskCaptureIntent">Take a Photo with the Camera App</a></li> + <li><a href="#TaskPhotoView">View the Photo</a></li> + <li><a href="#TaskPath">Save the Photo</a></li> + <li><a href="#TaskGallery">Add the Photo to a Gallery</a></li> + <li><a href="#TaskScalePhoto">Decode a Scaled Image</a></li> + </ol> + + <h2>You should also read</h2> + <ul> + <li><a href="{@docRoot}guide/topics/media/camera.html">Camera</a></li> + <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent + Filters</a></li> + </ul> + + <h2>Try it out</h2> + <div class="download-box"> + <a href="{@docRoot}shareables/training/PhotoIntentActivity.zip" class="button">Download the +sample</a> + <p class="filename">PhotoIntentActivity.zip</p> + </div> + + </div> +</div> + +<p>This lesson explains how to capture photos using an existing camera +application.</p> + +<p>Suppose you are implementing a crowd-sourced weather service that makes a +global weather map by blending together pictures of the sky taken by devices +running your client app. Integrating photos is only a small part of your +application. You want to take photos with minimal fuss, not reinvent the +camera. Happily, most Android-powered devices already have at least one camera +application installed. In this lesson, you learn how to make it take a picture +for you.</p> + + +<h2 id="TaskManifest">Request Camera Permission</h2> + +<p>If an essential function of your application is taking pictures, then restrict +its visibility in Android Market to devices that have a camera. To advertise +that your application depends on having a camera, put a <a +href="{@docRoot}guide/topics/manifest/uses-feature-element.html"> {@code +<uses-feature>}</a> tag in your manifest file:</p> + +<pre> +<manifest ... > + <uses-feature android:name="android.hardware.camera" /> + ... +</manifest ... > +</pre> + +<p>If your application uses, but does not require a camera in order to function, add {@code +android:required="false"} to the tag. In doing so, Android Market will allow devices without a +camera to download your application. It's then your responsibility to check for the availability +of the camera at runtime by calling {@link +android.content.pm.PackageManager#hasSystemFeature hasSystemFeature(PackageManager.FEATURE_CAMERA)}. +If a camera is not available, you should then disable your camera features.</p> + + +<h2 id="TaskCaptureIntent">Take a Photo with the Camera App</h2> + +<p>The Android way of delegating actions to other applications is to invoke an {@link +android.content.Intent} that describes what you want done. This process involves three pieces: The +{@link android.content.Intent} itself, a call to start the external {@link android.app.Activity}, +and some code to handle the image data when focus returns to your activity.</p> + +<p>Here's a function that invokes an intent to capture a photo.</p> + +<pre> +private void dispatchTakePictureIntent(int actionCode) { + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(takePictureIntent, actionCode); +} +</pre> + + +<p>Congratulations: with this code, your application has gained the ability to +make another camera application do its bidding! Of course, if no compatible +application is ready to catch the intent, then your app will fall down like a +botched stage dive. Here is a function to check whether an app can handle your intent:</p> + +<pre> +public static boolean isIntentAvailable(Context context, String action) { + final PackageManager packageManager = context.getPackageManager(); + final Intent intent = new Intent(action); + List<ResolveInfo> list = + packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + return list.size() > 0; +} +</pre> + + +<h2 id="TaskPhotoView">View the Photo</h2> + +<p>If the simple feat of taking a photo is not the culmination of your app's +ambition, then you probably want to get the image back from the camera +application and do something with it.</p> + +<p>The Android Camera application encodes the photo in the return {@link android.content.Intent} +delivered to {@link android.app.Activity#onActivityResult onActivityResult()} as a small {@link +android.graphics.Bitmap} in the extras, under the key {@code "data"}. The following code retrieves +this image and displays it in an {@link android.widget.ImageView}.</p> + +<pre> +private void handleSmallCameraPhoto(Intent intent) { + Bundle extras = intent.getExtras(); + mImageBitmap = (Bitmap) extras.get("data"); + mImageView.setImageBitmap(mImageBitmap); +} +</pre> + +<p class="note"><strong>Note:</strong> This thumbnail image from {@code "data"} might be good for an +icon, but not a lot more. Dealing with a full-sized image takes a bit more +work.</p> + + +<h2 id="TaskPath">Save the Photo</h2> + +<p>The Android Camera application saves a full-size photo if you give it a file to +save into. You must provide a path that includes the storage volume, +folder, and file name.</p> + +<p>There is an easy way to get the path for photos, but it works only on Android 2.2 (API level 8) +and later:</p> + +<pre> +storageDir = new File( + Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES + ), + getAlbumName() +); +</pre> + +<p>For earlier API levels, you have to provide the name of the photo +directory yourself.</p> + +<pre> +storageDir = new File ( + Environment.getExternalStorageDirectory() + + PICTURES_DIR + + getAlbumName() +); +</pre> + +<p class="note"><strong>Note:</strong> The path component {@code PICTURES_DIR} is +just {@code Pictures/}, the standard location for shared photos on the external/shared +storage.</p> + + +<h3 id="TaskFileName">Set the file name</h3> + +<p>As shown in the previous section, the file location for an image should be +driven by the device environment. What you need to do yourself is choose a +collision-resistant file-naming scheme. You may wish also to save the path in a +member variable for later use. Here's an example solution:</p> + +<pre> +private File createImageFile() throws IOException { + // Create an image file name + String timeStamp = + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_"; + File image = File.createTempFile( + imageFileName, + JPEG_FILE_SUFFIX, + getAlbumDir() + ); + mCurrentPhotoPath = image.getAbsolutePath(); + return image; +} +</pre> + + +<h3 id="TaskIntentFileName">Append the file name onto the Intent</h3> + +<p>Once you have a place to save your image, pass that location to the camera +application via the {@link android.content.Intent}.</p> + +<pre> +File f = createImageFile(); +takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); +</pre> + + +<h2 id="TaskGallery">Add the Photo to a Gallery</h2> + +<p>When you create a photo through an intent, you should know where your image is located, because +you said where to save it in the first place. For everyone else, perhaps the easiest way to make +your photo accessible is to make it accessible from the system's Media Provider.</p> + +<p>The following example method demonstrates how to invoke the system's media scanner to add your +photo to the Media Provider's database, making it available in the Android Gallery application +and to other apps.</p> + +<pre> +private void galleryAddPic() { + Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + File f = new File(mCurrentPhotoPath); + Uri contentUri = Uri.fromFile(f); + mediaScanIntent.setData(contentUri); + this.sendBroadcast(mediaScanIntent); +} +</pre> + + +<h2 id="TaskScalePhoto">Decode a Scaled Image</h2> + +<p>Managing multiple full-sized images can be tricky with limited memory. If +you find your application running out of memory after displaying just a few +images, you can dramatically reduce the amount of dynamic heap used by +expanding the JPEG into a memory array that's already scaled to match the size +of the destination view. The following example method demonstrates this +technique.</p> + +<pre> +private void setPic() { + // Get the dimensions of the View + int targetW = mImageView.getWidth(); + int targetH = mImageView.getHeight(); + + // Get the dimensions of the bitmap + BitmapFactory.Options bmOptions = new BitmapFactory.Options(); + bmOptions.inJustDecodeBounds = true; + BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); + int photoW = bmOptions.outWidth; + int photoH = bmOptions.outHeight; + + // Determine how much to scale down the image + int scaleFactor = Math.min(photoW/targetW, photoH/targetH); + + // Decode the image file into a Bitmap sized to fill the View + bmOptions.inJustDecodeBounds = false; + bmOptions.inSampleSize = scaleFactor; + bmOptions.inPurgeable = true; + + Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); + mImageView.setImageBitmap(bitmap); +} +</pre> + diff --git a/docs/html/training/camera/videobasics.jd b/docs/html/training/camera/videobasics.jd new file mode 100644 index 0000000..a0f5732 --- /dev/null +++ b/docs/html/training/camera/videobasics.jd @@ -0,0 +1,118 @@ +page.title=Recording Videos Simply +parent.title=Capturing Photos with the Camera +parent.link=index.html + +trainingnavtop=true +previous.title=Recording Photos Simply +previous.link=photobasics.html +next.title=Controlling the Camera +next.link=cameradirect.html + +@jd:body + + +<div id="tb-wrapper"> + <div id="tb"> + + <h2>This lesson teaches you to</h2> + <ol> + <li><a href="#TaskManifest">Request Camera Permission</a></li> + <li><a href="#TaskCaptureIntent">Record a Video with a Camera App</a> + <li><a href="#TaskVideoView">View the Video</a></li> + </ol> + + <h2>You should also read</h2> + <ul> + <li><a href="{@docRoot}guide/topics/media/camera.html">Camera</a></li> + <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent + Filters</a></li> + </ul> + + <h2>Try it out</h2> + + <div class="download-box"> + <a href="{@docRoot}shareables/training/PhotoIntentActivity.zip" class="button">Download the +sample</a> + <p class="filename">PhotoIntentActivity.zip</p> + </div> + </div> +</div> + + +<p>This lesson explains how to capture video using existing camera +applications.</p> + +<p>Your application has a job to do, and integrating videos is only a small +part of it. You want to take videos with minimal fuss, and not reinvent the +camcorder. Happily, most Android-powered devices already have a camera application that +records video. In this lesson, you make it do this for you.</p> + + + +<h2 id="TaskManifest">Request Camera Permission</h2> + +<p>To advertise that your application depends on having a camera, put a +{@code <uses-feature>} tag in the manifest file:</p> + +<pre> +<manifest ... > + <uses-feature android:name="android.hardware.camera" /> + ... +</manifest ... > +</pre> + +<p>If your application uses, but does not require a camera in order to function, add {@code +android:required="false"} to the tag. In doing so, Android Market will allow devices without a +camera to download your application. It's then your responsibility to check for the availability +of the camera at runtime by calling {@link +android.content.pm.PackageManager#hasSystemFeature hasSystemFeature(PackageManager.FEATURE_CAMERA)}. +If a camera is not available, you should then disable your camera features.</p> + + +<h2 id="TaskCaptureIntent">Record a Video with a Camera App</h2> + +<p>The Android way of delegating actions to other applications is to invoke +an {@link android.content.Intent} that describes what you want done. This +involves three pieces: the {@link android.content.Intent} itself, a call to start the external +{@link android.app.Activity}, and some code to handle the video when focus returns +to your activity.</p> + +<p>Here's a function that invokes an intent to capture video.</p> + +<pre> +private void dispatchTakeVideoIntent() { + Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + startActivityForResult(takeVideoIntent, ACTION_TAKE_VIDEO); +} +</pre> + + +<p>It's a good idea to make sure an app exists to handle your intent +before invoking it. Here's a function that checks for apps that can handle your intent:</p> + +<pre> +public static boolean isIntentAvailable(Context context, String action) { + final PackageManager packageManager = context.getPackageManager(); + final Intent intent = new Intent(action); + List<ResolveInfo> list = + packageManager.queryIntentActivities(intent, + PackageManager.MATCH_DEFAULT_ONLY); + return list.size() > 0; +} +</pre> + + +<h2 id="TaskVideoView">View the Video</h2> + +<p>The Android Camera application returns the video in the {@link android.content.Intent} delivered +to {@link android.app.Activity#onActivityResult onActivityResult()} as a {@link +android.net.Uri} pointing to the video location in storage. The following code +retrieves this image and displays it in a {@link android.widget.VideoView}.</p> + +<pre> +private void handleCameraVideo(Intent intent) { + mVideoUri = intent.getData(); + mVideoView.setVideoURI(mVideoUri); +} +</pre> + |