From 564e8aa41c29ebd10cb691851d4ecc347f8eee71 Mon Sep 17 00:00:00 2001 From: Scott Main Date: Thu, 15 Dec 2011 15:59:34 -0800 Subject: [PATCH] docs: Android University - Camera class Change-Id: Idc0c6ca88b42908289701c8367cd5c403d85f71e --- .../training/PhotoIntentActivity.zip | Bin 0 -> 15261 bytes docs/html/training/camera/cameradirect.jd | 308 ++++++++++++++++++ docs/html/training/camera/index.jd | 60 ++++ docs/html/training/camera/photobasics.jd | 258 +++++++++++++++ docs/html/training/camera/videobasics.jd | 118 +++++++ 5 files changed, 744 insertions(+) create mode 100644 docs/html/shareables/training/PhotoIntentActivity.zip create mode 100644 docs/html/training/camera/cameradirect.jd create mode 100644 docs/html/training/camera/index.jd create mode 100644 docs/html/training/camera/photobasics.jd create mode 100644 docs/html/training/camera/videobasics.jd diff --git a/docs/html/shareables/training/PhotoIntentActivity.zip b/docs/html/shareables/training/PhotoIntentActivity.zip new file mode 100644 index 0000000000000000000000000000000000000000..9fcc0e19a7c8aa55f94544454c55982b086360d6 GIT binary patch literal 15261 zcmb7r1ymi~vL^2C?(PuW-3bJDcXxMpcMt9k!6CT2ySoH;7;~p$% z^{Ktey1Krul9K`kK>>jH+$3Cy_yGPG$e;TH)`s>rW`;6))@H^=4vuuLR+do;qt-nP z2<fGnWw0#>FCa{HI33zIFhpp;8OaDNbLxV1 zfC-$&5R^V|Q*f9lCYaidCf27 z+78mz1CZVwL6IKyDfkWoC+( zx_L)Z5pyxf7W@q+cQaynM(2r7$_LT)W`6M6YMbY!P`405zK9#dp>&|P=SHDm3*Zz* z&5lntr3XtvV?lJ;){5I+siFEoF)TRvvV}wIDgRQ0rk)9B?FFWY{(VPu%m~+6Yr(QIELh9X zpbO68ec};aP6`|X&qW*E4G;jp3K#%D?!PoQ*#h^M=CD3BXK&;{Z)mUQqNi_ZL~Ckj zYesKoU}H^ZYi$Df1!3$mOzx`~EEE>h=asM$;==Nuzv90q1lZ@d(s{ku=MRX3poAjC z=kSCu4E;QYv=vu#004mc^?L#eRxqc2p2Tq!QFTwc>=?|HMwT^0U?ML5@AFKcaGz(IWe>R_}Rv`8x6WX%SPkaKl#+%07k~ zb7_~A1O7dmXV*~#aoQ@vD-u>NpI>euo2USa+^tRu-gy<4cg!Hm@@{2ttSt6^0K5wp!er_p)iP^mNJ%zZ8T%fa}aC$c*|p_-TXFi8=&i zL_jh_@dXt=3Zg770YF~oHS(m$NP$vNQMeAuHYO+ znE6DX1vVToqE&fR23JdBqr9^afq|Q$6H-;UfP)bE{;0q-I5+)V;&4Dzu)5Kg@lqzZ z0A+80iZB*TG|cjw_#FOMwE%N4&geM#tvO4403g5G^eGg(z!++SrDJd~5Fjg|NTp_` z4dGdk1*$|y+bj&AkQIVLX-u(4@oiQmI#Ed?j}t~WlC>4?; ztG3K0S9(d6ZX_om=mph^+JtP%5Q7S{4}&Vs7rX)|Mp1mJQHgA5rLc))CrytF_%JTa zNVsWEk_*G;`!)R8wANUDRE|z-a%AkN=34U%O{`{$PuXw;!EIp#F<_k(BB7`zwS-$t zz942KuZJmvRnl-OCI$dW1_kPYqEbcr6Ht7EyDoU!ubA+}i4+b3Ov(+F2NV^;P=@FQ zC`3uh4V(w6L@6YQPzsg<1<`}FAQ@d{jdSGsrZ;ru#8pZGlHk>B#$h_}tpagh727S7 zB>?~1Wu5W#JkD6BphjKFeV=)7#Ol*lord^RgxZWdA!^p)m6p$->JveR@|u9nix{L+ znC26KADx}ugHCKTy^-B0D0kN-UieQ$*6Jq@^;bG?pRJenjSplHBn#M)z}o`0U(-rD z`4~8ab4HO$asJF0JeD%``BvVE!NF9y^3)g*BZ4`>ZYAwH@B!6OL zRi3J@KABizKXRBD(HV#wJT zyOfjwRl~m~##DA@-0v;-t-&0+yi+p%h=Q+f4vwoeE zalxMj8L13vbOxW~;)m^a{AAqis@g^qq*z~#vV*H7H2uRHcE2QCMX&#oea)}ejmztW zt$YZ=pOQ5Gerp-rwJ&u3HPR~2KpRIssp$6`5eWX#d!Qg?;v%TOjHuK4B%9!0?<*L8=t&Mmj-S-T{nkG~A&UA9Sx-kf({sa|AU4YM9v@721;oHryFiOI3|x4bKl+ z?^|bH5bWgcb8X34P(`<@-53&r8=z1YopzUW0SgU≦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 z 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 Hee}Nohrf6d literal 0 HcmV?d00001 diff --git a/docs/html/training/camera/cameradirect.jd b/docs/html/training/camera/cameradirect.jd new file mode 100644 index 0000000000000..d37f2c49e0f5b --- /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 + + + + +

In this lesson, we discuss how to control the camera hardware directly using +the framework APIs.

+ +

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.

+ + +

Open the Camera Object

+ +

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.

+ +
+private void openCameraPerIdAndSetPreview() {
+    if (! safeCameraOpen(mCameraId)) {
+        mCameraId = getFirstRearCameraID();
+        safeCameraOpen(mCameraId);
+    }
+
+    mPreview.setCamera(mCamera);
+}
+
+ +

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).

+ +

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.

+ +
+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;
+    }
+}
+
+ + +

