MediaRecorder.AudioSource音頻參數(shù)說明
MediaRecorder.AudioSource.MIC參數(shù)說明
其中第一個參數(shù)就是選擇錄音源的靶累,其可選參數(shù)如下:
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已實現(xiàn)大量的封裝浙垫,操作起來更加簡單,而AudioRecord使用起來更加靈活努释,能實現(xiàn)更多的功能。
1.AudioRecord(基于字節(jié)流錄音)?
優(yōu)點:可以實現(xiàn)語音的實時處理咬摇,進行邊錄邊播伐蒂,對音頻的實時處理。?
缺點:輸出的是PCM的語音數(shù)據(jù)肛鹏,如果保存成音頻文件是不能被播放器播放的逸邦。要用到AudioTrack這個去進行處理。
2.MediaRecorder(基于文件錄音)?
已集成了錄音在扰,編碼昭雌,壓縮等,支持少量的音頻格式文件健田。?
優(yōu)點:封裝度很高烛卧,操作簡單?
缺點:無法實現(xiàn)實時處理音頻,輸出的音頻格式少妓局。
功能實現(xiàn):MediaRecorder(這里需要注意总放,無論錄制還是播放都是一個耗時操作,需要在非主線程中去操作)
//實現(xiàn)觸摸錄音好爬,松開錄音結束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;
? ? ? ? ? ? }
? ? ? ? });
開啟一個單線程去實現(xiàn)錄音功能局雄,及失敗操作:
/**
? ? ?* 開啟錄音
? ? ?*/
? ? 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 {
? ? ? ? ? ? //創(chuàng)建MediaRecorder
? ? ? ? ? ? mMediaRecorder = new MediaRecorder();
? ? ? ? ? ? //創(chuàng)建錄音文件
? ? ? ? ? ? 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系統(tǒng)都支持的適中采樣的頻率
? ? ? ? ? ? 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;
? ? ? ? }
? ? ? ? //記錄開始錄音時間,用于統(tǒng)計時長穆桂,小于3秒中宫盔,錄音不發(fā)送? ? ? ? return true;
? ? }
停止錄音操作:
/**
?* 關閉錄音 *
?* @return*/
?private boolean doStop() {
? ? ? ? try {
? ? ? ? ? ? mMediaRecorder.stop();
? ? ? ? ? ? stopRecorderTime = System.currentTimeMillis();
? ? ? ? ? ? final int second = (int) (stopRecorderTime - startRecorderTime) / 1000;
? ? ? ? ? ? //按住時間小于3秒鐘,算作錄取失敗享完,不進行發(fā)送
? ? ? ? ? ? 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);
? ? ? ? ? ? //播放是否循環(huán)
? ? ? ? ? ? mediaPlayer.setLooping(false);
? ? ? ? ? ? //設置監(jiān)聽回調 播放完畢
? ? ? ? ? ? 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完整功能實現(xiàn)代碼:
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函數(shù)不具有線程安全性巍佑,因此用單線程? ? ? ? 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 {
? ? ? ? ? ? //創(chuàng)建MediaRecorder
? ? ? ? ? ? mMediaRecorder = new MediaRecorder();
? ? ? ? ? ? //創(chuàng)建錄音文件
? ? ? ? ? ? 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系統(tǒng)都支持的適中采樣的頻率
? ? ? ? ? ? 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;
? ? ? ? }
? ? ? ? //記錄開始錄音時間萤衰,用于統(tǒng)計時長,小于3秒中猜旬,錄音不發(fā)送? ? ? ? return true;
? ? }? ? /**
? ? ?* 關閉錄音? ? *
? ? ?* @return*/
? ? private boolean doStop() {
? ? ? ? try {
? ? ? ? ? ? mMediaRecorder.stop();
? ? ? ? ? ? stopRecorderTime = System.currentTimeMillis();
? ? ? ? ? ? final int second = (int) (stopRecorderTime - startRecorderTime) / 1000;
? ? ? ? ? ? //按住時間小于3秒鐘腻菇,算作錄取失敗,不進行發(fā)送? ? ? ? ? ? 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);
? ? ? ? ? ? //播放是否循環(huán)
? ? ? ? ? ? mediaPlayer.setLooping(false);
? ? ? ? ? ? //設置監(jiān)聽回調 播放完畢
? ? ? ? ? ? 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的功能實現(xiàn):?
實現(xiàn)一個點擊button進行錄音,再次點擊停止錄音功能
開啟錄音和停止錄音:
public void recorderaudio(View view) {
? ? ? ? if (mIsRecording) {
? ? ? ? ? ? bt_stream_recorder.setText("開始錄音");
? ? ? ? ? ? //在開始錄音中如果這個值沒有變false嘉竟,則一直進行邦危,當再次點擊變false時,錄音才停止
? ? ? ? ? ? mIsRecording = false;
? ? ? ? ? ? //執(zhí)行停止錄音邏輯舍扰,這塊不用下面代碼倦蚪,只需上面變換mIsRecording這個狀態(tài)就可以了,下面一直走while
? ? ? ? ? /*? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? stopRecorder();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });*/?
? ? ? ?} else {
? ? ? ? ? ? bt_stream_recorder.setText("停止錄音");
? ? ? ? ? ? //提交后臺任務边苹,執(zhí)行錄音邏輯
? ? ? ? ? ? mIsRecording = true;
? ? ? ? ? ? //提交后臺任務陵且,執(zhí)行錄音邏輯
? ? ? ? ? ? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? startRecorder();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? }
? ? }
開啟錄音:
/**
? ? ?* 開始錄音
? ? ?*/
? ? private void startRecorder() {
? ? ? ? // realeseRecorder();
? ? ? ? if (!dostart()) recorderFail();
? ? }
AudioRecord的配置及功能實現(xiàn)具體代碼:
private boolean dostart() {
? ? ? ? try {
? ? ? ? ? ? //記錄開始錄音時間
? ? ? ? ? ? startRecorderTime = System.currentTimeMillis();
? ? ? ? ? ? //創(chuàng)建錄音文件
? ? ? ? ? ? mAudioRecordFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
? ? ? ? ? ? ? ? ? ? "/recorderdemo/" + System.currentTimeMillis() + ".pcm");
? ? ? ? ? ? if (!mAudioRecordFile.getParentFile().exists())
? ? ? ? ? ? ? ? mAudioRecordFile.getParentFile().mkdirs();
? ? ? ? ? ? mAudioRecordFile.createNewFile();
? ? ? ? ? ? //創(chuàng)建文件輸出流
? ? ? ? ? ? mFileOutputStream = new FileOutputStream(mAudioRecordFile);
? ? ? ? ? ? //配置AudioRecord
? ? ? ? ? ? int audioSource = MediaRecorder.AudioSource.MIC;
? ? ? ? ? ? //所有android系統(tǒng)都支持
? ? ? ? ? ? int sampleRate = 44100;
? ? ? ? ? ? //單聲道輸入
? ? ? ? ? ? int channelConfig = AudioFormat.CHANNEL_IN_MONO;
? ? ? ? ? ? //PCM_16是所有android系統(tǒng)都支持的
? ? ? ? ? ? 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();
? ? ? ? ? ? //循環(huán)讀取數(shù)據(jù)慕购,寫入輸出流中
? ? ? ? ? ? while (mIsRecording) {
? ? ? ? ? ? ? ? //只要還在錄音就一直讀取
? ? ? ? ? ? ? ? int read = mAudioRecord.read(mBuffer, 0, BUFFER_SIZE);
? ? ? ? ? ? ? ? if(read<=0){
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? mFileOutputStream.write(mBuffer, 0, read);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //退出循環(huán),停止錄音茬底,釋放資源
? ? ? ? ? ? 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;
? ? ? ? //記錄結束時間,統(tǒng)計錄音時長
? ? ? ? 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);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? }
播放錄音具體實現(xiàn)最爬,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);
? ? ? ? ? ? //從文件流讀數(shù)據(jù)
? ? ? ? ? ? FileInputStream inputStream=null;
? ? ? ? ? ? try{
? ? ? ? ? ? ? ? //循環(huán)讀數(shù)據(jù)蒜鸡,寫到播放器去播放
? ? ? ? ? ? ? ? inputStream=new FileInputStream(audioFile);
? ? ? ? ? ? ? ? //循環(huán)讀數(shù)據(jù)胯努,寫到播放器去播放
? ? ? ? ? ? ? ? int read;
? ? ? ? ? ? ? ? //只要沒讀完牢裳,循環(huán)播放
? ? ? ? ? ? ? ? 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的功能實現(xiàn)完整代碼:
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("字節(jié)流錄音");
? ? ? ? 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;
? ? ? ? ? ? //執(zhí)行停止錄音邏輯,這塊不用下面代碼溉箕,只需上面變換mIsRecording這個狀態(tài)就可以了晦墙,下面一直走while
? ? ? ? ? /*? mExecutorService.submit(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? stopRecorder();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });*/
? ? ? ? } else {
? ? ? ? ? ? bt_stream_recorder.setText("停止錄音");
? ? ? ? ? ? //提交后臺任務,執(zhí)行錄音邏輯
? ? ? ? ? ? mIsRecording = true;
? ? ? ? ? ? //提交后臺任務肴茄,執(zhí)行錄音邏輯
? ? ? ? ? ? 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();
? ? ? ? ? ? //創(chuàng)建錄音文件
? ? ? ? ? ? mAudioRecordFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
? ? ? ? ? ? ? ? ? ? "/recorderdemo/" + System.currentTimeMillis() + ".pcm");
? ? ? ? ? ? if (!mAudioRecordFile.getParentFile().exists())
? ? ? ? ? ? ? ? mAudioRecordFile.getParentFile().mkdirs();
? ? ? ? ? ? mAudioRecordFile.createNewFile();
? ? ? ? ? ? //創(chuàng)建文件輸出流
? ? ? ? ? ? mFileOutputStream = new FileOutputStream(mAudioRecordFile);
? ? ? ? ? ? //配置AudioRecord
? ? ? ? ? ? int audioSource = MediaRecorder.AudioSource.MIC;
? ? ? ? ? ? //所有android系統(tǒng)都支持
? ? ? ? ? ? int sampleRate = 44100;
? ? ? ? ? ? //單聲道輸入
? ? ? ? ? ? int channelConfig = AudioFormat.CHANNEL_IN_MONO;
? ? ? ? ? ? //PCM_16是所有android系統(tǒng)都支持的
? ? ? ? ? ? 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();
? ? ? ? ? ? //循環(huán)讀取數(shù)據(jù),寫入輸出流中
? ? ? ? ? ? while (mIsRecording) {
? ? ? ? ? ? ? ? //只要還在錄音就一直讀取
? ? ? ? ? ? ? ? int read = mAudioRecord.read(mBuffer, 0, BUFFER_SIZE);
? ? ? ? ? ? ? ? if(read<=0){
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? mFileOutputStream.write(mBuffer, 0, read);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //退出循環(huán),停止錄音梅忌,釋放資源
? ? ? ? ? ? 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");
? ? ? ? //記錄結束時間,統(tǒng)計錄音時長
? ? ? ? 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);
? ? ? ? ? ? //從文件流讀數(shù)據(jù)? ? ? ? ? ? FileInputStream inputStream=null;
? ? ? ? ? ? try{
? ? ? ? ? ? ? ? //循環(huán)讀數(shù)據(jù),寫到播放器去播放
? ? ? ? ? ? ? ? inputStream=new FileInputStream(audioFile);
? ? ? ? ? ? ? ? //循環(huán)讀數(shù)據(jù)尤蒿,寫到播放器去播放
? ? ? ? ? ? ? ? int read;
? ? ? ? ? ? ? ? //只要沒讀完郑气,循環(huán)播放
? ? ? ? ? ? ? ? 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);
? ? ? ? ? ? }
? ? ? ? ? ? //循環(huán)讀數(shù)據(jù)腰池,寫到播放器去播放
? ? ? ? ? ? //錯誤處理尾组,防止閃退? ? ? ? }
? ? }
? ? /**
? ? ?* 關閉輸入流
? ? ?* @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>