前言
Android除了支持播放多媒体文件之外,还可以从对应的硬件中捕获多媒体,比如从麦克风录音、从摄像头录像等。本篇博客讲解一下Android下如何通过MediaRecorder进行录音以及录像的步骤,最后将以简单的Demo演示。
本篇的主要内容:
- MediaRecorder
- MediaRecorder录制音频
- MediaRecorder录制视频
- MediaRecorder的内部类
MediaRecorder
MediaRecorder主要用于记录音频与视频,它位于"android.media.MediaRecorder"下。它为开发人员提供了详尽的AIP以完成记录音频与视频的工作,下面简单介绍一些常用的。
• void prepar():准备录制。
• void start():开始录制。
• void stop():停止录制。
• void reset():重置MediaRecorder。
• void release():释放MediaRecorder占用的资源。
• void setAudioEncoder(int):设置音频记录的编码格式。
• void setAudoSource(int):设置音频记录的音频源。
• void setOutoutFormat(int):设置记录的媒体文件的输出转换格式。
• void setPreviewDisplay(Surface):设置视频的预览界面。
• void setVideoEncoder(int):设置视频记录的编码格式。
• void setVideoSource(int):设置视频记录的视频源。
• void setOutputFile(String):媒体文件输出路径。
• void setMaxDuration(int):设置最大记录时长,单位为毫秒。
上面仅仅列出了一些常用的方法,但是通过这个方法可以看出MediaRecorder是需要在多个状态之间切换的,准备、开始、停止、重置等等。MediaRecorder也为我们提供了一套状态切换的规则,只有在既定的状态下,才能完成对应的操作,下图是官方文档提供的状态图。
上图非常直观的展示了MediaRecorder的状态间的转换,这里只说几点需要注意的地方:
- 当为MediaRecorder设定媒体录入源之后即初始化完成,这个时候才可以为其设定其他的参数。
- 在开始录制前必须先调用prepare()准备录制。
- 只有在Initial初始化状态,才可以对MediaRecorder调用release()释放资源,其他状态必须先stop()或者reset()。
- 错误状态是游离在所有状态之外的,当发生错误的时候,只有进行reset()才会进入Initial初始状态。
MediaRecorder录制视频必不可少的步骤:
- 调用new MediaRecorder()构造函数得到MediaRecorder的实例。
- 调用setOutputFormat()设定媒体文件的输出格式,必须在设定音频与视频的编码格式之前设定。
- 如果需要记录音频,则调用setAudioSource()设定音频的录入源以及调用setAudioEncoder()设定音频的编码方式。
- 如果需要记录视频,则调用setVideoSource()设定视频的录入员以及调用setVideoEncoder()设定视频的编码方式。
- 调用setOutputFile()设定记录的媒体文件保存的路径。
- 先调用prepare()准备录制,准备完成之后调用start()开始录制。
- 记录完成后,调用stop()停止录制。
MediaRecorder录制音频
上面介绍了使用MediaRecorder录制视频必不可少的步骤,因为录制音频无需捕获图像,所以更简单一些。下面直接通过一个简单的示例,演示如何录制音频,录制的音频文件保存在sd根目录下,注释很详细,这里不在累述了。布局很简单,只有两个Button,开始录音、结束录音,就不提供布局代码了。
实现代码:
1 package cn.bgxt.mediarecorderdemo;
2
3 import java.io.File;
4 import android.app.Activity;
5 import android.media.MediaRecorder;
6 import android.media.MediaRecorder.OnErrorListener;
7 import android.os.Bundle;
8 import android.view.View;
9 import android.view.View.OnClickListener;
10 import android.widget.Button;
11 import android.widget.Toast;
12
13 public class RecordActivity extends Activity {
14 private Button btn_RecordStart, btn_RecordStop;
15 private MediaRecorder mediaRecorder;
16 private boolean isRecording;
17 @Override
18 protected void onCreate(Bundle savedInstanceState) {
19 // TODO Auto-generated method stub
20 super.onCreate(savedInstanceState);
21 setContentView(R.layout.activity_record);
22
23 btn_RecordStart = (Button) findViewById(R.id.btn_RecordStart);
24 btn_RecordStop = (Button) findViewById(R.id.btn_RecordStop);
25
26 btn_RecordStop.setEnabled(false);
27
28 btn_RecordStart.setOnClickListener(click);
29 btn_RecordStop.setOnClickListener(click);
30 }
31
32 private View.OnClickListener click = new OnClickListener() {
33
34 @Override
35 public void onClick(View v) {
36 switch (v.getId()) {
37 case R.id.btn_RecordStart:
38 start();
39 break;
40 case R.id.btn_RecordStop:
41 stop();
42 break;
43 default:
44 break;
45 }
46 }
47 };
48
49 /**
50 * 开始录音
51 */
52 protected void start() {
53 try {
54 File file = new File("/sdcard/mediarecorder.amr");
55 if (file.exists()) {
56 // 如果文件存在,删除它,演示代码保证设备上只有一个录音文件
57 file.delete();
58 }
59 mediaRecorder = new MediaRecorder();
60 // 设置音频录入源
61 mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
62 // 设置录制音频的输出格式
63 mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
64 // 设置音频的编码格式
65 mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
66 // 设置录制音频文件输出文件路径
67 mediaRecorder.setOutputFile(file.getAbsolutePath());
68
69 mediaRecorder.setOnErrorListener(new OnErrorListener() {
70
71 @Override
72 public void onError(MediaRecorder mr, int what, int extra) {
73 // 发生错误,停止录制
74 mediaRecorder.stop();
75 mediaRecorder.release();
76 mediaRecorder = null;
77 isRecording=false;
78 btn_RecordStart.setEnabled(true);
79 btn_RecordStop.setEnabled(false);
80 Toast.makeText(RecordActivity.this, "录音发生错误", 0).show();
81 }
82 });
83
84 // 准备、开始
85 mediaRecorder.prepare();
86 mediaRecorder.start();
87
88 isRecording=true;
89 btn_RecordStart.setEnabled(false);
90 btn_RecordStop.setEnabled(true);
91 Toast.makeText(RecordActivity.this, "开始录音", 0).show();
92 } catch (Exception e) {
93 e.printStackTrace();
94 }
95 }
96
97 /**
98 * 录音结束
99 */
100 protected void stop() {
101 if (isRecording) {
102 // 如果正在录音,停止并释放资源
103 mediaRecorder.stop();
104 mediaRecorder.release();
105 mediaRecorder = null;
106 isRecording=false;
107 btn_RecordStart.setEnabled(true);
108 btn_RecordStop.setEnabled(false);
109 Toast.makeText(RecordActivity.this, "录音结束", 0).show();
110 }
111 }
112
113 @Override
114 protected void onDestroy() {
115 if (isRecording) {
116 // 如果正在录音,停止并释放资源
117 mediaRecorder.stop();
118 mediaRecorder.release();
119 mediaRecorder = null;
120 }
121 super.onDestroy();
122 }
123
124 }
录制音频需要访问麦克风设备,访问设备需要添加权限:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
效果展示:
MediaRecorder录制视频
上面已经介绍了使用MediaRecorder录制视频的步骤,这里依照步骤一步一步写代码就可以了。下面通过一个简单的Demo演示如何使用MediaRecorder录制一段从摄像头捕获到的视频,录制的视频文件将保持在SD卡上。布局很简单,两个Button,开始、停止,然后还有一个SurfaceView显示预览效果,就不给出布局代码了。
实现代码:
1 package cn.bgxt.mediarecorderdemo;
2
3 import java.io.File;
4 import java.io.IOException;
5
6 import android.app.Activity;
7 import android.media.MediaRecorder;
8 import android.media.MediaRecorder.OnErrorListener;
9 import android.os.Bundle;
10 import android.view.SurfaceHolder;
11 import android.view.SurfaceView;
12 import android.view.View;
13 import android.view.View.OnClickListener;
14 import android.widget.Button;
15 import android.widget.Toast;
16
17 public class VideoActivity extends Activity {
18 private Button btn_VideoStart, btn_VideoStop;
19 private SurfaceView sv_view;
20 private boolean isRecording;
21 private MediaRecorder mediaRecorder;
22
23 @Override
24 protected void onCreate(Bundle savedInstanceState) {
25 super.onCreate(savedInstanceState);
26 setContentView(R.layout.activity_video);
27
28 btn_VideoStart = (Button) findViewById(R.id.btn_VideoStart);
29 btn_VideoStop = (Button) findViewById(R.id.btn_VideoStop);
30 sv_view = (SurfaceView) findViewById(R.id.sv_view);
31
32 btn_VideoStop.setEnabled(false);
33
34 btn_VideoStart.setOnClickListener(click);
35 btn_VideoStop.setOnClickListener(click);
36
37 // 声明Surface不维护自己的缓冲区,针对Android3.0以下设备支持
38 sv_view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
39 }
40
41 private View.OnClickListener click = new OnClickListener() {
42
43 @Override
44 public void onClick(View v) {
45 switch (v.getId()) {
46 case R.id.btn_VideoStart:
47 start();
48 break;
49 case R.id.btn_VideoStop:
50 stop();
51 break;
52 default:
53 break;
54 }
55 }
56 };
57
58 protected void start() {
59 try {
60 File file = new File("/sdcard/video.mp4");
61 if (file.exists()) {
62 // 如果文件存在,删除它,演示代码保证设备上只有一个录音文件
63 file.delete();
64 }
65
66 mediaRecorder = new MediaRecorder();
67 mediaRecorder.reset();
68 // 设置音频录入源
69 mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
70 // 设置视频图像的录入源
71 mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
72 // 设置录入媒体的输出格式
73 mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
74 // 设置音频的编码格式
75 mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
76 // 设置视频的编码格式
77 mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
78 // 设置视频的采样率,每秒4帧
79 mediaRecorder.setVideoFrameRate(4);
80 // 设置录制视频文件的输出路径
81 mediaRecorder.setOutputFile(file.getAbsolutePath());
82 // 设置捕获视频图像的预览界面
83 mediaRecorder.setPreviewDisplay(sv_view.getHolder().getSurface());
84
85 mediaRecorder.setOnErrorListener(new OnErrorListener() {
86
87 @Override
88 public void onError(MediaRecorder mr, int what, int extra) {
89 // 发生错误,停止录制
90 mediaRecorder.stop();
91 mediaRecorder.release();
92 mediaRecorder = null;
93 isRecording=false;
94 btn_VideoStart.setEnabled(true);
95 btn_VideoStop.setEnabled(false);
96 Toast.makeText(VideoActivity.this, "录制出错", 0).show();
97 }
98 });
99
100 // 准备、开始
101 mediaRecorder.prepare();
102 mediaRecorder.start();
103
104 btn_VideoStart.setEnabled(false);
105 btn_VideoStop.setEnabled(true);
106 isRecording = true;
107 Toast.makeText(VideoActivity.this, "开始录像", 0).show();
108 } catch (Exception e) {
109 e.printStackTrace();
110 }
111
112 }
113
114 protected void stop() {
115 if (isRecording) {
116 // 如果正在录制,停止并释放资源
117 mediaRecorder.stop();
118 mediaRecorder.release();
119 mediaRecorder = null;
120 isRecording=false;
121 btn_VideoStart.setEnabled(true);
122 btn_VideoStop.setEnabled(false);
123 Toast.makeText(VideoActivity.this, "停止录像,并保存文件", 0).show();
124 }
125 }
126
127 @Override
128 protected void onDestroy() {
129 if (isRecording) {
130 mediaRecorder.stop();
131 mediaRecorder.release();
132 mediaRecorder = null;
133 }
134 super.onDestroy();
135 }
136
137 }
录制视频需要用到麦克风和摄像头硬件,还需要赋予一些相应的权限。
1 <uses-permission android:name="android.permission.RECORD_AUDIO"/>
2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3 <uses-permission android:name="android.permission.CAMERA"/>
4 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
效果展示:
MediaRecorder的内部类
通过上面录制视频的Demo可以看出,使用MediaRecorder录制视频,需要设置一些录入源、编码格式、输出格式等。这些方法都是以int类型的参数设定的,它们其实都是在MediaRecorder的内部类中已经以常量的形式定义好了,直接适用场景进行选择即可。
• MediaRecorder.AudioEncoder:音频的编码格式。
• MediaRecorder.AudioSource:录制的音频源。
• MediaRecorder.OutputFormat:媒体文件的输出编码格式。
• MediaRecorder.VideoEncoder:视频的编码格式。
• MediaRecorder.VideoSource:录制的视频源。