Android實(shí)現(xiàn)錄音方法(仿微信語(yǔ)音、麥克風(fēng)錄音、發(fā)送語(yǔ)音、解決5.0以上BUG)
先給大家展示下效果圖,如果大家感覺(jué)不錯(cuò),請(qǐng)參考使用方法,
效果圖如下所示:
使用方法:
錄音工具類(lèi):AudioRecoderUtils.java,代碼如下:
public class AudioRecoderUtils { //文件路徑 private String filePath; //文件夾路徑 private String FolderPath; private MediaRecorder mMediaRecorder; private final String TAG = "fan"; public static final int MAX_LENGTH = 1000 * 60 * 10;// 最大錄音時(shí)長(zhǎng)1000*60*10; private OnAudioStatusUpdateListener audioStatusUpdateListener; /** * 文件存儲(chǔ)默認(rèn)sdcard/record */ public AudioRecoderUtils(){ //默認(rèn)保存路徑為/sdcard/record/下 this(Environment.getExternalStorageDirectory()+"/record/"); } public AudioRecoderUtils(String filePath) { File path = new File(filePath); if(!path.exists()) path.mkdirs(); this.FolderPath = filePath; } private long startTime; private long endTime; /** * 開(kāi)始錄音 使用amr格式 * 錄音文件 * @return */ public void startRecord() { // 開(kāi)始錄音 /* ①I(mǎi)nitial:實(shí)例化MediaRecorder對(duì)象 */ if (mMediaRecorder == null) mMediaRecorder = new MediaRecorder(); try { /* ②setAudioSource/setVedioSource */ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 設(shè)置麥克風(fēng) /* ②設(shè)置音頻文件的編碼:AAC/AMR_NB/AMR_MB/Default 聲音的(波形)的采樣 */ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); /* * ②設(shè)置輸出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式 * ,H263視頻/ARM音頻編碼)、MPEG-4、RAW_AMR(只支持音頻且音頻編碼要求為AMR_NB) */ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); filePath = FolderPath + TimeUtils.getCurrentTime() + ".amr" ; /* ③準(zhǔn)備 */ mMediaRecorder.setOutputFile(filePath); mMediaRecorder.setMaxDuration(MAX_LENGTH); mMediaRecorder.prepare(); /* ④開(kāi)始 */ mMediaRecorder.start(); // AudioRecord audioRecord. /* 獲取開(kāi)始時(shí)間* */ startTime = System.currentTimeMillis(); updateMicStatus(); Log.e("fan", "startTime" + startTime); } catch (IllegalStateException e) { Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage()); } catch (IOException e) { Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage()); } } /** * 停止錄音 */ public long stopRecord() { if (mMediaRecorder == null) return 0L; endTime = System.currentTimeMillis(); //有一些網(wǎng)友反應(yīng)在5.0以上在調(diào)用stop的時(shí)候會(huì)報(bào)錯(cuò),翻閱了一下谷歌文檔發(fā)現(xiàn)上面確實(shí)寫(xiě)的有可能會(huì)報(bào)錯(cuò)的情況,捕獲異常清理一下就行了,感謝大家反饋! try { mMediaRecorder.stop(); mMediaRecorder.reset(); mMediaRecorder.release(); mMediaRecorder = null; audioStatusUpdateListener.onStop(filePath); filePath = ""; }catch (RuntimeException e){ mMediaRecorder.reset(); mMediaRecorder.release(); mMediaRecorder = null; File file = new File(filePath); if (file.exists()) file.delete(); filePath = ""; } return endTime - startTime; } /** * 取消錄音 */ public void cancelRecord(){ try { mMediaRecorder.stop(); mMediaRecorder.reset(); mMediaRecorder.release(); mMediaRecorder = null; }catch (RuntimeException e){ mMediaRecorder.reset(); mMediaRecorder.release(); mMediaRecorder = null; } File file = new File(filePath); if (file.exists()) file.delete(); filePath = ""; } private final Handler mHandler = new Handler(); private Runnable mUpdateMicStatusTimer = new Runnable() { public void run() { updateMicStatus(); } }; private int BASE = 1; private int SPACE = 100;// 間隔取樣時(shí)間 public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) { this.audioStatusUpdateListener = audioStatusUpdateListener; } /** * 更新麥克狀態(tài) */ private void updateMicStatus() { if (mMediaRecorder != null) { double ratio = (double)mMediaRecorder.getMaxAmplitude() / BASE; double db = 0;// 分貝 if (ratio > 1) { db = 20 * Math.log10(ratio); if(null != audioStatusUpdateListener) { audioStatusUpdateListener.onUpdate(db,System.currentTimeMillis()-startTime); } } mHandler.postDelayed(mUpdateMicStatusTimer, SPACE); } } public interface OnAudioStatusUpdateListener { /** * 錄音中... * @param db 當(dāng)前聲音分貝 * @param time 錄音時(shí)長(zhǎng) */ public void onUpdate(double db,long time); /** * 停止錄音 * @param filePath 保存路徑 */ public void onStop(String filePath); } }
使用很簡(jiǎn)單,主要就是開(kāi)始錄音startRecord()、取消錄音cancelRecord()、結(jié)束錄音stopRecord()和錄音監(jiān)聽(tīng)setOnAudioStatusUpdateListener(),注意,取消錄音不保存文件,結(jié)束錄音會(huì)保存文件!
在布局文件中添加一個(gè)控件(任意一個(gè)都行)
<Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按住說(shuō)話" android:textColor="@android:color/white" android:id="@+id/button" android:background="@color/colorPrimary" />
在Activity中使用:
//當(dāng)前布局文件的根layout final RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl); mButton = (Button) findViewById(R.id.button); //PopupWindow的布局文件 final View view = View.inflate(this, R.layout.layout_microphone, null); final PopupWindowFactory mPop = new PopupWindowFactory(this,view); //PopupWindow布局文件里面的控件 mImageView = (ImageView) view.findViewById(R.id.iv_recording_icon); mTextView = (TextView) view.findViewById(R.id.tv_recording_time); mAudioRecoderUtils = new AudioRecoderUtils(); //錄音回調(diào) mAudioRecoderUtils.setOnAudioStatusUpdateListener(new AudioRecoderUtils.OnAudioStatusUpdateListener() { //錄音中....db為聲音分貝,time為錄音時(shí)長(zhǎng) @Override public void onUpdate(double db, long time) { //根據(jù)分貝值來(lái)設(shè)置錄音時(shí)話筒圖標(biāo)的上下波動(dòng),下面有講解 mImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100)); mTextView.setText(TimeUtils.long2String(time)); } //錄音結(jié)束,filePath為保存路徑 @Override public void onStop(String filePath) { Toast.makeText(MainActivity.this, "錄音保存在:" + filePath, Toast.LENGTH_SHORT).show(); mTextView.setText(TimeUtils.long2String(0)); } }); //Button的touch監(jiān)聽(tīng) mButton.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: mPop.showAtLocation(rl,Gravity.CENTER,0,0); mButton.setText("松開(kāi)保存"); mAudioRecoderUtils.startRecord(); break; case MotionEvent.ACTION_UP: mAudioRecoderUtils.stopRecord(); //結(jié)束錄音(保存錄音文件) // mAudioRecoderUtils.cancelRecord(); //取消錄音(不保存錄音文件) mPop.dismiss(); mButton.setText("按住說(shuō)話"); break; } return true; } });
總結(jié)
以上所述是小編給大家介紹的Android實(shí)現(xiàn)錄音方法(仿微信語(yǔ)音、麥克風(fēng)錄音、發(fā)送語(yǔ)音、解決5.0以上BUG),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android音頻錄制MediaRecorder之簡(jiǎn)易的錄音軟件實(shí)現(xiàn)代碼
- Android簡(jiǎn)單的利用MediaRecorder進(jìn)行錄音的實(shí)例代碼
- Android實(shí)現(xiàn)錄音功能實(shí)現(xiàn)實(shí)例(MediaRecorder)
- Android應(yīng)用開(kāi)發(fā):電話監(jiān)聽(tīng)和錄音代碼示例
- Android App調(diào)用MediaRecorder實(shí)現(xiàn)錄音功能的實(shí)例
- 詳解Android開(kāi)發(fā)錄音和播放音頻的步驟(動(dòng)態(tài)獲取權(quán)限)
- Android實(shí)現(xiàn)語(yǔ)音播放與錄音功能
- Android編程實(shí)現(xiàn)錄音及保存播放功能的方法【附demo源碼下載】
- Android開(kāi)發(fā)四大組件之實(shí)現(xiàn)電話攔截和電話錄音
- Android實(shí)現(xiàn)錄音聲波圖
相關(guān)文章
android多線程斷點(diǎn)下載-帶進(jìn)度條和百分比進(jìn)度顯示效果
下面小編就為大家?guī)?lái)一篇android多線程斷點(diǎn)下載-帶進(jìn)度條和百分比進(jìn)度顯示效果。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06Android利用CircleImageView實(shí)現(xiàn)圓形頭像的方法
這篇文章主要介紹了Android利用CircleImageView實(shí)現(xiàn)圓形頭像的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10搭建Android上的服務(wù)器 “實(shí)現(xiàn)隔空取物”的方法
本篇文章主要介紹了搭建Android上的服務(wù)器 “實(shí)現(xiàn)隔空取物”的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01Android定時(shí)器實(shí)現(xiàn)的幾種方式整理及removeCallbacks失效問(wèn)題解決
本文為大家詳細(xì)介紹下Android 定時(shí)器實(shí)現(xiàn)的幾種方式:Handler + Runnable、Timer的方式、Handle與線程的sleep(long )方法和removeCallbacks失效問(wèn)題如何解決2013-06-06SQLiteStudio優(yōu)雅調(diào)試Android手機(jī)數(shù)據(jù)庫(kù)Sqlite(推薦)
這篇文章主要介紹了SQLiteStudio優(yōu)雅調(diào)試Android手機(jī)數(shù)據(jù)庫(kù)Sqlite的相關(guān)資料,需要的朋友可以參考下2017-11-11Android的WebView與H5前端JS代碼交互的實(shí)例代碼
本篇文章主要介紹了Android的WebView與H5前端JS代碼交互的實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-07-07