11.3.2 定制视频捕获的完整示例

     下面是将上述所有的步骤汇总在一起的完整示例。它使用了CamcorderProfile,因此需要Android 2.2或更高的版本。

 1 package com.nthm.androidtestActivity;
 2 
 3 import java.io.IOException;
 4 import com.nthm.androidtest.R;
 5 import android.app.Activity;
 6 import android.content.pm.ActivityInfo;
 7 import android.media.CamcorderProfile;
 8 import android.media.MediaRecorder;
 9 import android.os.Bundle;
10 import android.os.Environment;
11 import android.view.SurfaceHolder;
12 import android.view.SurfaceView;
13 import android.view.View;
14 import android.view.View.OnClickListener;
15 import android.view.Window;
16 import android.view.WindowManager;

    在此示例中,活动将实现OnClickListener,使得用户可以单击以启动和停止录制;同时活动还将实现SurfaceHolder.Callback以处理与表面相关的事件。

1 public class VideoCapture extends Activity implements OnClickListener,SurfaceHolder.Callback{
2     private MediaRecorder recorder;
3     private SurfaceHolder holder;

    我们使用一个布尔值来表示当前是否正在录制。当不在录制时它的值是false;而在录制时它的值是true。

1     private boolean recording=false;
2     @Override
3     protected void onCreate(Bundle savedInstanceState) {
4         super.onCreate(savedInstanceState);

    此活动将以全屏和横向模式运行,所以将使用下列方法对它进行设置。

1         requestWindowFeature(Window.FEATURE_NO_TITLE);
2         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
3         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    接下来将实例化MediaRecorder对象。

1         recorder=new MediaRecorder();

    initRecorder方法(在后面定义)将处理所有的MediaRecorder设置。

1         initRecorder();
2         setContentView(R.layout.videocapture);

    接着,将获得指向SurfaceView和SurfaceHolder的引用,同时将活动注册为SurfaceHolder.Callback。

1         SurfaceView cameraView=(SurfaceView) findViewById(R.id.CameraView);
2         holder=cameraView.getHolder();
3         holder.addCallback(this);
4         holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    设置SurfaceView为可单击,并将活动注册为它的OnClickListener。这样当触摸SurfaceView时,将调用活动的onClick方法。

1         cameraView.setClickable(true);
2         cameraView.setOnClickListener(this);
3     }

    下面定义的initRecorder方法将处理所有的MediaRecorder设置。

1     private void initRecorder(){

    我们将使用默认的音频和视频源。

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

    与指定所有单个的设置不同,我们将使用一个内置的CamcorderProfile设置——在当前情况下,其由QUALITY_HIGH常量指定。

1         CamcorderProfile cpHigh=CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
2         recorder.setProfile(cpHigh);

    需要指定录制到其中的文件路径。在当前的情况下,它是直接位于SD卡上的一个文件中。

1         recorder.setOutputFile(Environment.getExternalStorageDirectory()+"/test.mp4");

    然后将以毫秒为单位指定最长持续时间。

1         recorder.setMaxDuration(50000);

    最后将以字节为单位指定最大文件大小。

1         recorder.setMaxFileSize(5000000);
2     }

    下面的prepareRecorder方法将setPreviewDisplay方法与其余的MediaRecorder方法分离开来。之所以这么做,是因为需要在创建表面之后执行这个步骤,而其他步骤可以在实例化MediaRecorder之后或者在它已停止之后的任何时候执行。

1     private void prepareRecorder(){
2         recorder.setPreviewDisplay(holder.getSurface());

    在设置预览显示之后,可以调用MediaRecorder对象上的preapre方法。这个步骤为捕获操作做好准备。必须将该步骤包装在一个try/catch块中,因为它会抛出一些异常。如果得到任何异常,那么本活动将仅仅是结束。在你的应用程序中,你可能希望更合理的处理他们。

 1         try {
 2             recorder.prepare();
 3         } catch (IllegalStateException e) {
 4             e.printStackTrace();
 5             finish();
 6         } catch (IOException e) {
 7             e.printStackTrace();
 8             finish();
 9         }
10     }

    当单击SurfaceView时,将调用活动的onClick方法。

1     @Override
2     public void onClick(View v) {

    如果recording布尔值为true,那么将调用recording对象上的stop方法,并设置recording布尔值为false。另外,如果完成了MediaRecorder的使用,那么应该调用release方法以释放它的资源,因为每次只有一个应用程序可以使用这些资源。

1            if(recording){
2                recorder.stop();
3                //recorder.release();
4                recording=false;

    此示例需要允许用户再次录制,因此将调用initRecorder和prepareRecorder方法重置所有的内容。之所以这么做,是因为在使用stop方法停止录制之后,其状态就和刚刚初始化一样,因此不会再次准备好录制。

1                //调用initRecorder,从而可以重新录制
2                initRecorder();
3                prepareRecorder();
4            }else{

    如果recording布尔值为false,那么将调用MediaRecorder上的start方法,并更新该布尔值。

1                recording=true;
2                recorder.start();
3            }
4     }

    正如之前所述,一旦创建表面,就调用prepareRecorder方法。

 1     @Override
 2     public void surfaceCreated(SurfaceHolder holder) {
 3         prepareRecorder();
 4     }
 5 
 6     @Override
 7     public void surfaceChanged(SurfaceHolder holder, int format, int width,
 8             int height) {
 9         
10     }

    当销毁表面时,如果正在录制,那么停止录制。这可能会在活动不再可见时发生。由于MediaRecorder使用共享资源,如摄像头和麦克风,因此会调用release方法,以便其他应用程序可以使用他们。此外,没有理由需要保持这个应用程序继续运行;可以调用finish方法,从而当该应用程序下次启动时重新初始化所有内容。

 1     @Override
 2     public void surfaceDestroyed(SurfaceHolder holder) {
 3         if(recording){
 4             recorder.stop();
 5             recording=false;
 6         }
 7         recorder.release();
 8         finish();
 9     }
10 }

    下面用于上述活动的布局XML。

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical"
 5     >
 6  <SurfaceView 
 7      android:id="@+id/CameraView"
 8      android:layout_width="640px"
 9      android:layout_height="480px"/>
10 </LinearLayout>

     下面是本示例中需要的权限:

1     <uses-permission android:name="android.permission.CAMERA"/>
2     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
3     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    编写一个应用程序以执行定制视频捕获并不是十分的困难,但是如果没有注意表面的创建和步骤的顺序,那么它可能会面临一些困难。创建自己的应用程序将在更改设置方面获得很大的灵活性,例如编解码器、比特率和用于录制的格式等。

 

 

   

posted on 2014-09-09 11:46  宁静致远,一览众山小  阅读(234)  评论(0编辑  收藏  举报

导航