今天項(xiàng)目里有一個(gè)需要進(jìn)行錄音的功能,第一時(shí)間想到的AudioRecorder和MediaRecorder,但是后臺(tái)要的格式是amr,所以只能使用MediaRecorder來進(jìn)行音頻錄制,并且把它寫成了一個(gè)工具類來分享給大家。當(dāng)然你也可以使用AudioRecorder,但是你需要進(jìn)行一個(gè)額外的轉(zhuǎn)碼工作。
一、音頻錄制權(quán)限
/**
* 1. 錄音權(quán)限
* 2. 存儲(chǔ)權(quán)限
*/
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
二、MediaRecorder主要方法
1. 一般我們要進(jìn)行音頻錄制會(huì)想到一些最基礎(chǔ)的方法。
/**
* 第一時(shí)間想到的肯定會(huì)是開始錄制,停止錄制,還有準(zhǔn)備錄制這三個(gè)基礎(chǔ)的方法。
* 錄制完之后我們會(huì)對(duì)對(duì)資源進(jìn)行一個(gè)釋放,這個(gè)時(shí)候會(huì)想到重置和釋放這兩個(gè)方法。
*/
//開始
void start();
//停止
void stop();
//準(zhǔn)備
void prepar();
//重置
void reset();
//釋放資源
void release();
2. 這些基礎(chǔ)的方法有了之后我們會(huì)對(duì)音頻的編碼,還有音頻文件需要保存的路徑進(jìn)行一個(gè)設(shè)置。
/**
* 我們?cè)黉浿埔纛l的時(shí)候可以想一想,既然是錄音,那么就得設(shè)置我們聲音的來源,設(shè)置完
* 聲音來源之后我們?cè)撛O(shè)置的肯定是自己想要輸出的音頻格式了,格式設(shè)置完我們也得設(shè)置
* 錄音的編碼。完事以后就該保存我們的音頻文件了。
*/
//設(shè)置音頻來源
void setAudioSource(int);
//設(shè)置音頻輸出格式
void setOutputFormat(int);
//設(shè)置音頻編碼方式
void setAudioEncoder(int);
//保存錄制的音頻文件
void setOutputFile(String);
3. 音頻來源,輸出格式,音頻編碼的設(shè)定。
3.1 音頻來源
在源碼中可以看到音頻來源有 9 種。

音頻來源設(shè)定
按設(shè)定編碼排序
| 常數(shù) | |
|---|---|
| DEFAULT | 默認(rèn)音頻來源。 |
| MIC | 音頻來源為麥克風(fēng)。 |
| VOICE_UPLINK | Voice call uplink (Tx) audio source. 語音呼叫上行(Tx)音頻源。 |
| VOICE_DOWNLINK | Voice call downlink (Rx) audio source. 語音呼叫下行鏈路(Rx)音頻源。 |
| VOICE_CALL | 語音通話上行+下行音頻源 從VOICE_CALL源捕獲需要獲得 Manifest.permission.CAPTURE_AUDIO_OUTPUT許可。 |
| CAMCORDER | 調(diào)整了用于視頻錄制的麥克風(fēng)音頻源,如果沒有內(nèi)置相機(jī)或者無法識(shí)別會(huì)使用預(yù)設(shè)的麥克風(fēng)。 |
| VOICE_RECOGNITION | 用于捕獲要實(shí)時(shí)處理并回放以進(jìn)行現(xiàn)場(chǎng)表演(例如卡拉OK)的音頻的源。 |
| VOICE_COMMUNICATION | 調(diào)整了用于語音通信(例如VoIP)的麥克風(fēng)音頻源。 |
| REMOTE_SUBMIX | 用于遠(yuǎn)程呈現(xiàn)音頻流子混合的音頻源。 |
3.2 音頻輸出格式
在源碼中可以看到輸出格式有 8 種

輸出格式設(shè)定
按設(shè)定編碼排序
| 常數(shù) | |
|---|---|
| DEFAULT | 默認(rèn) |
| THREE_GPP | GPP媒體文件格式 |
| MPEG_4 | MPEG4媒體文件格式 |
| 在API級(jí)別16中不推薦使用此常量。不推薦使用MediaRecorder.OutputFormat.AMR_NB | |
| AMR_NB | AMR NB文件格式 |
| AMR_WB | AMR WB文件格式 |
| AAC_ADTS | AAC ADTS文件格式 |
| WEBM | WEBM容器中的VP8 / VORBIS數(shù)據(jù) |
3.3 音頻編碼
在源碼種看到有 7 種編碼格式。

編解碼格式設(shè)定
按照設(shè)定編碼排序
| 常數(shù) | |
|---|---|
| DEFAULT | 默認(rèn) |
| AMR_NB | AMR(窄帶)音頻編解碼器 |
| AMR_WB | AMR(寬帶)音頻編解碼器 |
| AAC | AAC低復(fù)雜度(AAC-LC)音頻編解碼器 |
| HE_AAC | 高效AAC(HE-AAC)音頻編解碼器 |
| AAC_ELD | 增強(qiáng)型低延遲AAC(AAC-ELD)音頻編解碼器 |
| VORBIS | Ogg Vorbis音頻編解碼器(支持是可選的) |
但是在Android官網(wǎng)中我發(fā)現(xiàn)有一個(gè)額外的 Opus音頻編解碼器 。
在了解完這些基礎(chǔ)信息后就可以開始代碼的編寫了。
三、代碼編寫
初始化MediaRecorder
/**
* 首先需要對(duì)MediaRecorder進(jìn)行初始化。
*/
private MediaRecorder mMediaRecorder;
private void initMediaRecorder() {
mMediaRecorder = new MediaRecorder();
//初始化后需要對(duì)MediaRecorder的音頻來源,輸出格式,編碼方式,輸出地址進(jìn)行設(shè)置。
// 設(shè)置音頻來源 MIC == 麥克
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 設(shè)置默認(rèn)音頻輸出格式 .amr 格式
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB);
// 設(shè)置默認(rèn)音頻編碼方式 .amr 編碼
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
//指定音頻輸出文件路徑
mMediaRecorder.setOutputFile(Environment.getExternalStorageDirectory().getPath() +
"/" + MyUtils.getPackageName(MyApplication.getAppContext()) + "/recorder");
}
開始錄制
//開始錄音
public void start() {
if (mMediaRecorder == null) {
initMediaRecorder();
}
if (!isRecording) {
try {
isRecording = true;
mMediaRecorder.prepare();
mMediaRecorder.start();
//開始錄制
} catch (IOException e) {
e.printStackTrace();
isRecording = false;
}
} else {
ToastUtil.show("正在錄制中...");
}
}
停止錄制
//停止錄音
public void stop() {
if (mMediaRecorder != null && isRecording) {
isRecording = false;
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
mFile = null;
} else {
ToastUtil.show("先開始錄音");
}
}
這里還需要寫一個(gè)關(guān)閉Activity進(jìn)行釋放資源的方法。
//必須在onDestroy調(diào)用此方法,否則會(huì)消耗資源
public void onDestroy() {
if (mMediaRecorder != null && isRecording) {
isRecording = false;
mMediaRecorder.stop();
mMediaRecorder.release();
mPathList.clear();
}
mMediaRecorder = null;
}
這樣就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的音頻錄制功能,是不是很簡(jiǎn)單...
代碼已經(jīng)上傳到 github ,使用方法請(qǐng)查看Wiki如果想使用你可以直接使用依賴或者下載lib中的MediaRecorderUtils.java。(提取碼: 1vwc )