Android自帶的錄音類MediaRecorder只有start和stop功能,既沒有pause功能也沒有seekto函數,所以我們要實現暫停功能需要自己動手。而暫停這個功能在很多地方是需要的,假設一個應用中有錄音這個功能,那么當電話打來的時候就需要使用暫停功能,並且在打完電話之后恢復錄音。(小米手機的原生錄音功能是在打進來電話的時候停止錄音)。
基本思想是,基於它只能開始和暫停(也有reset重置功能),那么我們只能在打進電話的同時調用stop方法,這個別無它法,然后我們要做的就是在電話打完恢復應用的時候就去重新開始一段錄音,等用戶點擊保存的時候,合並所有的錄音文件,這樣就可以實現暫停和繼續錄音的功能。借鑒以下兩篇博客以及自己的經驗做出闡述如下:
博客一:AMR文件格式分析
博客二:Android MediaRecorder實現暫停斷點錄音功能
前一篇博客描述了AMR文件的格式,我們可以確定,AMR文件的前6個字節(也就是文件頭)是一定一樣的。
這幅圖最前面的額框就是文件頭"#!AMR\n"的ASCII字符碼,我在MAC上使用Vim命令同樣可以看到該效果(包括換行),截圖如下:
左上角就是"#!AMR\n"的文件頭,這里換行了。
到這里就很簡單了,AMR文件的文件頭很簡單,什么都沒有,而我們要做的就是讀一個文件頭,將所有文件的音頻幀拼湊到一起,OK,繼續。
1 /** 合並所有的音頻文件 */ 2 public void mergeAllAmrFiles(){ 3 // 創建音頻文件,合並的文件放這里 4 File tempFile = new File(recordingFiles.get(0)); 5 File mergeFile = new File(tempFile.getParent() + File.separator + Utils.QIDUO_AMR + ".amr"); 6 Log.d("RECORD", "MERGE : " + mergeFile.getAbsolutePath()); 7 FileOutputStream fileOutputStream = null; 8 9 if(!mergeFile.exists()){ 10 try { 11 mergeFile.createNewFile(); 12 } catch (IOException e){ 13 // TODO Auto-generated catch block 14 e.printStackTrace(); 15 } 16 } 17 18 try { 19 fileOutputStream=new FileOutputStream(mergeFile); 20 } catch (IOException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } 24 25 //list里面為暫停錄音 所產生的幾段錄音文件的名字,中間幾段文件的減去前面的6個字節頭文件 26 for(int index = 0; index < recordingFiles.size(); index++){ 27 File file=new File(recordingFiles.get(index)); 28 Log.d("RECORD-PATH", recordingFiles.get(index) + file.length()); 29 try { 30 FileInputStream fileInputStream=new FileInputStream(file); 31 byte []myByte = new byte[fileInputStream.available()]; 32 //文件長度 33 int length = myByte.length; 34 Log.d("RECORD-LENGTH", length + ""); 35 36 //頭文件 37 if(index == 0){ 38 while(fileInputStream.read(myByte) != -1){ 39 fileOutputStream.write(myByte); 40 //fileOutputStream.write(myByte, 0,length); 41 } 42 } 43 44 //之后的文件,去掉前面6個字節(頭文件) 45 else{ 46 while(fileInputStream.read(myByte) != -1){ 47 fileOutputStream.write(myByte, 6, length - 6); 48 } 49 } 50 51 fileOutputStream.flush(); 52 fileInputStream.close(); 53 //合並之后刪除文件 54 //file.delete(); 55 } catch (Exception e) { 56 // TODO Auto-generated catch block 57 e.printStackTrace(); 58 } 59 } 60 61 //結束后關閉流 62 try { 63 fileOutputStream.flush(); 64 fileOutputStream.close(); 65 } catch (IOException e) { 66 // TODO Auto-generated catch block 67 e.printStackTrace(); 68 } 69 70 mSampleFile = mergeFile;//指向它,以便獲取地址 71 }
如上代碼,我們將除第一個文件的其余amr文件的文件頭全部去掉,拼湊在一起即可實現需要的功能。
注意點:
1 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 2 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);// 3 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
OutputStream一定要設置為"RAW_AMR"類型,THREE_GPP是一定不可以的!(文件格式完全不一樣,需要重新考察文件頭)