今天我们介绍一下Android中录音的应用。我们在开发中经常有需要录音的场景,比如语音记录,聊天发送语音。这些情况下我们就要进行录音操作。那么今天我就给大家介绍一下在Android中如何进行录音。
1.媒体录制器MediaRecorder简介
MediaRecorder是Android自带的音频和视频录制工具,它通过操纵摄像头和麦克风完成媒体录制,既可录制视频,又可单独录制音频。
2.MediaRecorder常用方法(录音与录像通用)
- reset:重置录制资源。
- prepare:准备录制。
- start:开始录制。
- stop:结束录制。
- release:释放录制资源。
- setOnErrorListener:设置错误监听器。可监听服务器异常和未知错误的事件。需要实现接口MediaRecorder.OnErrorListener的onError方法。
- setOnInfoListener:设置信息监听器。可监听录制结束事件,包括达到录制时长或达到录制大小。需要实现接口MediaRecorder.OnInfoListener的onInfo方法。
- setMaxDuration:设置可录制的最大时长,单位毫秒。
- setMaxFileSize:设置可录制的最大文件大小,单位字节。
- setOutputFile:设置输出文件的路径。
3.MediaRecorder用于音频录制的方法
- setAudioSource:设置音频来源。一般使用麦克风AudioSource.MIC。
- setOutputFormat:设置媒体输出格式。媒体输出格式的取值说明见表1。
表1 | |||
OutputFormat类的输出格式 | 格式分类 | 扩展名 | 格式说明 |
AMR_NB | 音频 | .amr | 窄带格式 |
AMR_WB | 音频 | .amr | 宽带格式 |
AAC_ADTS | 音频 | .aac | 高级的音频传输流格式 |
MPEG_4 | 视频 | .mp4 | MPEG4格式 |
THREE_GPP | 视频 | .3gp | 3GP格式 |
- setAudioEncoder:设置音频编码器。音频编码器的取值说明见表2。注意:该方法应在setOutputFormat方法之后执行,否则会出现setAudioEncoder called in an invalid state(2)的异常。
表2 | |
AudioEncoder类的音频编码器 | 说明 |
AMR_NB | 窄带编码 |
AMR_WB | 宽带编码 |
AAC | 低复杂度的高级编码 |
HE_AAC | 高效率的高级编码 |
AAC_ELD | 增强型低延时的高级编码 |
- setAudioSamplingRate:设置音频的采样率,单位千赫兹(kHz)。AMR_NB格式默认8kHz,AMR_WB格式默认16kHz。
- setAudioChannels:设置音频的声道数。1表示单声道,2表示双声道。
- setAudioEncodingBitRate:设置音频每秒录制的字节数。数值越大音频越清晰。
4.音频录制示例
权限添加
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_record"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="录音"
android:layout_centerInParent="true"
android:background="@android:color/holo_green_light"
android:gravity="center"/>
</RelativeLayout>
MainActivity.java
public class MainActivity extends WaterPermissionActivity implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
private TextView tv_record;
private MediaRecorder mMediaRecorder;
private String voicePath;
@Override
protected MvcBaseModel getModelImp() {
return null;
}
@Override
protected int getContentLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initWidget() {
tv_record = findViewById(R.id.tv_record);
tv_record.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
//开始录制
tv_record.setText("松开停止");
requestPermission(WRITE_EXTERNAL_STORAGE);
}else if (event.getAction() == MotionEvent.ACTION_UP){
//结束录制
tv_record.setText("录音");
cancelRecord();
}
return true;
}
});
}
@Override
protected void doSDWrite() {
requestPermission(READ_EXTERNAL_STORAGE);
}
@Override
protected void doSDRead() {
requestPermission(RECORD);
}
@Override
protected void doRecord() {
getPath();
startRecord();
}
/**
* 录制前创建一个空文件并获取路径
*/
private void getPath(){
List<String> list = new ArrayList<>();
list.add("record");
String dirPath = PathGetUtil.getLongwayPath(this,list);
File fileDir = new File(dirPath);
if (!fileDir.exists()){
fileDir.mkdirs();
}
File fileVoice = new File(dirPath,"voice"+System.currentTimeMillis()+".amr");
if (!fileVoice.exists()){
try {
fileVoice.createNewFile();
voicePath = fileVoice.getPath();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 开始录音
*/
private void startRecord(){
//开始录音操作
mMediaRecorder = new MediaRecorder(); // 创建一个媒体录制器
mMediaRecorder.setOnErrorListener(this); // 设置媒体录制器的错误监听器
mMediaRecorder.setOnInfoListener(this); // 设置媒体录制器的信息监听器
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置音频源为麦克风
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); // 设置媒体的输出格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置媒体的音频编码器
// mMediaRecorder.setAudioSamplingRate(8); // 设置媒体的音频采样率。可选
// mMediaRecorder.setAudioChannels(2); // 设置媒体的音频声道数。可选
// mMediaRecorder.setAudioEncodingBitRate(1024); // 设置音频每秒录制的字节数。可选
mMediaRecorder.setMaxDuration(10 * 1000); // 设置媒体的最大录制时长
// mMediaRecorder.setMaxFileSize(1024*1024*10); // 设置媒体的最大文件大小
// setMaxFileSize与setMaxDuration设置其一即可
mMediaRecorder.setOutputFile(voicePath); // 设置媒体文件的保存路径
try {
mMediaRecorder.prepare(); // 媒体录制器准备就绪
mMediaRecorder.start(); // 媒体录制器开始录制
} catch (Exception e) {
e.printStackTrace();
}
}
// 取消录制操作
private void cancelRecord() {
if (mMediaRecorder != null) {
mMediaRecorder.setOnErrorListener(null); // 错误监听器置空
mMediaRecorder.setPreviewDisplay(null); // 预览界面置空
try {
mMediaRecorder.stop(); // 媒体录制器停止录制
} catch (Exception e) {
e.printStackTrace();
}
mMediaRecorder.release(); // 媒体录制器释放资源
mMediaRecorder = null;
}
}
@Override
public void onError(MediaRecorder mr, int what, int extra) {
if (mr != null) {
mr.reset(); // 重置媒体录制器
}
}
@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
// 录制达到最大时长,或者达到文件大小限制,都停止录制
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
|| what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
cancelRecord();
}
}
}
老规矩,动态权限大家根据自身情况进行申请。触发开始录制是执行getPath()和startRecord()两个方法,一个是获取一个新的文件路径,用来放音频文件。另一个是开始真正的录制。停止录制调用cancelRecord()方法。其他处理可以按照示例代码中的进行配置。参数可以根据项目实际情况进行修改。