使用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)
还没有任何评论哟~
