Advertisement

使用MediaRecorder录制视频,并进行播放

阅读量:

自Android SDK 1.6 开始,录制视频需要将照相机所看到的内容预览到Surface对象上。采用真机测试。

布局文件:

复制代码
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    
     xmlns:tools="http://schemas.android.com/tools"
    
     android:layout_width="match_parent"
    
     android:layout_height="match_parent" 
    
     android:orientation="horizontal">
    
  
    
     <LinearLayout 
    
     android:layout_width="wrap_content"
    
     android:layout_height="wrap_content"
    
     android:orientation="vertical"
    
     >
    
     <Button 
    
         android:id="@+id/initBtn"
    
         android:layout_width="wrap_content"
    
         android:layout_height="wrap_content"
    
         android:text="Initialize Recorder"
    
         android:onClick="doClick"
    
         android:enabled="false"
    
         />
    
     <Button 
    
         android:id="@+id/beginBtn"
    
         android:layout_width="wrap_content"
    
         android:layout_height="wrap_content"
    
         android:text="Begin Recording"
    
         android:onClick="doClick"
    
         android:enabled="false"
    
         />
    
     <Button 
    
         android:id="@+id/stopBtn"
    
         android:layout_width="wrap_content"
    
         android:layout_height="wrap_content"
    
         android:text="Stop Recording"
    
         android:onClick="doClick"
    
         />
    
     <Button 
    
         android:id="@+id/playRecordingBtn"
    
         android:layout_width="wrap_content"
    
         android:layout_height="wrap_content"
    
         android:text="Play Recording"
    
         android:onClick="doClick"
    
         />
    
     <Button 
    
         android:id="@+id/stopPlayingRecordingBtn"
    
         android:layout_width="wrap_content"
    
         android:layout_height="wrap_content"
    
         android:text="Stop Playing"
    
         android:onClick="doClick"
    
         />
    
     </LinearLayout>
    
  
    
     <LinearLayout 
    
     android:orientation="vertical"
    
     android:layout_width="match_parent"
    
     android:layout_height="match_parent"
    
     >
    
     <TextView 
    
         android:id="@+id/recording"
    
         android:text=" "
    
         android:textColor="#0000ff"
    
         android:layout_width="wrap_content"
    
         android:layout_height="wrap_content"
    
         />
    
     <VideoView 
    
         android:id="@+id/videoView"
    
         android:layout_width="250dp"
    
         android:layout_height="200dp"
    
         />
    
     </LinearLayout>
    
 </LinearLayout>

布局为一个LinearLayout中包含两个并排的LinearLayout.左侧是应用程序将在演示过程中启用和禁用的5个按钮。右侧是主要的VideoView,在它之上是Recording消息。在清单文件中设置android:screenOrientation="landscape"特性,强制此应用处于横向模式。

