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

来源:互联网 发布:淘宝好评返现不给 编辑:程序博客网 时间:2024/06/05 16:16

    自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;@Overrideprotected 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);}@Overrideprotected 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();}}@Overrideprotected 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 blocke.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();}}@Overridepublic 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();}}@Overridepublic void surfaceCreated(SurfaceHolder holder) {Log.v("TAG", "in sufaceCreated");try {mCamera.setPreviewDisplay(mHoler);mCamera.startPreview();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}mInitBtn.setEnabled(true);}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {Log.v("TAG", "surfaceChanged:Width x Height = "+width + "x" +height);}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.v("TAG", "in surfaceDestroyed");}@Overridepublic 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释放方法的初始化方法。


代码链接:http://download.csdn.net/detail/tan313/8831513

0 0