Create the Camera Preview

+ +

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.

+ +

Preview Class

+ +

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.

+ +
+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);
+    }
+...
+}
+
+ +

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.

+ + +

Set and Start the Preview

+ +

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.

+ +
+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();
+    }
+}
+
+ + +

Modify Camera Settings

+ +

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:

+ +
+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();
+}
+
+ + +

Set the Preview Orientation

+ +

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.

+ + +

Take a Picture

+ +

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.

+ +

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()}.

+ + +

Restart the Preview

+ +

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.

+ +
+@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();
+}
+
+ + +

Stop the Preview and Release the Camera

+ +

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.

+ +

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.

+ +
+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;
+    }
+}
+
+ +

In the example application, this procedure is also part of the {@code +setCamera()} method, so initializing a camera always begins with stopping the +preview.

+ diff --git a/docs/html/training/camera/index.jd b/docs/html/training/camera/index.jd new file mode 100644 index 0000000000000..400f6368ad97b --- /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 + +
+
+ + +

Dependencies and prerequisites

+
    +
  • Android 1.5 (API level 3) or higher
  • +
  • A device with a camera
  • +
+ + +

You should also read

+ + + +

Try it out

+ +
+ Download the Intent sample +

PhotoIntentActivity.zip

+
+ +
+
+ +

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.

+ +

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.

+ + +

Lessons

+ +
+
Taking Photos Simply
+
Leverage other applications and capture photos with just a few lines of code.
+
Recording Videos Simply
+
Leverage other applications and record videos with just a few lines of code.
+
Controlling the Camera
+
Control the camera hardware directly and implement your own camera application.
+
+ diff --git a/docs/html/training/camera/photobasics.jd b/docs/html/training/camera/photobasics.jd new file mode 100644 index 0000000000000..002dec7287219 --- /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 + + +
+
+ +

This lesson teaches you to