复制代码
 package com.example.recordvideo;

    
  
    
 import java.io.File;
    
 import java.io.IOException;
    
  
    
 import android.app.Activity;
    
 import android.hardware.Camera;
    
 import android.media.MediaRecorder;
    
 import android.media.MediaRecorder.OnErrorListener;
    
 import android.media.MediaRecorder.OnInfoListener;
    
 import android.os.Bundle;
    
 import android.os.Environment;
    
 import android.util.Log;
    
 import android.view.SurfaceHolder;
    
 import android.view.View;
    
 import android.widget.Button;
    
 import android.widget.MediaController;
    
 import android.widget.TextView;
    
 import android.widget.Toast;
    
 import android.widget.VideoView;
    
  
    
 public class MainActivity extends Activity implements SurfaceHolder.Callback, OnInfoListener, OnErrorListener{
    
  
    
 	private static final String TAG = "RecordVideo";
    
 	
    
 	private MediaRecorder mRecorder = null;
    
 	private SurfaceHolder mHoler = null;
    
 	
    
 	private String mOutputFileName;
    
 	
    
 	private VideoView mVideoView;
    
 	private Button mInitBtn = null;
    
 	private Button mStartBtn = null;
    
 	private Button mStopBtn = null;
    
 	private Button mPlayBtn = null;
    
 	private Button mStopPlayBtn = null;
    
 	private Camera mCamera = null;
    
 	
    
 	private TextView mRecordingMsg = null;
    
 	@Override
    
 	protected void onCreate(Bundle savedInstanceState) {
    
 		super.onCreate(savedInstanceState);
    
 		setContentView(R.layout.activity_main);
    
 		
    
 		InitViews();
    
 	}
    
 	
    
 	private void InitViews() {
    
 		mInitBtn = (Button) findViewById(R.id.initBtn);
    
 		mStartBtn = (Button) findViewById(R.id.beginBtn);
    
 		mStopBtn = (Button) findViewById(R.id.stopBtn);
    
 		mPlayBtn = (Button) findViewById(R.id.playRecordingBtn);
    
 		mStopPlayBtn = (Button) findViewById(R.id.stopPlayingRecordingBtn);
    
 		
    
 		mRecordingMsg = (TextView) findViewById(R.id.recording);
    
 		
    
 		mVideoView = (VideoView) findViewById(R.id.videoView);
    
 	}
    
  
    
 	@Override
    
 	protected void onResume() {
    
 		Log.v("TAG", "in onResume");
    
 		super.onResume();
    
 		//设置不可点击
    
 		mInitBtn.setEnabled(false);
    
 		mStartBtn.setEnabled(false);
    
 		mStopBtn.setEnabled(false);
    
 		mPlayBtn.setEnabled(false);
    
 		mStopPlayBtn.setEnabled(false);
    
 		
    
 		if(!initCamera())
    
 		{
    
 			finish();
    
 		}
    
 	}
    
 	
    
 	@Override
    
 	protected void onPause() {
    
 		Log.v("TAG", "in onPause");
    
 		super.onPause();
    
 		releaseRecorder();
    
 		releaseCamera();
    
 	}
    
 	
    
 	private void releaseCamera() {
    
 		if(mCamera != null)
    
 		{
    
 			try {
    
 				mCamera.reconnect();
    
 			} catch (IOException e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 			mCamera.release();
    
 			mCamera = null;
    
 		}
    
 	}
    
  
    
 	private void releaseRecorder() {
    
 		if(mRecorder != null)
    
 		{
    
 			mRecorder.release();
    
 			mRecorder = null;
    
 		}
    
 	}
    
  
    
 	private boolean initCamera() {
    
 		Toast.makeText(MainActivity.this, "初始化中...", Toast.LENGTH_SHORT).show();
    
 		try {
    
 			mCamera = Camera.open();
    
 			Camera.Parameters camParams = mCamera.getParameters();
    
 			mCamera.lock();
    
 			
    
 			mHoler = mVideoView.getHolder();
    
 			mHoler.addCallback(this);
    
 			mHoler.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    
 		} catch (Exception e) {
    
 			Log.v("TAG", "Could not initialize the Camera");
    
 			e.printStackTrace();
    
 			return false;
    
 		}
    
 		return true;
    
 	}
    
  
    
 	public void doClick(View v)
    
 	{
    
 		switch (v.getId()) {
    
 		case R.id.initBtn:
    
 			Toast.makeText(MainActivity.this, "点击初始化按钮了..", Toast.LENGTH_SHORT).show();
    
 			initRecorder();
    
 			break;
    
 		case R.id.beginBtn:
    
 			Toast.makeText(MainActivity.this, "开始录制...", Toast.LENGTH_SHORT).show();
    
 			beaginRecording();
    
 			break;
    
 		case R.id.stopBtn:
    
 			Toast.makeText(MainActivity.this, "停止录制...", Toast.LENGTH_SHORT).show();
    
 			stopRecording();
    
 			break;
    
 		case R.id.playRecordingBtn:
    
 			Toast.makeText(MainActivity.this, "开始播放录制视频..", Toast.LENGTH_SHORT).show();
    
 			playRecording();
    
 			break;
    
 		case R.id.stopPlayingRecordingBtn:
    
 			Toast.makeText(MainActivity.this, "停止播放录制视频..", Toast.LENGTH_SHORT).show();
    
 			stopPlayingRecording();
    
 			break;
    
 		}
    
 	}
    
  
    
 	private void stopPlayingRecording() {
    
 		mVideoView.stopPlayback();
    
 	}
    
  
    
 	private void playRecording() {
    
 		MediaController mc = new MediaController(this);
    
 		mVideoView.setMediaController(mc);
    
 		mVideoView.setVideoPath(mOutputFileName);
    
 		mVideoView.start();
    
 		mStopPlayBtn.setEnabled(true);
    
 	}
    
  
    
 	private void stopRecording() {
    
 		if(mRecorder != null)
    
 		{
    
 			mRecorder.setOnErrorListener(null);
    
 			mRecorder.setOnInfoListener(null);
    
 			try {
    
 				mRecorder.stop();
    
 			} catch (IllegalStateException e) {
    
 				Log.v("", "在停止录制发生错误...");
    
 				e.printStackTrace();
    
 			}
    
 			releaseRecorder();
    
 			mRecordingMsg.setText("");
    
 			releaseCamera();
    
 			mStartBtn.setEnabled(false);
    
 			mStopBtn.setEnabled(false);
    
 			mPlayBtn.setEnabled(true);
    
 		}
    
 	}
    
  
    
 	private void beaginRecording() {
    
 		mRecorder.setOnInfoListener(this);
    
 		mRecorder.setOnErrorListener(this);//以上两个接口是用来被告知是否有任何来自MediaRecorder的消息
    
 		mRecorder.start();//开始录制
    
 		mRecordingMsg.setText("正在录制中...");
    
 		mStartBtn.setEnabled(false);
    
 		mStopBtn.setEnabled(true);
    
 	}
    
  
    
 	private void initRecorder() {
    
 		if(mRecorder != null)return;
    
 		
    
 		mOutputFileName = Environment.getExternalStorageDirectory()+"/test.mp4";
    
 		File outFile = new File(mOutputFileName);
    
 		if(outFile.exists())
    
 		{
    
 			outFile.delete();
    
 		}
    
 		
    
 		try {
    
 			mCamera.stopPreview();
    
 			mCamera.unlock();
    
 			
    
 			mRecorder = new MediaRecorder();
    
 			mRecorder.setCamera(mCamera);
    
 			
    
 			mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    
 			mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    
 			mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    
 			mRecorder.setVideoSize(176, 144);
    
 			mRecorder.setVideoFrameRate(15);
    
 			mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
    
 			mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    
 			mRecorder.setMaxDuration(7000);
    
 			mRecorder.setPreviewDisplay(mHoler.getSurface());
    
 			mRecorder.setOutputFile(mOutputFileName);
    
 			
    
 			System.out.println("1");
    
 			
    
 			mRecorder.prepare();
    
 			System.out.println("2");
    
 			
    
 			Log.v("TAG", "MediaRecorder initialized");
    
 			mInitBtn.setEnabled(false);
    
 			mStartBtn.setEnabled(true);
    
 			
    
 			System.out.println("2");
    
 		} catch (Exception e) {
    
 			Log.v("TAG", "MediaRecorder failed to initialize");
    
 			e.printStackTrace();
    
 		}
    
 	}
    
  
    
 	@Override
    
 	public void onInfo(MediaRecorder mr, int what, int extra) {
    
 		Log.i("TAG", "得到一个录制事件");
    
 		if(what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED)
    
 		{
    
 			Log.i("TAG", "...max duration reached");
    
 			stopRecording();
    
 			Toast.makeText(MainActivity.this, "录制时限已经到了,即将停止录制...", Toast.LENGTH_SHORT).show();
    
 		}
    
 	}
    
  
    
 	@Override
    
 	public void surfaceCreated(SurfaceHolder holder) {
    
 		Log.v("TAG", "in sufaceCreated");
    
 		try {
    
 			mCamera.setPreviewDisplay(mHoler);
    
 			mCamera.startPreview();
    
 		} catch (IOException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 		mInitBtn.setEnabled(true);
    
 	}
    
  
    
 	@Override
    
 	public void surfaceChanged(SurfaceHolder holder, int format, int width,
    
 			int height) {
    
 		Log.v("TAG", "surfaceChanged:Width x Height = "+width + "x" +height);
    
 	}
    
  
    
 	@Override
    
 	public void surfaceDestroyed(SurfaceHolder holder) {
    
 		Log.v("TAG", "in surfaceDestroyed");
    
 	}
    
  
    
 	@Override
    
 	public void onError(MediaRecorder mr, int what, int extra) {
    
 		Log.e("TAG", "录制发生错误..");
    
 		stopRecording();
    
 		Toast.makeText(MainActivity.this, "录制发生错误...", Toast.LENGTH_SHORT).show();
    
 	}
    
 }

此类实现了三个接口,第一个接口SurfaceHolder.Callback用于接收表明Surface已准备好显示视频图像的标志。正本程序中,Surface来自VideoView.我们还希望 被告知是否有任何来自MediaRecorder的消息,这正是我们同时实现了OnInfoListener和OnErrorListener的原因。

在onResume()中,我们仅将按钮设置为初始化的状态,然后初始化照相机。在onPause()中,我们需要同时释放MediaRecorder和Camera.这样,任何时候应用程序退出视图,都会停止录制并释放照相机,使另一个应用程序可使用它。如果用户返回到应用程序,应用程序将重新启动,用户将能够再次录制视频。接下来照相机、Surface.Callback回调,以及Camera和MediaRecorder释放方法的初始化方法。

代码链接:<>

全部评论 (0)

还没有任何评论哟~