音頻錄制(一)

MediaRecorder.AudioSource音頻參數說明

MediaRecorder.AudioSource.MIC參數說明

其中第一個參數就是選擇錄音源的,其可選參數如下:

MediaRecorder.AudioSource.CAMCORDER? ?//?設定錄音來源于同方向的相機麥克風相同,若相機無內置相機或無法識別,則使用預設的麥克風 MediaRecorder.AudioSource.DEFAULT? // 默認音頻源
MediaRecorder.AudioSource.MIC? // 設定錄音來源為主麥克風。
MediaRecorder.AudioSource.VOICE_CALL? // 設定錄音來源為語音撥出的語音與對方說話的聲音MediaRecorder.AudioSource.VOICE_COMMUNICATION? // 攝像頭旁邊的麥克風
MediaRecorder.AudioSource.VOICE_DOWNLINK? // 下行聲音
MediaRecorder.AudioSource.VOICE_RECOGNITION? // 語音識別
MediaRecorder.AudioSource.VOICE_UPLINK? //?上行聲音

音頻的兩種錄制方式-AudioRecord,MediaRecorder的使用及播放

AudioRecord和MediaRecorder兩種都可以錄制音頻,MediaRecorder已實現大量的封裝,操作起來更加簡單,而AudioRecord使用起來更加靈活,能實現更多的功能。

1.AudioRecord(基于字節流錄音)?

優點:可以實現語音的實時處理,進行邊錄邊播,對音頻的實時處理。?

缺點:輸出的是PCM的語音數據,如果保存成音頻文件是不能被播放器播放的。要用到AudioTrack這個去進行處理。

2.MediaRecorder(基于文件錄音)?

已集成了錄音,編碼,壓縮等,支持少量的音頻格式文件。?

優點:封裝度很高,操作簡單?

缺點:無法實現實時處理音頻,輸出的音頻格式少。

功能實現:MediaRecorder(這里需要注意,無論錄制還是播放都是一個耗時操作,需要在非主線程中去操作)

//實現觸摸錄音,松開錄音結束tv_press_send.setOnTouchListener(new View.OnTouchListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean onTouch(View v, MotionEvent event) {
? ? ? ? ? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? ? ? ? ? ? ? startRecorder();
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? ? ? ? ? stopRecorder();
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_CANCEL:
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? });

開啟一個單線程去實現錄音功能,及失敗操作:

