Permissions

Appportunity

Build your own Android App Dev Empire

Get Instant Access

Using the MediaRecorder for both audio and video capture and saving to a file on the SD card requires the following permissions be set in the AndroidManifest.xml file.

<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission> <uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">^ </uses-permission>

Full Custom Video Capture Example

Here is a full example putting all of the foregoing steps together. It is using CamcorderProfile, so it requires Android 2.2 or higher.

package com.apress.proandroidmedia.ch11.videocapture;

import java.io.IOException;

import android.app.Activity;

import android.content.pm.ActivityInfo;

import android.media.CamcorderProfile;

import android.media.MediaRecorder;

import android.os.Bundle;

import android.util.Log;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

import android.view.View;

import android.view.Window;

import android.view.WindowManager;

import android.view.View.OnClickListener;

In this example, our activity will implement OnClickListener, so that the user can click to start and stop recording, and SurfaceHolder.Callback to handle Surface-related events.

public class VideoCapture extends Activity implements OnClickListener,^ SurfaceHolder.Callback {

MediaRecorder recorder; SurfaceHolder holder;

Here we have a Boolean that represents whether we are currently recording. It will be false when we are not recording and true when we are.

boolean recording = false;

public static final String TAG = "VIDEOCAPTURE"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

This activity will run full-screen and in landscape, so we'll set that up with the following methods.

requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,^

WindowManager.LayoutParams.FLAG_FULLSCREEN);

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Next, we'll instantiate our MediaRecorder object.

recorder = new MediaRecorder();

The initRecorder method, defined further on, will handle all of the MediaRecorder settings.

initRecorder();

setContentView(R.layout.main);

Continuing on, we'll get a reference to the SurfaceView and the SurfaceHolder as well as register our activity as the SurfaceHolder.Callback.

Continuing on, we'll get a reference to the SurfaceView and the SurfaceHolder as well as register our activity as the SurfaceHolder.Callback.

SurfaceView cameraView = (SurfaceView)^ findViewByld(R.id.CameraView);

holder = cameraView.getHolder(); holder.addCallback(this);

holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

We'll make our SurfaceView clickable and register our activity as the OnClickListener for it. This way our onClick method will be called when the SurfaceView is touched.

cameraView.setClickable(true); cameraView.setOnClickListener(this);

The initRecorder method, defined here, takes care of all of the MediaRecorder settings.

private void initRecorder() {

We'll use the default audio and video sources.

recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

Rather than go through all of the individual settings, we'll use one of the built-in CamcorderProfile's—in this case, the one specified by the OUALITY_HIGH constant.

CamcorderProfile cpHigh CamcorderProfile.get(CamcorderProfile.OUALITY_HIGH); recorder.setProfile(cpHigh);

We'll specify the path to a file to record to. In this case, it is a file directly on the SD card.

recorder.setOutputFile("/sdcard/videocapture_example.mp4"); Then we'll specify a maximum duration in milliseconds.

recorder.setMaxDuration(50000); // 50 seconds Finally we'll specify a maximum file size in bytes.

recorder.setMaxFileSize(5000000); // Approximately 5 megabytes

The following prepareRecorder method exists to separate the setPreviewDisplay method from the rest of the MediaRecorder methods. We need to do this as this step needs to be performed after the Surface has been created, whereas the other steps can be performed at any time after the MediaRecorder is instantiated or after it has been stopped.

private void prepareRecorder() {

recorder.setPreviewDisplay(holder.getSurface());

After the preview display has been set, we can call the prepare method on the MediaRecorder object. This step gets everything ready for capture. We have to wrap it in a try/catch block as it throws some exceptions. If we get any, we'll just finish. In your applications, you will probably want to handle them more gracefully.

recorder.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); finish(); } catch (IOException e) {

e.printStackTrace(); finish();

When the SurfaceView is clicked, our activity's onClick method will be called. public void onClick(View v) {

If the recording Boolean is true, we'll call the stop method on the recorder and set the recording Boolean to false. Additionally, if we are done with the MediaRecorder, we should call the release method to free up its resources, as only one application can use it at a time.

recorder.stop(); //recorder.release(); recording = false; Log.v(TAG,"Recording Stopped");

In this example, we are going to allow the user to record again, so we'll call initRecorder and prepareRecorder to set everything back up. We need to do this because after recording is stopped with the stop method, its state is as if it were just initialized, and it therefore isn't ready to record again.

// Let's initRecorder so we can record again initRecorder(); prepareRecorder(); } else {

If the recording Boolean is false, we'll call the start method on the MediaRecorder and update the Boolean.

recording = true; recorder.start(); Log.v(TAG,"Recording Started");

As explained previously, we'll call prepareRecorder once the Surface is created.

public void surfaceCreated(SurfaceHolder holder) { Log.v(TAG,"surfaceCreated"); prepareRecorder();

public void surfaceChanged(SurfaceHolder holder, int format, int width,~

We'll stop the recording if we are recording when the Surface is destroyed. This will likely happen when the activity is no longer visible. Since the MediaRecorder uses shared resources, such as the camera and microphone, we'll call the release method so that other applications may use them. In addition, there is no reason to keep this application running; we'll call finish so that next time it is started, everything is initialized again.

public void surfaceDestroyed(SurfaceHolder holder) { Log.v(TAG,"surfaceDestroyed"); if (recording) {

recorder.stop(); recording = false;

recorder.release(); finish();

Here is the layout XML that we are using. <?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<SurfaceView android:id="@+id/CameraView" android:layout_width="640px"^ android:layout_height="480px"></SurfaceView> </LinearLayout>

Here are the contents of AndroidManifest.xml for this example. Of note are the three uses-permission tags that are required.

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.apress.proandroidmedia.ch11.videocapture" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".VideoCapture"

android:label="@string/app_name"> <intent-filter>

<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>

<uses-sdk android:minSdkVersion="8" />

<uses-permission android:name="android.permission.RECORD_AUDIO"> </uses-permission>

<uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"> </uses-permission>

</manifest>

As we see, writing an application to perform custom video capture isn't terribly difficult, but it can be a bit painful if we don't pay attention to the Surface creation and the order of the steps. Creating our own application gives us a lot of flexibility in changing the settings, such as the codec, bitrate, and format used to record. Figure 11-2 shows the foregoing example as it looks on a device.

Figure 11-2. Custom Video Capture activity

Was this article helpful?

0 0

Post a comment