下面是将上述所有的步骤汇总在一起的完整示例。它使用了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"/>
编写一个应用程序以执行定制视频捕获并不是十分的困难,但是如果没有注意表面的创建和步骤的顺序,那么它可能会面临一些困难。创建自己的应用程序将在更改设置方面获得很大的灵活性,例如编解码器、比特率和用于录制的格式等。