/**
? ? ?* 開啟錄音
? ? ?*/
? ? private void startRecorder() {
? ? ? ? tv_press_send.setText("正在說話...");
? ? ? ? //提交后臺任務,開始錄音? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? //釋放上一次的錄音
? ? ? ? ? ? ? ? releaseRecorder();
? ? ? ? ? ? ? ? //開始錄音
? ? ? ? ? ? ? ? if (!doStart()) {
? ? ? ? ? ? ? ? ? ? recorderFial();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? }

啟動錄音,及MediaRecorder的配置:

/**
?* 啟動錄音
?* * @return
*/
?private boolean doStart() {
? ? ? ? try {
? ? ? ? ? ? //創建MediaRecorder
? ? ? ? ? ? mMediaRecorder = new MediaRecorder();
? ? ? ? ? ? //創建錄音文件
? ? ? ? ? ? mRecorderFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
? ? ? ? ? ? ? ? ? ? + "/recorderdemo/" + System.currentTimeMillis() + ".m4a");

? ? ? ? ? ? if (!mRecorderFile.getParentFile().exists()) mRecorderFile.getParentFile().mkdirs();
? ? ? ? ? ? mRecorderFile.createNewFile();
? ? ? ? ? ? //配置MediaRecorder
? ? ? ? ? ? //從麥克風采集
? ? ? ? ? ? mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
? ? ? ? ? ? //保存文件為MP4格式
? ? ? ? ? ? mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
? ? ? ? ? ? //所有android系統都支持的適中采樣的頻率
? ? ? ? ? ? mMediaRecorder.setAudioSamplingRate(44100);
? ? ? ? ? ? //通用的AAC編碼格式
? ? ? ? ? ? mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
? ? ? ? ? ? //設置音質頻率
? ? ? ? ? ? mMediaRecorder.setAudioEncodingBitRate(96000);
? ? ? ? ? ? //設置文件錄音的位置
? ? ? ? ? ? mMediaRecorder.setOutputFile(mRecorderFile.getAbsolutePath());
? ? ? ? ? ? //開始錄音
? ? ? ? ? ? mMediaRecorder.prepare();
? ? ? ? ? ? mMediaRecorder.start();
? ? ? ? ? ? startRecorderTime = System.currentTimeMillis();
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? Toast.makeText(FileActivity.this, "錄音失敗,請重試", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? //記錄開始錄音時間,用于統計時長,小于3秒中,錄音不發送? ? ? ? return true;
? ? }

停止錄音操作:

/**
?* 關閉錄音 *
?* @return*/
?private boolean doStop() {
? ? ? ? try {
? ? ? ? ? ? mMediaRecorder.stop();
? ? ? ? ? ? stopRecorderTime = System.currentTimeMillis();
? ? ? ? ? ? final int second = (int) (stopRecorderTime - startRecorderTime) / 1000;
? ? ? ? ? ? //按住時間小于3秒鐘,算作錄取失敗,不進行發送
? ? ? ? ? ? if (second < 3) return false;
? ? ? ? ? ? mHander.post(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? tv_sendmsg.setText("錄制成功:" + second + "秒");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return true;
? ? }

釋放MediaRecorder:

/**
? * 釋放上一次的錄音
? */
? ? private void releaseRecorder() {
? ? ? ? if (mMediaRecorder != null) {
? ? ? ? ? ? mMediaRecorder.release();
? ? ? ? ? ? mMediaRecorder = null;
? ? ? ? }
? ? }

錄音的播放:使用MediaPlayer

開啟一個單線程,去播放:

/**
?* 播放錄音 *
?* @paramview
?*/
?public void playrecorder(View view) {
? ? ? ? if (!mIsPlaying) {
? ? ? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? doPlay(mRecorderFile);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? } else {
? ? ? ? ? ? Toast.makeText(FileActivity.this, "正在播放", Toast.LENGTH_SHORT).show();
? ? ? ? }
? ? }

具體播放代碼:

private void doPlay(File audioFile) {
? ? ? ? try {
? ? ? ? ? ? //配置播放器 MediaPlayer
? ? ? ? ? ? mediaPlayer = new MediaPlayer();
? ? ? ? ? ? //設置聲音文件
? ? ? ? ? ? mediaPlayer.setDataSource(audioFile.getAbsolutePath());
? ? ? ? ? ? //配置音量,中等音量
? ? ? ? ? ? mediaPlayer.setVolume(1,1);
? ? ? ? ? ? //播放是否循環
? ? ? ? ? ? mediaPlayer.setLooping(false);
? ? ? ? ? ? //設置監聽回調 播放完畢
? ? ? ? ? ? mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void onCompletion(MediaPlayer mp) {
? ? ? ? ? ? ? ? ? ? stopPlayer();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? ? ? mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public boolean onError(MediaPlayer mp, int what, int extra) {
? ? ? ? ? ? ? ? ? ? stopPlayer();
? ? ? ? ? ? ? ? ? ? Toast.makeText(FileActivity.this,"播放失敗",Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? ? ? //設置播放
? ? ? ? ? ? mediaPlayer.prepare();
? ? ? ? ? ? mediaPlayer.start();
? ? ? ? ? ? //異常處理,防止閃退
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? stopPlayer();
? ? ? ? }
? ? }

activity銷毀后的onDestory的處理:

@Override
?protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? //當activity關閉時,停止這個線程,防止內存泄漏
? ? ? ? mExecutorService.shutdownNow();
? ? ? ? releaseRecorder();
? ? }

MediaRecord完整功能實現代碼:

package com.example.amelon.myapplication;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public classFileActivityextendsAppCompatActivity{

? ? private TextView tv_sendmsg, tv_press_send;
? ? private ExecutorService mExecutorService;
? ? private MediaRecorder mMediaRecorder;
? ? private MediaPlayer mediaPlayer;
? ? private File mRecorderFile;
? ? private long startRecorderTime, stopRecorderTime;
? ? private Handler mHander = new Handler(Looper.getMainLooper());
? ? private boolean mIsPlaying = false;

? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_first);
? ? ? ? setTitle("文件錄音");
? ? ? ? initView();
? ? ? ? //錄音JNI函數不具有線程安全性,因此用單線程? ? ? ? mExecutorService = Executors.newSingleThreadExecutor();
? ? }

? ? private void initView() {
? ? ? ? tv_sendmsg = (TextView) findViewById(R.id.tv_sendmsg);
? ? ? ? tv_press_send = (TextView) findViewById(R.id.tv_press_send);
? ? ? ? tv_press_send.setOnTouchListener(new View.OnTouchListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean onTouch(View v, MotionEvent event) {
? ? ? ? ? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? ? ? ? ? ? ? startRecorder();
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? ? ? ? ? stopRecorder();
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_CANCEL:
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? });
? ? }

? ? /**
? ? ?* 開啟錄音
? ? ?*/
? ? private void startRecorder() {
? ? ? ? tv_press_send.setText("正在說話...");
? ? ? ? //提交后臺任務,開始錄音
? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? //釋放上一次的錄音
? ? ? ? ? ? ? ? releaseRecorder();
? ? ? ? ? ? ? ? //開始錄音
? ? ? ? ? ? ? ? if (!doStart()) {
? ? ? ? ? ? ? ? ? ? recorderFial();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? }

? ? /**
? ? ?* 釋放上一次的錄音
? ? ?*/
? ? private void releaseRecorder() {
? ? ? ? if (mMediaRecorder != null) {
? ? ? ? ? ? mMediaRecorder.release();
? ? ? ? ? ? mMediaRecorder = null;
? ? ? ? }
? ? }

? ? /**
? ? ?* 啟動錄音? ? *
? ? ?* @return
? ? ?*/
? ? private boolean doStart() {
? ? ? ? try {
? ? ? ? ? ? //創建MediaRecorder
? ? ? ? ? ? mMediaRecorder = new MediaRecorder();
? ? ? ? ? ? //創建錄音文件
? ? ? ? ? ? mRecorderFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
? ? ? ? ? ? ? ? ? ? + "/recorderdemo/" + System.currentTimeMillis() + ".m4a");

? ? ? ? ? ? if (!mRecorderFile.getParentFile().exists()) mRecorderFile.getParentFile().mkdirs();
? ? ? ? ? ? mRecorderFile.createNewFile();
? ? ? ? ? ? //配置MediaRecorder
? ? ? ? ? ? //從麥克風采集
? ? ? ? ? ? mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
? ? ? ? ? ? //保存文件為MP4格式
? ? ? ? ? ? mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
? ? ? ? ? ? //所有android系統都支持的適中采樣的頻率
? ? ? ? ? ? mMediaRecorder.setAudioSamplingRate(44100);
? ? ? ? ? ? //通用的AAC編碼格式
? ? ? ? ? ? mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
? ? ? ? ? ? //設置音質頻率
? ? ? ? ? ? mMediaRecorder.setAudioEncodingBitRate(96000);
? ? ? ? ? ? //設置文件錄音的位置
? ? ? ? ? ? mMediaRecorder.setOutputFile(mRecorderFile.getAbsolutePath());
? ? ? ? ? ? //開始錄音
? ? ? ? ? ? mMediaRecorder.prepare();
? ? ? ? ? ? mMediaRecorder.start();
? ? ? ? ? ? startRecorderTime = System.currentTimeMillis();
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? Toast.makeText(FileActivity.this, "錄音失敗,請重試", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? //記錄開始錄音時間,用于統計時長,小于3秒中,錄音不發送? ? ? ? return true;
? ? }

? ? /**
? ? ?* 關閉錄音? ? *
? ? ?* @return*/
? ? private boolean doStop() {
? ? ? ? try {
? ? ? ? ? ? mMediaRecorder.stop();
? ? ? ? ? ? stopRecorderTime = System.currentTimeMillis();
? ? ? ? ? ? final int second = (int) (stopRecorderTime - startRecorderTime) / 1000;
? ? ? ? ? ? //按住時間小于3秒鐘,算作錄取失敗,不進行發送? ? ? ? ? ? if (second < 3) return false;
? ? ? ? ? ? mHander.post(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? tv_sendmsg.setText("錄制成功:" + second + "秒");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return true;
? ? }

? ? /**
? ? ?* 錄音失敗邏輯
? ? ?*/
? ? private void recorderFial() {
? ? ? ? mRecorderFile = null;
? ? ? ? mHander.post(new Runnable() {
? ? ? ? ? ? @Override? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? tv_press_send.setText("錄音失敗請重新錄音");
? ? ? ? ? ? }
? ? ? ? });
? ? }

? ? /**
? ? ?* 停止錄音
? ? ?*/
? ? private void stopRecorder() {
? ? ? ? tv_press_send.setText("開始錄音");
? ? ? ? //提交后臺任務,停止錄音
? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? if (!doStop()) {
? ? ? ? ? ? ? ? ? ? recorderFial();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? releaseRecorder();
? ? ? ? ? ? }
? ? ? ? });
? ? }

? ? /**
? ? ?* 播放錄音? ? *?
? ? * @paramview
? ? ?*/?
? ?public void playrecorder(View view) {
? ? ? ? if (!mIsPlaying) {
? ? ? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? doPlay(mRecorderFile);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? } else {
? ? ? ? ? ? Toast.makeText(FileActivity.this, "正在播放", Toast.LENGTH_SHORT).show();
? ? ? ? }
? ? }
? ? private void doPlay(File audioFile) {
? ? ? ? try {
? ? ? ? ? ? //配置播放器 MediaPlayer
? ? ? ? ? ? mediaPlayer = new MediaPlayer();
? ? ? ? ? ? //設置聲音文件
? ? ? ? ? ? mediaPlayer.setDataSource(audioFile.getAbsolutePath());
? ? ? ? ? ? //配置音量,中等音量
? ? ? ? ? ? mediaPlayer.setVolume(1,1);
? ? ? ? ? ? //播放是否循環
? ? ? ? ? ? mediaPlayer.setLooping(false);
? ? ? ? ? ? //設置監聽回調 播放完畢
? ? ? ? ? ? mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void onCompletion(MediaPlayer mp) {
? ? ? ? ? ? ? ? ? ? stopPlayer();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });

? ? ? ? ? ? mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public boolean onError(MediaPlayer mp, int what, int extra) {
? ? ? ? ? ? ? ? ? ? stopPlayer();
? ? ? ? ? ? ? ? ? ? Toast.makeText(FileActivity.this,"播放失敗",Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });

? ? ? ? ? ? //設置播放
? ? ? ? ? ? mediaPlayer.prepare();
? ? ? ? ? ? mediaPlayer.start();
? ? ? ? ? ? //異常處理,防止閃退
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? stopPlayer();
? ? ? ? }
? ? }

? ? private void stopPlayer(){
? ? ? ? mIsPlaying=false;
? ? ? ? mediaPlayer.release();
? ? ? ? mediaPlayer=null;
? ? }

? ? @Override
? ? protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? //當activity關閉時,停止這個線程,防止內存泄漏
? ? ? ? mExecutorService.shutdownNow();
? ? ? ? releaseRecorder();
? ? }
}

xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
?xmlns:tools="http://schemas.android.com/tools"
?android:id="@+id/activity_first"
?android:layout_width="match_parent"
?android:layout_height="match_parent"
?android:orientation="vertical"
?android:padding="2dp"
?tools:context="com.example.amelon.myapplication.FileActivity">


<Button
?android:onClick="playrecorder"
?android:layout_width="wrap_content"
?android:layout_height="wrap_content"
?android:text="播放"
?android:paddingLeft="3dp"
?android:paddingRight="3dp" />

<TextView
?android:id="@+id/tv_sendmsg"
?android:layout_weight="8"
?android:layout_width="wrap_content"
?android:layout_height="0dp"
?android:layout_marginTop="30dp"
?android:onClick="filerecord"
?android:text="文件錄音:" />

< TextView
?android:id="@+id/tv_press_send"
?android:layout_width="match_parent"
?android:layout_weight="1"
?android:background="@android:color/darker_gray"
?android:gravity="center"
?android:layout_height="0dp"
?android:textSize="24sp"
?android:textColor="#70ffffff"
?android:paddingLeft="10dp"
?android:paddingRight="10dp"
?android:text="按下說話" />

< /LinearLayout>


AudioRecord的功能實現:?

實現一個點擊button進行錄音,再次點擊停止錄音功能

開啟錄音和停止錄音:

public void recorderaudio(View view) {
? ? ? ? if (mIsRecording) {
? ? ? ? ? ? bt_stream_recorder.setText("開始錄音");
? ? ? ? ? ? //在開始錄音中如果這個值沒有變false,則一直進行,當再次點擊變false時,錄音才停止
? ? ? ? ? ? mIsRecording = false;
? ? ? ? ? ? //執行停止錄音邏輯,這塊不用下面代碼,只需上面變換mIsRecording這個狀態就可以了,下面一直走while
? ? ? ? ? /*? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? stopRecorder();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });*/?
? ? ? ?} else {
? ? ? ? ? ? bt_stream_recorder.setText("停止錄音");
? ? ? ? ? ? //提交后臺任務,執行錄音邏輯
? ? ? ? ? ? mIsRecording = true;
? ? ? ? ? ? //提交后臺任務,執行錄音邏輯
? ? ? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? startRecorder();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? }
? ? }

開啟錄音:

/**
? ? ?* 開始錄音
? ? ?*/
? ? private void startRecorder() {
? ? ? ? // realeseRecorder();
? ? ? ? if (!dostart()) recorderFail();
? ? }

AudioRecord的配置及功能實現具體代碼:

private boolean dostart() {
? ? ? ? try {
? ? ? ? ? ? //記錄開始錄音時間
? ? ? ? ? ? startRecorderTime = System.currentTimeMillis();
? ? ? ? ? ? //創建錄音文件
? ? ? ? ? ? mAudioRecordFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
? ? ? ? ? ? ? ? ? ? "/recorderdemo/" + System.currentTimeMillis() + ".pcm");
? ? ? ? ? ? if (!mAudioRecordFile.getParentFile().exists())
? ? ? ? ? ? ? ? mAudioRecordFile.getParentFile().mkdirs();
? ? ? ? ? ? mAudioRecordFile.createNewFile();
? ? ? ? ? ? //創建文件輸出流
? ? ? ? ? ? mFileOutputStream = new FileOutputStream(mAudioRecordFile);
? ? ? ? ? ? //配置AudioRecord
? ? ? ? ? ? int audioSource = MediaRecorder.AudioSource.MIC;
? ? ? ? ? ? //所有android系統都支持
? ? ? ? ? ? int sampleRate = 44100;
? ? ? ? ? ? //單聲道輸入
? ? ? ? ? ? int channelConfig = AudioFormat.CHANNEL_IN_MONO;
? ? ? ? ? ? //PCM_16是所有android系統都支持的
? ? ? ? ? ? int autioFormat = AudioFormat.ENCODING_PCM_16BIT;
? ? ? ? ? ? //計算AudioRecord內部buffer最小
? ? ? ? ? ? int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, autioFormat);
? ? ? ? ? ? //buffer不能小于最低要求,也不能小于我們每次我們讀取的大小。
? ? ? ? ? ? mAudioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, autioFormat, Math.max(minBufferSize, BUFFER_SIZE));
? ? ? ? ? ? //開始錄音
? ? ? ? ? ? mAudioRecord.startRecording();
? ? ? ? ? ? //循環讀取數據,寫入輸出流中
? ? ? ? ? ? while (mIsRecording) {
? ? ? ? ? ? ? ? //只要還在錄音就一直讀取
? ? ? ? ? ? ? ? int read = mAudioRecord.read(mBuffer, 0, BUFFER_SIZE);
? ? ? ? ? ? ? ? if(read<=0){
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? mFileOutputStream.write(mBuffer, 0, read);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //退出循環,停止錄音,釋放資源
? ? ? ? ? ? stopRecorder();
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? return false;
? ? ? ? } finally {
? ? ? ? ? ? if (mAudioRecord != null) {
? ? ? ? ? ? ? ? mAudioRecord.release();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return true;
? ? }

再次點擊停止錄音操作代碼:

private boolean doStop() {
? ? ? ? //停止錄音,關閉文件輸出流
? ? ? ? mAudioRecord.stop();
? ? ? ? mAudioRecord.release();
? ? ? ? mAudioRecord = null;
? ? ? ? //記錄結束時間,統計錄音時長
? ? ? ? stopRecorderTime = System.currentTimeMillis();
? ? ? ? //大于3秒算成功,在主線程更新UI
? ? ? ? final int send = (int) (stopRecorderTime - startRecorderTime) / 1000;
? ? ? ? if (send > 3) {
? ? ? ? ? ? mHandler.post(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? tv_stream_msg.setText("錄音成功:" + send + "秒");
? ? ? ? ? ? ? ? ? ? bt_stream_recorder.setText("開始錄音");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? } else {
? ? ? ? ? ? recorderFail();
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? return true;
? ? }

錄取失敗,更新UI操作:

private boolean recorderFail() {
? ? ? ? mHandler.post(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? bt_stream_recorder.setText("開始錄音");
? ? ? ? ? ? ? ? tv_stream_msg.setText("錄取失敗,請重新錄入");
? ? ? ? ? ? ? ? mIsRecording=false;
? ? ? ? ? ? ? ? Log.i("Tag8", "go here111111111");
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? return false;
? ? }

播放錄音代碼:

/** * 播放聲音
?* @paramview
?*/
?public void player(View view){
? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? if(!mIsPlaying){
? ? ? ? ? ? ? ? ? ? Log.i("Tag8","go here");
? ? ? ? ? ? ? ? ? ? mIsPlaying=true;
? ? ? ? ? ? ? ? ? ? doPlay(mAudioRecordFile);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? }

播放錄音具體實現,AudioTrack的使用:

private void doPlay(File audioFile) {
? ? ? ? if(audioFile !=null){
? ? ? ? ? ? Log.i("Tag8","go there");
? ? ? ? ? ? //配置播放器
? ? ? ? ? ? //音樂類型,揚聲器播放
? ? ? ? ? ? int streamType= AudioManager.STREAM_MUSIC;
? ? ? ? ? ? //錄音時采用的采樣頻率,所以播放時同樣的采樣頻率
? ? ? ? ? ? int sampleRate=44100;
? ? ? ? ? ? //單聲道,和錄音時設置的一樣
? ? ? ? ? ? int channelConfig=AudioFormat.CHANNEL_OUT_MONO;
? ? ? ? ? ? //錄音時使用16bit,所以播放時同樣采用該方式
? ? ? ? ? ? int audioFormat=AudioFormat.ENCODING_PCM_16BIT;
? ? ? ? ? ? //流模式
? ? ? ? ? ? int mode= AudioTrack.MODE_STREAM;
? ? ? ? ? ? //計算最小buffer大小
? ? ? ? ? ? int minBufferSize=AudioTrack.getMinBufferSize(sampleRate,channelConfig,audioFormat);
? ? ? ? ? ? //構造AudioTrack? 不能小于AudioTrack的最低要求,也不能小于我們每次讀的大小
? ? ? ? ? ? AudioTrack audioTrack=new AudioTrack(streamType,sampleRate,channelConfig,audioFormat,
? ? ? ? ? ? ? ? ? ? Math.max(minBufferSize,BUFFER_SIZE),mode);
? ? ? ? ? ? //從文件流讀數據
? ? ? ? ? ? FileInputStream inputStream=null;
? ? ? ? ? ? try{
? ? ? ? ? ? ? ? //循環讀數據,寫到播放器去播放
? ? ? ? ? ? ? ? inputStream=new FileInputStream(audioFile);
? ? ? ? ? ? ? ? //循環讀數據,寫到播放器去播放
? ? ? ? ? ? ? ? int read;
? ? ? ? ? ? ? ? //只要沒讀完,循環播放
? ? ? ? ? ? ? ? while ((read=inputStream.read(mBuffer))>0){
? ? ? ? ? ? ? ? ? ? Log.i("Tag8","read:"+read);
? ? ? ? ? ? ? ? ? ? int ret=audioTrack.write(mBuffer,0,read);
? ? ? ? ? ? ? ? ? ? //檢查write的返回值,處理錯誤
? ? ? ? ? ? ? ? ? ? switch (ret){
? ? ? ? ? ? ? ? ? ? ? ? case AudioTrack.ERROR_INVALID_OPERATION:
? ? ? ? ? ? ? ? ? ? ? ? case AudioTrack.ERROR_BAD_VALUE:
? ? ? ? ? ? ? ? ? ? ? ? case AudioManager.ERROR_DEAD_OBJECT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? playFail();
? ? ? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }catch (Exception e){
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? //讀取失敗
? ? ? ? ? ? ? ? playFail();
? ? ? ? ? ? }finally {
? ? ? ? ? ? ? ? mIsPlaying=false;
? ? ? ? ? ? ? ? //關閉文件輸入流?
? ? ? ? ? ? ? ?if(inputStream !=null){
? ? ? ? ? ? ? ? ? ? closeStream(inputStream);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //播放器釋放
? ? ? ? ? ? ? ? resetQuietly(audioTrack);
? ? ? ? ? ? }
? ? ? ? }
? ? }

播放失敗:更新UI操作

/**
? ? ?* 播放失敗
? ? ?*/
? ? private void playFail() {
? ? ? ? mHandler.post(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? tv_stream_msg.setText("播放失敗");
? ? ? ? ? ? }
? ? ? ? });
? ? }

activity銷毀處理代碼:

//防止內存泄漏
@Override protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? if (mExecutorService != null) {
? ? ? ? ? ? mExecutorService.shutdownNow();
? ? ? ? }
? ? ? ? if (mAudioRecord != null) {
? ? ? ? ? ? mAudioRecord.stop();
? ? ? ? ? ? mAudioRecord.release();
? ? ? ? ? ? mAudioRecord = null;
? ? ? ? }
? ? }

AudioRecord的功能實現完整代碼:

package com.example.amelon.myapplication;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public classStreamActivityextendsAppCompatActivity{ private Button bt_stream_recorder;
? ? private TextView tv_stream_msg;
? ? private ExecutorService mExecutorService;
? ? private long startRecorderTime, stopRecorderTime;
? ? private volatile boolean mIsRecording = false;
? ? private AudioRecord mAudioRecord;
? ? private FileOutputStream mFileOutputStream;
? ? private File mAudioRecordFile;
? ? private byte[] mBuffer;
? ? //buffer值不能太大,避免OOM
? ? private static final int BUFFER_SIZE = 2048;
? ? private boolean mIsPlaying=false;
? ? private Handler mHandler = new Handler(Looper.getMainLooper());
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_stream);
? ? ? ? setTitle("字節流錄音");
? ? ? ? initView();
? ? ? ? mExecutorService = Executors.newSingleThreadExecutor();
? ? ? ? mBuffer = new byte[BUFFER_SIZE];
? ? }

? ? private void initView() {
? ? ? ? bt_stream_recorder = (Button) findViewById(R.id.bt_stream_recorder);
? ? ? ? tv_stream_msg = (TextView) findViewById(R.id.tv_stream_msg);
? ? }

? ? public void recorderaudio(View view) {
? ? ? ? if (mIsRecording) {
? ? ? ? ? ? bt_stream_recorder.setText("開始錄音");
? ? ? ? ? ? //在開始錄音中如果這個值沒有變false,則一直進行,當再次點擊變false時,錄音才停止
? ? ? ? ? ? mIsRecording = false;
? ? ? ? ? ? //執行停止錄音邏輯,這塊不用下面代碼,只需上面變換mIsRecording這個狀態就可以了,下面一直走while
? ? ? ? ? /*? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? stopRecorder();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });*/
? ? ? ? } else {
? ? ? ? ? ? bt_stream_recorder.setText("停止錄音");
? ? ? ? ? ? //提交后臺任務,執行錄音邏輯
? ? ? ? ? ? mIsRecording = true;
? ? ? ? ? ? //提交后臺任務,執行錄音邏輯
? ? ? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? startRecorder();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? }
? ? }

? ? /**
? ? ?* 開始錄音
? ? ?*/
? ? private void startRecorder() {
? ? ? ? // realeseRecorder();
? ? ? ? if (!dostart()) recorderFail();
? ? }

? ? /**
? ? ?* 停止錄音
? ? ?*/
? ? private void stopRecorder() {
? ? ? ? mIsRecording=false;
? ? ? ? if (!doStop()) recorderFail();
? ? }
? ? private boolean dostart() {
? ? ? ? try {
? ? ? ? ? ? //記錄開始錄音時間
? ? ? ? ? ? startRecorderTime = System.currentTimeMillis();
? ? ? ? ? ? //創建錄音文件
? ? ? ? ? ? mAudioRecordFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
? ? ? ? ? ? ? ? ? ? "/recorderdemo/" + System.currentTimeMillis() + ".pcm");
? ? ? ? ? ? if (!mAudioRecordFile.getParentFile().exists())
? ? ? ? ? ? ? ? mAudioRecordFile.getParentFile().mkdirs();
? ? ? ? ? ? mAudioRecordFile.createNewFile();
? ? ? ? ? ? //創建文件輸出流
? ? ? ? ? ? mFileOutputStream = new FileOutputStream(mAudioRecordFile);
? ? ? ? ? ? //配置AudioRecord
? ? ? ? ? ? int audioSource = MediaRecorder.AudioSource.MIC;
? ? ? ? ? ? //所有android系統都支持
? ? ? ? ? ? int sampleRate = 44100;
? ? ? ? ? ? //單聲道輸入
? ? ? ? ? ? int channelConfig = AudioFormat.CHANNEL_IN_MONO;
? ? ? ? ? ? //PCM_16是所有android系統都支持的
? ? ? ? ? ? int autioFormat = AudioFormat.ENCODING_PCM_16BIT;
? ? ? ? ? ? //計算AudioRecord內部buffer最小
? ? ? ? ? ? int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, autioFormat);
? ? ? ? ? ? //buffer不能小于最低要求,也不能小于我們每次我們讀取的大小。
? ? ? ? ? ? mAudioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, autioFormat, Math.max(minBufferSize, BUFFER_SIZE));
? ? ? ? ? ? //開始錄音? ? ? ? ? ? mAudioRecord.startRecording();
? ? ? ? ? ? //循環讀取數據,寫入輸出流中
? ? ? ? ? ? while (mIsRecording) {
? ? ? ? ? ? ? ? //只要還在錄音就一直讀取
? ? ? ? ? ? ? ? int read = mAudioRecord.read(mBuffer, 0, BUFFER_SIZE);
? ? ? ? ? ? ? ? if(read<=0){
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? mFileOutputStream.write(mBuffer, 0, read);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //退出循環,停止錄音,釋放資源
? ? ? ? ? ? stopRecorder();
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? return false;
? ? ? ? } finally {
? ? ? ? ? ? if (mAudioRecord != null) {
? ? ? ? ? ? ? ? mAudioRecord.release();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return true;
? ? }

? ? private boolean recorderFail() {
? ? ? ? mHandler.post(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? bt_stream_recorder.setText("開始錄音");
? ? ? ? ? ? ? ? tv_stream_msg.setText("錄取失敗,請重新錄入");
? ? ? ? ? ? ? ? mIsRecording=false;
? ? ? ? ? ? ? ? Log.i("Tag8", "go here111111111");
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? return false;
? ? }

? ? private void realeseRecorder() {
? ? ? ? mAudioRecord.release();
? ? }

? ? private boolean doStop() {
? ? ? ? //停止錄音,關閉文件輸出流? ? ? ? mAudioRecord.stop();
? ? ? ? mAudioRecord.release();
? ? ? ? mAudioRecord = null;
? ? ? ? Log.i("Tag8", "go here");
? ? ? ? //記錄結束時間,統計錄音時長
? ? ? ? stopRecorderTime = System.currentTimeMillis();
? ? ? ? //大于3秒算成功,在主線程更新UI
? ? ? ? final int send = (int) (stopRecorderTime - startRecorderTime) / 1000;
? ? ? ? if (send > 3) {
? ? ? ? ? ? mHandler.post(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? tv_stream_msg.setText("錄音成功:" + send + "秒");
? ? ? ? ? ? ? ? ? ? bt_stream_recorder.setText("開始錄音");
? ? ? ? ? ? ? ? ? ? Log.i("Tag8", "go there");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? } else {
? ? ? ? ? ? recorderFail();
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? return true;
? ? }

? ? /**
? ? ?* 播放聲音
? ? ?* @paramview
? ? ?*/
? ? public void player(View view){
? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? if(!mIsPlaying){
? ? ? ? ? ? ? ? ? ? Log.i("Tag8","go here");
? ? ? ? ? ? ? ? ? ? mIsPlaying=true;
? ? ? ? ? ? ? ? ? ? doPlay(mAudioRecordFile);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? }

? ? private void doPlay(File audioFile) {
? ? ? ? if(audioFile !=null){
? ? ? ? ? ? Log.i("Tag8","go there");
? ? ? ? ? ? //配置播放器
? ? ? ? ? ? //音樂類型,揚聲器播放
? ? ? ? ? ? int streamType= AudioManager.STREAM_MUSIC;
? ? ? ? ? ? //錄音時采用的采樣頻率,所以播放時同樣的采樣頻率
? ? ? ? ? ? int sampleRate=44100;
? ? ? ? ? ? //單聲道,和錄音時設置的一樣
? ? ? ? ? ? int channelConfig=AudioFormat.CHANNEL_OUT_MONO;
? ? ? ? ? ? //錄音時使用16bit,所以播放時同樣采用該方式
? ? ? ? ? ? int audioFormat=AudioFormat.ENCODING_PCM_16BIT;
? ? ? ? ? ? //流模式
? ? ? ? ? ? int mode= AudioTrack.MODE_STREAM;
? ? ? ? ? ? //計算最小buffer大小
? ? ? ? ? ? int minBufferSize=AudioTrack.getMinBufferSize(sampleRate,channelConfig,audioFormat);
? ? ? ? ? ? //構造AudioTrack? 不能小于AudioTrack的最低要求,也不能小于我們每次讀的大小
? ? ? ? ? ? AudioTrack audioTrack=new AudioTrack(streamType,sampleRate,channelConfig,audioFormat,
? ? ? ? ? ? ? ? ? ? Math.max(minBufferSize,BUFFER_SIZE),mode);
? ? ? ? ? ? //從文件流讀數據? ? ? ? ? ? FileInputStream inputStream=null;
? ? ? ? ? ? try{
? ? ? ? ? ? ? ? //循環讀數據,寫到播放器去播放
? ? ? ? ? ? ? ? inputStream=new FileInputStream(audioFile);
? ? ? ? ? ? ? ? //循環讀數據,寫到播放器去播放
? ? ? ? ? ? ? ? int read;
? ? ? ? ? ? ? ? //只要沒讀完,循環播放
? ? ? ? ? ? ? ? while ((read=inputStream.read(mBuffer))>0){
? ? ? ? ? ? ? ? ? ? Log.i("Tag8","read:"+read);
? ? ? ? ? ? ? ? ? ? int ret=audioTrack.write(mBuffer,0,read);
? ? ? ? ? ? ? ? ? ? //檢查write的返回值,處理錯誤
? ? ? ? ? ? ? ? ? ? switch (ret){
? ? ? ? ? ? ? ? ? ? ? ? case AudioTrack.ERROR_INVALID_OPERATION:
? ? ? ? ? ? ? ? ? ? ? ? case AudioTrack.ERROR_BAD_VALUE:
? ? ? ? ? ? ? ? ? ? ? ? case AudioManager.ERROR_DEAD_OBJECT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? playFail();
? ? ? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }catch (Exception e){
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? //讀取失敗
? ? ? ? ? ? ? ? playFail();
? ? ? ? ? ? }finally {
? ? ? ? ? ? ? ? mIsPlaying=false;
? ? ? ? ? ? ? ? //關閉文件輸入流
? ? ? ? ? ? ? ? if(inputStream !=null){
? ? ? ? ? ? ? ? ? ? closeStream(inputStream);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //播放器釋放
? ? ? ? ? ? ? ? resetQuietly(audioTrack);
? ? ? ? ? ? }
? ? ? ? ? ? //循環讀數據,寫到播放器去播放
? ? ? ? ? ? //錯誤處理,防止閃退? ? ? ? }
? ? }
? ? /**
? ? ?* 關閉輸入流
? ? ?* @paraminputStream
? ? ?*/
? ? private void closeStream(FileInputStream inputStream){
? ? ? ? try {
? ? ? ? ? ? inputStream.close();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }

? ? private void resetQuietly(AudioTrack audioTrack){
? ? ? ? try{
? ? ? ? ? ? audioTrack.stop();
? ? ? ? ? ? audioTrack.release();
? ? ? ? }catch (Exception e){
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }

? ? /**
? ? ?* 播放失敗
? ? ?*/
? ? private void playFail() {
? ? ? ? mHandler.post(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? tv_stream_msg.setText("播放失敗");
? ? ? ? ? ? }
? ? ? ? });
? ? }

? ? @Override
? ? protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? if (mExecutorService != null) {
? ? ? ? ? ? mExecutorService.shutdownNow();
? ? ? ? }
? ? ? ? if (mAudioRecord != null) {
? ? ? ? ? ? mAudioRecord.stop();
? ? ? ? ? ? mAudioRecord.release();
? ? ? ? ? ? mAudioRecord = null;
? ? ? ? }
? ? }
}

xml布局文件:

<?xml version="1.0" encoding="utf-8"?>

< LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
?xmlns:tools="http://schemas.android.com/tools"
?android:id="@+id/activity_stream"
?android:layout_width="match_parent"
?android:layout_height="match_parent"
?android:padding="2dp"
?android:orientation="vertical"
?tools:context="com.example.amelon.myapplication.StreamActivity">

< LinearLayout
?android:layout_width="match_parent"
?android:layout_height="0dp"
?android:layout_weight="3"
?android:orientation="vertical" >

< Button
?android:onClick="recorderaudio"
?android:id="@+id/bt_stream_recorder"
?android:layout_width="wrap_content"
?android:layout_height="wrap_content"
?android:background="#50000000"
?android:layout_margin="10dp"
?android:textSize="24sp"
?android:textColor="#fff"
?android:padding="10dp"
?android:text="開始錄音" />

< Button
?android:onClick="player"
?android:layout_width="wrap_content"
?android:layout_height="wrap_content"
?android:background="#50000000"
?android:layout_margin="10dp"
?android:textSize="24sp"
?android:textColor="#fff"
?android:padding="10dp"
?android:text="播 放" />

< /LinearLayout>

< TextView
?android:id="@+id/tv_stream_msg"
?android:layout_weight="7"
?android:layout_width="match_parent"
?android:layout_height="wrap_content"
?android:textSize="24sp"
?android:padding="10dp"
?android:text="錄音結果" />

< /LinearLayout>

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,813評論 25 708
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,497評論 0 17
  • This is the jar of love 我承認之前的情感都是輕率而不夠真誠的。真正的感情應該是我聯系你,你...
    韋雄閱讀 1,449評論 3 0
  • 無意中翻了翻微信通訊錄里很久不聯系的朋友,打開她們的朋友圈,卻意外的發現沒有任何東西,我的第一反應就是她們是不是把...
    司夕閱讀 404評論 0 0