Android使用AudioRecord實(shí)現(xiàn)錄音功能
前言
Android使用AudioRecord實(shí)現(xiàn)錄音
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、AudioRecord使用
Android平臺(tái)可以使用AudioRecord和MediaRecorder來實(shí)現(xiàn)錄音,因?yàn)锳udioRecord更接近底層,并且錄制的數(shù)據(jù)為原始(pcm)數(shù)據(jù),pcm數(shù)據(jù)可以再進(jìn)行處理轉(zhuǎn)換,直播中使用的都是處理后的pcm數(shù)據(jù),所以在這里面學(xué)習(xí)下使用AudioRecord。
- 構(gòu)造AudioRecord
AudioRecord類的構(gòu)造方法中有5個(gè)參數(shù)
/** * audioSource 表示數(shù)據(jù)來源 一般為麥克風(fēng) MediaRecorder.AudioSource.MIC * sampleRateInHz 表示采樣率 一般設(shè)置為 44100 * channelConfig 表示聲道 一般設(shè)置為 AudioFormat.CHANNEL_IN_MONO * audioFormat 數(shù)據(jù)編碼方式 這里使用 AudioFormat.ENCODING_PCM_16BIT * bufferSizeInBytes 數(shù)據(jù)大小 這里使用AudioRecord.getMinBufferSize 獲取? */ AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, ? ? ? ? ? ? int bufferSizeInBytes)
- 創(chuàng)建AudioRecord對(duì)象
private AudioRecord audioRecord = null;
private int recordBufsize = 0;
? ? private void createAudioRecord() {
? ? ? ? recordBufsize = AudioRecord
? ? ? ? ? ? ? ? .getMinBufferSize(44100,
? ? ? ? ? ? ? ? ? ? ? ? AudioFormat.CHANNEL_IN_MONO,
? ? ? ? ? ? ? ? ? ? ? ? AudioFormat.ENCODING_PCM_16BIT);
? ? ? ? audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
? ? ? ? ? ? ? ? 44100,
? ? ? ? ? ? ? ? AudioFormat.CHANNEL_IN_MONO,
? ? ? ? ? ? ? ? AudioFormat.ENCODING_PCM_16BIT,
? ? ? ? ? ? ? ? recordBufsize);
? ? }- 開始錄音
// 調(diào)用開始錄音 audioRecord.startRecording();
調(diào)用開始錄音后,需要從audioRecord中讀取錄音的數(shù)據(jù)
audioRecord.read(data, 0, recordBufsize);
- 結(jié)束錄音
audioRecord.stop();
- 釋放資源
audioRecord.release();
AudioRecord的關(guān)鍵方法已經(jīng)介紹了,下面貼上完整的代碼
二、使用步驟
清單文件聲明權(quán)限
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
關(guān)于Android 6.0動(dòng)態(tài)申請(qǐng)權(quán)限這里就不重復(fù)了,可自行百度
完整代碼
public class MainActivity extends AppCompatActivity {
? ? private static final String FILE_NAME = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + File.separator + "test.pcm";
? ? private AudioRecord audioRecord = null;
? ? private int recordBufsize = 0;
? ? private boolean isRecording = false;
? ? private Button startRecordBtn;
? ? private Button stopRecordBtn;
? ? private Thread recordingThread;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000);
? ? ? ? }
? ? ? ? if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 2000);
? ? ? ? }
? ? ? ? startRecordBtn = findViewById(R.id.start_record_btn);
? ? ? ? stopRecordBtn = findViewById(R.id.stop_record_btn);
? ? ? ? createAudioRecord();
? ? ? ? startRecordBtn.setOnClickListener(v -> {
? ? ? ? ? ? startRecord();
? ? ? ? });
? ? ? ? stopRecordBtn.setOnClickListener(v -> {
? ? ? ? ? ? stopRecord();
? ? ? ? });
? ? }
? ? private void createAudioRecord() {
? ? ? ? recordBufsize = AudioRecord
? ? ? ? ? ? ? ? .getMinBufferSize(44100,
? ? ? ? ? ? ? ? ? ? ? ? AudioFormat.CHANNEL_IN_MONO,
? ? ? ? ? ? ? ? ? ? ? ? AudioFormat.ENCODING_PCM_16BIT);
? ? ? ? Log.i("audioRecordTest", "size->" + recordBufsize);
? ? ? ? audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
? ? ? ? ? ? ? ? 44100,
? ? ? ? ? ? ? ? AudioFormat.CHANNEL_IN_MONO,
? ? ? ? ? ? ? ? AudioFormat.ENCODING_PCM_16BIT,
? ? ? ? ? ? ? ? recordBufsize);
? ? }
? ? private void startRecord() {
? ? ? ? if (isRecording) {
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? isRecording = true;
? ? ? ? audioRecord.startRecording();
? ? ? ? Log.i("audioRecordTest", "開始錄音");
? ? ? ? recordingThread = new Thread(() -> {
? ? ? ? ? ? byte data[] = new byte[recordBufsize];
? ? ? ? ? ? File file = new File(FILE_NAME);
? ? ? ? ? ? FileOutputStream os = null;
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? if (!file.exists()) {
? ? ? ? ? ? ? ? ? ? file.createNewFile();
? ? ? ? ? ? ? ? ? ? Log.i("audioRecordTest", "創(chuàng)建錄音文件->" + FILE_NAME);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? os = new FileOutputStream(file);
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? int read;
? ? ? ? ? ? if (os != null) {
? ? ? ? ? ? ? ? while (isRecording) {
? ? ? ? ? ? ? ? ? ? read = audioRecord.read(data, 0, recordBufsize);
? ? ? ? ? ? ? ? ? ? if (AudioRecord.ERROR_INVALID_OPERATION != read) {
? ? ? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? ? ? os.write(data);
? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.i("audioRecordTest", "寫錄音數(shù)據(jù)->" + read);
? ? ? ? ? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? os.close();
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? recordingThread.start();
? ? }
? ? private void stopRecord() {
? ? ? ? isRecording = false;
? ? ? ? if (audioRecord != null) {
? ? ? ? ? ? audioRecord.stop();
? ? ? ? ? ? Log.i("audioRecordTest", "停止錄音");
? ? ? ? ? ? audioRecord.release();
? ? ? ? ? ? audioRecord = null;
? ? ? ? ? ? recordingThread = null;
? ? ? ? }
? ? }
}布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ? ? android:layout_width="match_parent" ? ? android:layout_height="match_parent" ? ? android:orientation="vertical"> ? ? <Button ? ? ? ? android:id="@+id/start_record_btn" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="wrap_content" ? ? ? ? android:text="開始錄音" /> ? ? <Button ? ? ? ? android:id="@+id/stop_record_btn" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="wrap_content" ? ? ? ? android:text="結(jié)束錄音" /> </LinearLayout>
運(yùn)行程序,點(diǎn)擊開始錄音,本地會(huì)創(chuàng)建test.pcm文件并寫入錄音數(shù)據(jù)。
總結(jié)
通過上面的學(xué)習(xí),對(duì)AudioRecord有初步的了解,能使用AudioRecord來實(shí)現(xiàn)錄音功能保存到本地。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Androd 勇闖高階性能優(yōu)化之布局優(yōu)化篇
Android性能優(yōu)化方面也有很多文章了,這里就做一個(gè)總結(jié),從原理到方法,工具等做一個(gè)簡(jiǎn)單的了解,從而可以慢慢地改變編碼風(fēng)格,從而提高性能2021-10-10
Android實(shí)現(xiàn)捕獲TextView超鏈接的方法
這篇文章主要介紹了Android實(shí)現(xiàn)捕獲TextView超鏈接的方法,涉及Android查找TextView中超鏈接的相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10
Android編程判斷SD卡是否存在及使用容量查詢實(shí)現(xiàn)方法
這篇文章主要介紹了Android編程判斷SD卡是否存在及使用容量查詢實(shí)現(xiàn)方法,實(shí)例分析了Android針對(duì)SD卡是否存在及使用容量、全部容量等的判斷技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-10-10
android listview實(shí)現(xiàn)新聞列表展示效果
這篇文章主要為大家詳細(xì)介紹了android listview實(shí)現(xiàn)新聞列表展示效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
根據(jù)USER-AGENT判斷手機(jī)類型并跳轉(zhuǎn)到相應(yīng)的app下載頁(yè)面
檢測(cè)瀏覽器的USER-AGENT,然后根據(jù)正則表達(dá)式來確定客戶端類型,并跳轉(zhuǎn)到相應(yīng)的app下載頁(yè)面,這個(gè)方法還是比較實(shí)用的,大家可以看看2014-09-09
Android recycleView的應(yīng)用和點(diǎn)擊事件實(shí)例詳解
這篇文章主要介紹了Android recycleView的應(yīng)用和點(diǎn)擊事件實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12
Flutter如何完成路由攔截,實(shí)現(xiàn)權(quán)限管理
本篇介紹了利用 Fluro 路由管理實(shí)現(xiàn)路由權(quán)限攔截的兩種方式,兩種方式各有好處,使用過程中可以根據(jù)實(shí)際情況決定使用哪一種方法。2021-06-06
Android屏幕旋轉(zhuǎn)之橫屏豎屏切換的實(shí)現(xiàn)
這篇文章主要介紹了Android屏幕旋轉(zhuǎn)之橫屏豎屏切換的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
輕松實(shí)現(xiàn)安卓(Android)九宮格解鎖
在平常使用手機(jī)的過程中,九宮格解鎖是我們經(jīng)常接觸到的。常見的比如有鎖屏中的九宮格,還有支付寶中的九宮格等。因?yàn)榫艑m格可以保護(hù)用戶的隱私,所以它的應(yīng)用面很廣泛。那么今天我們就來自定義一個(gè)屬于自己的九宮格吧!2016-08-08