+
    +
  1. Request Camera Permission
  2. +
  3. Take a Photo with the Camera App
  4. +
  5. View the Photo
  6. +
  7. Save the Photo
  8. +
  9. Add the Photo to a Gallery
  10. +
  11. Decode a Scaled Image
  12. +
+ +

You should also read

+ + +

Try it out

+
+ Download the +sample +

PhotoIntentActivity.zip

+
+ +
+
+ +

This lesson explains how to capture photos using an existing camera +application.

+ +

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.

+ + +

Request Camera Permission

+ +

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 {@code +<uses-feature>} tag in your manifest file:

+ +
+<manifest ... >
+    <uses-feature android:name="android.hardware.camera" />
+    ...
+</manifest ... >
+
+ +

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.

+ + +

Take a Photo with the Camera App

+ +

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.

+ +

Here's a function that invokes an intent to capture a photo.

+ +
+private void dispatchTakePictureIntent(int actionCode) {
+    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+    startActivityForResult(takePictureIntent, actionCode);
+}
+
+ + +

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:

+ +
+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;
+}
+
+ + +

View the Photo

+ +

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.

+ +

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}.

+ +
+private void handleSmallCameraPhoto(Intent intent) {
+    Bundle extras = intent.getExtras();
+    mImageBitmap = (Bitmap) extras.get("data");
+    mImageView.setImageBitmap(mImageBitmap);
+}
+
+ +

Note: 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.

+ + +

Save the Photo

+ +

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.

+ +

There is an easy way to get the path for photos, but it works only on Android 2.2 (API level 8) +and later:

+ +
 
+storageDir = new File(
+    Environment.getExternalStoragePublicDirectory(
+        Environment.DIRECTORY_PICTURES
+    ), 
+    getAlbumName()
+);		
+
+ +

For earlier API levels, you have to provide the name of the photo +directory yourself.

+ +
 
+storageDir = new File (
+    Environment.getExternalStorageDirectory()
+        + PICTURES_DIR
+        + getAlbumName()
+);
+
+ +

Note: The path component {@code PICTURES_DIR} is +just {@code Pictures/}, the standard location for shared photos on the external/shared +storage.

+ + +

Set the file name

+ +

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:

+ +
 
+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;
+}
+
+ + +

Append the file name onto the Intent

+ +

Once you have a place to save your image, pass that location to the camera +application via the {@link android.content.Intent}.

+ +
+File f = createImageFile();
+takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
+
+ + +

Add the Photo to a Gallery

+ +

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.

+ +

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.

+ +
+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);
+}
+
+ + +

Decode a Scaled Image

+ +

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.

+ +
+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);
+}
+
+ diff --git a/docs/html/training/camera/videobasics.jd b/docs/html/training/camera/videobasics.jd new file mode 100644 index 0000000000000..a0f57325dbbb5 --- /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 + + +
+
+ +

This lesson teaches you to

+
    +
  1. Request Camera Permission
  2. +
  3. Record a Video with a Camera App +
  4. View the Video
  5. +
+ +

You should also read

+ + +

Try it out

+ +
+ Download the +sample +

PhotoIntentActivity.zip

+
+
+
+ + +

This lesson explains how to capture video using existing camera +applications.

+ +

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.

+ + + +

Request Camera Permission

+ +

To advertise that your application depends on having a camera, put a +{@code <uses-feature>} tag in the manifest file:

+ +
+<manifest ... >
+    <uses-feature android:name="android.hardware.camera" />
+    ...
+</manifest ... >
+
+ +

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.

+ + +

Record a Video with a Camera App

+ +

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.

+ +

Here's a function that invokes an intent to capture video.

+ +
+private void dispatchTakeVideoIntent() {
+    Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+    startActivityForResult(takeVideoIntent, ACTION_TAKE_VIDEO);
+}
+
+ + +

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:

+ +
+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;
+}
+
+ + +

View the Video

+ +

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}.

+ +
+private void handleCameraVideo(Intent intent) {
+    mVideoUri = intent.getData();
+    mVideoView.setVideoURI(mVideoUri);
+}
+
+