【錄音】Android錄音--AudioRecord、MediaRecorder

    Android提供了兩個API用於實現錄音功能:android.media.AudioRecord、android.media.MediaRecorder。java

    網上有不少談論這兩個類的資料。如今大體總結下:android

一、AudioRecordgit

主要是實現邊錄邊播(AudioRecord+AudioTrack)以及對音頻的實時處理(如會說話的湯姆貓、語音)github

優勢:語音的實時處理,能夠用代碼實現各類音頻的封裝數組

缺點:輸出是PCM語音數據,若是保存成音頻文件,是不可以被播放器播放的,因此必須先寫代碼實現數據編碼以及壓縮app

示例:ide

使用AudioRecord類錄音,並實現WAV格式封裝。錄音20s,輸出的音頻文件大概爲3.5M左右(已寫測試代碼)post

二、MediaRecorder測試

已經集成了錄音、編碼、壓縮等,支持少許的錄音音頻格式,大概有.aac(API = 16) .amr .3gpui

優勢:大部分以及集成,直接調用相關接口便可,代碼量小

缺點:沒法實時處理音頻;輸出的音頻格式不是不少,例如沒有輸出mp3格式文件

示例:

使用MediaRecorder類錄音,輸出amr格式文件。錄音20s,輸出的音頻文件大概爲33K(已寫測試代碼)

三、音頻格式比較

WAV格式:錄音質量高,可是壓縮率小,文件大

AAC格式:相對於mp3,AAC格式的音質更佳,文件更小;有損壓縮;通常蘋果或者Android SDK4.1.2(API 16)及以上版本支持播放

AMR格式:壓縮比比較大,但相對其餘的壓縮格式質量比較差,多用於人聲,通話錄音

至於經常使用的mp3格式,使用MediaRecorder沒有該視頻格式輸出。一些人的作法是使用AudioRecord錄音,而後編碼成wav格式,再轉換成mp3格式

 

    再貼上一些測試工程。

功能描述:

一、點擊「錄音WAV文件」,開始錄音。錄音完成後,生成文件/sdcard/FinalAudio.wav

二、點擊「錄音AMR文件」,開始錄音。錄音完成後,生成文件/sdcard/FinalAudio.amr

三、點擊「中止錄音」,中止錄音,並顯示錄音輸出文件以及該文件大小。

 

大體代碼以下:

一、AudioRecord錄音,封裝成WAV格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
package  com.example.audiorecordtest;
 
import  java.io.File;
import  java.io.FileInputStream;
import  java.io.FileNotFoundException;
import  java.io.FileOutputStream;
import  java.io.IOException;
 
import  android.media.AudioFormat;
import  android.media.AudioRecord;
 
public  class  AudioRecordFunc {
     // 緩衝區字節大小 
     private  int  bufferSizeInBytes = 0 ;
     
     //AudioName裸音頻數據文件 ,麥克風
     private  String AudioName = ""
     
     //NewAudioName可播放的音頻文件 
     private  String NewAudioName = "" ;
     
     private  AudioRecord audioRecord; 
     private  boolean  isRecord = false ; // 設置正在錄製的狀態 
     
     
     private  static  AudioRecordFunc mInstance;
          
     private  AudioRecordFunc(){
         
     }  
     
     public  synchronized  static  AudioRecordFunc getInstance()
     {
         if (mInstance == null )
             mInstance = new  AudioRecordFunc();
         return  mInstance;
     }
     
     public  int  startRecordAndFile() {
         //判斷是否有外部存儲設備sdcard
         if (AudioFileFunc.isSdcardExit())
         {
             if (isRecord)
             {
                 return  ErrorCode.E_STATE_RECODING;
             }
             else
             {
                 if (audioRecord == null )
                     creatAudioRecord();
                 
                 audioRecord.startRecording(); 
                 // 讓錄製狀態爲true 
                 isRecord = true
                 // 開啓音頻文件寫入線程 
                 new  Thread( new  AudioRecordThread()).start(); 
                 
                 return  ErrorCode.SUCCESS;
             }
             
         }      
         else
         {
             return  ErrorCode.E_NOSDCARD;           
         }      
 
    
   
     public  void  stopRecordAndFile() { 
         close(); 
     }
     
     
     public  long  getRecordFileSize(){
         return  AudioFileFunc.getFileSize(NewAudioName);
     }
     
   
     private  void  close() { 
         if  (audioRecord != null ) { 
             System.out.println( "stopRecord" ); 
             isRecord = false ; //中止文件寫入 
             audioRecord.stop(); 
             audioRecord.release(); //釋放資源 
             audioRecord = null
        
     }
     
     
     private  void  creatAudioRecord() { 
         // 獲取音頻文件路徑
         AudioName = AudioFileFunc.getRawFilePath();
         NewAudioName = AudioFileFunc.getWavFilePath();
         
         // 得到緩衝區字節大小 
         bufferSizeInBytes = AudioRecord.getMinBufferSize(AudioFileFunc.AUDIO_SAMPLE_RATE, 
                 AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT); 
         
         // 建立AudioRecord對象 
         audioRecord = new  AudioRecord(AudioFileFunc.AUDIO_INPUT, AudioFileFunc.AUDIO_SAMPLE_RATE, 
                 AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes); 
     }
     
     
     class  AudioRecordThread implements  Runnable { 
         @Override 
         public  void  run() { 
             writeDateTOFile(); //往文件中寫入裸數據 
             copyWaveFile(AudioName, NewAudioName); //給裸數據加上頭文件 
        
    
   
     /**
      * 這裏將數據寫入文件,可是並不能播放,由於AudioRecord得到的音頻是原始的裸音頻,
      * 若是須要播放就必須加入一些格式或者編碼的頭信息。可是這樣的好處就是你能夠對音頻的 裸數據進行處理,好比你要作一個愛說話的TOM
      * 貓在這裏就進行音頻的處理,而後從新封裝 因此說這樣獲得的音頻比較容易作一些音頻的處理。
      */ 
     private  void  writeDateTOFile() { 
         // new一個byte數組用來存一些字節數據,大小爲緩衝區大小 
         byte [] audiodata = new  byte [bufferSizeInBytes]; 
         FileOutputStream fos = null
         int  readsize = 0
         try 
             File file = new  File(AudioName); 
             if  (file.exists()) { 
                 file.delete(); 
            
             fos = new  FileOutputStream(file); // 創建一個可存取字節的文件 
         } catch  (Exception e) { 
             e.printStackTrace(); 
        
         while  (isRecord == true ) { 
             readsize = audioRecord.read(audiodata, 0 , bufferSizeInBytes); 
             if  (AudioRecord.ERROR_INVALID_OPERATION != readsize && fos!= null ) { 
                 try 
                     fos.write(audiodata); 
                 } catch  (IOException e) { 
                     e.printStackTrace(); 
                
            
        
         try  {
             if (fos != null )
                 fos.close(); // 關閉寫入流 
         } catch  (IOException e) { 
             e.printStackTrace(); 
        
    
   
     // 這裏獲得可播放的音頻文件 
     private  void  copyWaveFile(String inFilename, String outFilename) { 
         FileInputStream in = null
         FileOutputStream out = null
         long  totalAudioLen = 0
         long  totalDataLen = totalAudioLen + 36
         long  longSampleRate = AudioFileFunc.AUDIO_SAMPLE_RATE; 
         int  channels = 2
         long  byteRate = 16  * AudioFileFunc.AUDIO_SAMPLE_RATE * channels / 8
         byte [] data = new  byte [bufferSizeInBytes]; 
         try 
             in = new  FileInputStream(inFilename); 
             out = new  FileOutputStream(outFilename); 
             totalAudioLen = in.getChannel().size(); 
             totalDataLen = totalAudioLen + 36
             WriteWaveFileHeader(out, totalAudioLen, totalDataLen, 
                     longSampleRate, channels, byteRate); 
             while  (in.read(data) != - 1 ) { 
                 out.write(data); 
            
             in.close(); 
             out.close(); 
         } catch  (FileNotFoundException e) { 
             e.printStackTrace(); 
         } catch  (IOException e) { 
             e.printStackTrace(); 
        
    
   
     /**
      * 這裏提供一個頭信息。插入這些信息就能夠獲得能夠播放的文件。
      * 爲我爲啥插入這44個字節,這個還真沒深刻研究,不過你隨便打開一個wav
      * 音頻的文件,能夠發現前面的頭文件能夠說基本同樣哦。每種格式的文件都有
      * 本身特有的頭文件。
      */ 
     private  void  WriteWaveFileHeader(FileOutputStream out, long  totalAudioLen, 
             long  totalDataLen, long  longSampleRate, int  channels, long  byteRate) 
             throws  IOException { 
         byte [] header = new  byte [ 44 ]; 
         header[ 0 ] = 'R' ; // RIFF/WAVE header 
         header[ 1 ] = 'I'
         header[ 2 ] = 'F'
         header[ 3 ] = 'F'
         header[ 4 ] = ( byte ) (totalDataLen & 0xff ); 
         header[ 5 ] = ( byte ) ((totalDataLen >> 8 ) & 0xff ); 
         header[ 6 ] = ( byte ) ((totalDataLen >> 16 ) & 0xff ); 
         header[ 7 ] = ( byte ) ((totalDataLen >> 24 ) & 0xff ); 
         header[ 8 ] = 'W'
         header[ 9 ] = 'A'
         header[ 10 ] = 'V'
         header[ 11 ] = 'E'
         header[ 12 ] = 'f' ; // 'fmt ' chunk 
         header[ 13 ] = 'm'
         header[ 14 ] = 't'
         header[ 15 ] = ' '
         header[ 16 ] = 16 ; // 4 bytes: size of 'fmt ' chunk 
         header[ 17 ] = 0
         header[ 18 ] = 0
         header[ 19 ] = 0
         header[ 20 ] = 1 ; // format = 1 
         header[ 21 ] = 0
         header[ 22 ] = ( byte ) channels; 
         header[ 23 ] = 0
         header[ 24 ] = ( byte ) (longSampleRate & 0xff ); 
         header[ 25 ] = ( byte ) ((longSampleRate >> 8 ) & 0xff ); 
         header[ 26 ] = ( byte ) ((longSampleRate >> 16 ) & 0xff ); 
         header[ 27 ] = ( byte ) ((longSampleRate >> 24 ) & 0xff ); 
         header[ 28 ] = ( byte ) (byteRate & 0xff ); 
         header[ 29 ] = ( byte ) ((byteRate >> 8 ) & 0xff ); 
         header[ 30 ] = ( byte ) ((byteRate >> 16 ) & 0xff ); 
         header[ 31 ] = ( byte ) ((byteRate >> 24 ) & 0xff ); 
         header[ 32 ] = ( byte ) ( 2  * 16  / 8 ); // block align 
         header[ 33 ] = 0
         header[ 34 ] = 16 ; // bits per sample 
         header[ 35 ] = 0
         header[ 36 ] = 'd'
         header[ 37 ] = 'a'
         header[ 38 ] = 't'
         header[ 39 ] = 'a'
         header[ 40 ] = ( byte ) (totalAudioLen & 0xff ); 
         header[ 41 ] = ( byte ) ((totalAudioLen >> 8 ) & 0xff ); 
         header[ 42 ] = ( byte ) ((totalAudioLen >> 16 ) & 0xff ); 
         header[ 43 ] = ( byte ) ((totalAudioLen >> 24 ) & 0xff ); 
         out.write(header, 0 , 44 ); 
    
}

 

二、MediaRecorder錄音,輸出amr格式音頻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package  com.example.audiorecordtest;
 
import  java.io.File;
import  java.io.IOException;
 
import  android.media.MediaRecorder;
 
public  class  MediaRecordFunc { 
     private  boolean  isRecord = false ;
     
     private  MediaRecorder mMediaRecorder;
     private  MediaRecordFunc(){
     }
     
     private  static  MediaRecordFunc mInstance;
     public  synchronized  static  MediaRecordFunc getInstance(){
         if (mInstance == null )
             mInstance = new  MediaRecordFunc();
         return  mInstance;
     }
     
     public  int  startRecordAndFile(){
         //判斷是否有外部存儲設備sdcard
         if (AudioFileFunc.isSdcardExit())
         {
             if (isRecord)
             {
                 return  ErrorCode.E_STATE_RECODING;
             }
             else
             {
                 if (mMediaRecorder == null )
                     createMediaRecord();
                 
                 try {
                     mMediaRecorder.prepare();
                     mMediaRecorder.start();
                     // 讓錄製狀態爲true 
                     isRecord = true ;
                     return  ErrorCode.SUCCESS;
                 } catch (IOException ex){
                     ex.printStackTrace();
                     return  ErrorCode.E_UNKOWN;
                 }
             }
             
         }      
         else
         {
             return  ErrorCode.E_NOSDCARD;           
         }      
     }
     
     
     public  void  stopRecordAndFile(){
          close();
     }
     
     public  long  getRecordFileSize(){
         return  AudioFileFunc.getFileSize(AudioFileFunc.getAMRFilePath());
     }
     
     
     private  void  createMediaRecord(){
          /* ①Initial:實例化MediaRecorder對象 */
         mMediaRecorder = new  MediaRecorder();
         
         /* setAudioSource/setVedioSource*/
         mMediaRecorder.setAudioSource(AudioFileFunc.AUDIO_INPUT); //設置麥克風
         
         /* 設置輸出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default
          * THREE_GPP(3gp格式,H263視頻/ARM音頻編碼)、MPEG-四、RAW_AMR(只支持音頻且音頻編碼要求爲AMR_NB)
          */
          mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
          
          /* 設置音頻文件的編碼:AAC/AMR_NB/AMR_MB/Default */
          mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
          
          /* 設置輸出文件的路徑 */
          File file = new  File(AudioFileFunc.getAMRFilePath());
          if  (file.exists()) { 
              file.delete(); 
          }
          mMediaRecorder.setOutputFile(AudioFileFunc.getAMRFilePath());
     }
     
     
     private  void  close(){
         if  (mMediaRecorder != null ) { 
             System.out.println( "stopRecord" ); 
             isRecord = false ;
             mMediaRecorder.stop(); 
             mMediaRecorder.release(); 
             mMediaRecorder = null ;
        
     }
}
1
  

三、其餘文件

AudioFileFunc.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package  com.example.audiorecordtest;
 
import  java.io.File;
 
import  android.media.MediaRecorder;
import  android.os.Environment;
 
public  class  AudioFileFunc {
     //音頻輸入-麥克風
     public  final  static  int  AUDIO_INPUT = MediaRecorder.AudioSource.MIC;
     
     //採用頻率
     //44100是目前的標準,可是某些設備仍然支持22050,16000,11025
     public  final  static  int  AUDIO_SAMPLE_RATE = 44100 //44.1KHz,廣泛使用的頻率  
     //錄音輸出文件
     private  final  static  String AUDIO_RAW_FILENAME = "RawAudio.raw" ;
     private  final  static  String AUDIO_WAV_FILENAME = "FinalAudio.wav" ;
     public  final  static  String AUDIO_AMR_FILENAME = "FinalAudio.amr" ;
     
     /**
      * 判斷是否有外部存儲設備sdcard
      * @return true | false
      */
     public  static  boolean  isSdcardExit(){      
         if  (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
             return  true ;
         else
             return  false ;
     }
         
     /**
      * 獲取麥克風輸入的原始音頻流文件路徑
      * @return
      */
     public  static  String getRawFilePath(){
         String mAudioRawPath = "" ;
         if (isSdcardExit()){
             String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath();
             mAudioRawPath = fileBasePath+ "/" +AUDIO_RAW_FILENAME;
         }  
         
         return  mAudioRawPath;
     }
     
     /**
      * 獲取編碼後的WAV格式音頻文件路徑
      * @return
      */
     public  static  String getWavFilePath(){
         String mAudioWavPath = "" ;
         if (isSdcardExit()){
             String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath();
             mAudioWavPath = fileBasePath+ "/" +AUDIO_WAV_FILENAME;
         }
         return  mAudioWavPath;
     }
     
     
     /**
      * 獲取編碼後的AMR格式音頻文件路徑
      * @return
      */
     public  static  String getAMRFilePath(){
         String mAudioAMRPath = "" ;
         if (isSdcardExit()){
             String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath();
             mAudioAMRPath = fileBasePath+ "/" +AUDIO_AMR_FILENAME;
         }
         return  mAudioAMRPath;
     }  
     
     
     /**
      * 獲取文件大小
      * @param path,文件的絕對路徑
      * @return
      */
     public  static  long  getFileSize(String path){
         File mFile = new  File(path);
         if (!mFile.exists())
             return  - 1 ;
         return  mFile.length();
     }
 
}

 

四、其餘文件

ErrorCode.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package  com.example.audiorecordtest;
 
import  android.content.Context;
import  android.content.res.Resources.NotFoundException;
 
public  class  ErrorCode {
     public  final  static  int  SUCCESS = 1000 ;
     public  final  static  int  E_NOSDCARD = 1001 ;
     public  final  static  int  E_STATE_RECODING = 1002 ;
     public  final  static  int  E_UNKOWN = 1003 ;
     
     
     public  static  String getErrorInfo(Context vContext, int  vType) throws  NotFoundException
     {
         switch (vType)
         {
         case  SUCCESS:
             return  "success" ;
         case  E_NOSDCARD:
             return  vContext.getResources().getString(R.string.error_no_sdcard);
         case  E_STATE_RECODING:
             return  vContext.getResources().getString(R.string.error_state_record); 
         case  E_UNKOWN:
         default :
             return  vContext.getResources().getString(R.string.error_unknown);          
             
         }
     }
 
}

 

五、string.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<? xml  version="1.0" encoding="utf-8"?>
< resources >
 
     < string  name="app_name">AudioRecordTest</ string >
     < string  name="hello_world">測試AudioRecord,實現錄音功能</ string >
     < string  name="menu_settings">Settings</ string >
     < string  name="view_record_wav">錄音WAV文件</ string >
     < string  name="view_record_amr">錄音AMR文件</ string >
     < string  name="view_stop">中止錄音</ string >
     
     < string  name="error_no_sdcard">沒有SD卡,沒法存儲錄音數據</ string >
     < string  name="error_state_record">正在錄音中,請先中止錄音</ string >
     < string  name="error_unknown">沒法識別的錯誤</ string >
 
</ resources >

 

六、主程序MainActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
package com.example.audiorecordtest;
 
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
 
public class MainActivity extends Activity {
     private final static int FLAG_WAV = 0;
     private final static int FLAG_AMR = 1;
     private int mState = -1;    //-1:沒再錄製,0:錄製wav,1:錄製amr
     private Button btn_record_wav;
     private Button btn_record_amr;
     private Button btn_stop;
     private TextView txt;
     private UIHandler uiHandler;
     private UIThread uiThread;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         findViewByIds();
         setListeners();
         init();
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         // Inflate the menu; this adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.activity_main, menu);
         return true;
     }
     private void findViewByIds(){
         btn_record_wav = (Button)this.findViewById(R.id.btn_record_wav);
         btn_record_amr = (Button)this.findViewById(R.id.btn_record_amr);
         btn_stop = (Button)this.findViewById(R.id.btn_stop);
         txt = (TextView)this.findViewById(R.id.text);
     }
     private void setListeners(){
         btn_record_wav.setOnClickListener(btn_record_wav_clickListener);
         btn_record_amr.setOnClickListener(btn_record_amr_clickListener);
         btn_stop.setOnClickListener(btn_stop_clickListener);
     }
     private void init(){
         uiHandler = new UIHandler();       
     }
     private Button.OnClickListener btn_record_wav_clickListener = new Button.OnClickListener(){
         public void onClick(View v){
             record(FLAG_WAV);
         }
     };
     private Button.OnClickListener btn_record_amr_clickListener = new Button.OnClickListener(){
         public void onClick(View v){
             record(FLAG_AMR);
         }
     };
     private Button.OnClickListener btn_stop_clickListener = new Button.OnClickListener(){
         public void onClick(View v){
             stop();    
         }
     };
     /**
      * 開始錄音
      * @param mFlag,0:錄製wav格式,1:錄音amr格式
      */
     private void record(int mFlag){
         if(mState != -1){
             Message msg = new Message();
             Bundle b = new Bundle();// 存放數據
             b.putInt("cmd",CMD_RECORDFAIL);
             b.putInt("msg", ErrorCode.E_STATE_RECODING);
             msg.setData(b);
 
             uiHandler.sendMessage(msg); // 向Handler發送消息,更新UI
             return;
         }
         int mResult = -1;
         switch(mFlag){       
         case FLAG_WAV:
             AudioRecordFunc mRecord_1 = AudioRecordFunc.getInstance();
             mResult = mRecord_1.startRecordAndFile();           
             break;
         case FLAG_AMR:
             MediaRecordFunc mRecord_2 = MediaRecordFunc.getInstance();
             mResult = mRecord_2.startRecordAndFile();
             break;
         }
         if(mResult == ErrorCode.SUCCESS){
             uiThread = new UIThread();
             new Thread(uiThread).start();
             mState = mFlag;
         }else{
             Message msg = new Message();
             Bundle b = new Bundle();// 存放數據
             b.putInt("cmd",CMD_RECORDFAIL);
             b.putInt("msg", mResult);
             msg.setData(b);
 
             uiHandler.sendMessage(msg); // 向Handler發送消息,更新UI
         }
     }
     /**
      * 中止錄音
      */
     private void stop(){
         if(mState != -1){
             switch(mState){
             case FLAG_WAV:
                 AudioRecordFunc mRecord_1 = AudioRecordFunc.getInstance();
                 mRecord_1.stopRecordAndFile();
                 break;
             case FLAG_AMR:
                 MediaRecordFunc mRecord_2 = MediaRecordFunc.getInstance();
                 mRecord_2.stopRecordAndFile();
                 break;
             }           
             if(uiThread != null){
                 uiThread.stopThread();
             }
             if(uiHandler != null)
                 uiHandler.removeCallbacks(uiThread);
             Message msg = new Message();
             Bundle b = new Bundle();// 存放數據
             b.putInt("cmd",CMD_STOP);
             b.putInt("msg", mState);
             msg.setData(b);
             uiHandler.sendMessageDelayed(msg,1000); // 向Handler發送消息,更新UI
             mState = -1;
         }
     }   
     private final static int CMD_RECORDING_TIME = 2000;
     private final static int CMD_RECORDFAIL = 2001;
     private final static int CMD_STOP = 2002;
     class UIHandler extends Handler{
         public UIHandler() {
         }
         @Override
         public void handleMessage(Message msg) {
             // TODO Auto-generated method stub
             Log.d("MyHandler", "handleMessage......");
             super.handleMessage(msg);
             Bundle b = msg.getData();
             int vCmd = b.getInt("cmd");
             switch(vCmd)
             {
             case CMD_RECORDING_TIME:
                 int vTime = b.getInt("msg");
                 MainActivity.this.txt.setText("正在錄音中,已錄製:"+vTime+" s");
                 break;
             case CMD_RECORDFAIL:
                 int vErrorCode = b.getInt("msg");
                 String vMsg = ErrorCode.getErrorInfo(MainActivity.this, vErrorCode);
                 MainActivity.this.txt.setText("錄音失敗:"+vMsg);
                 break;
             case CMD_STOP:               
                 int vFileType = b.getInt("msg");
                 switch(vFileType){
                 case FLAG_WAV:
                     AudioRecordFunc mRecord_1 = AudioRecordFunc.getInstance();
                     long mSize = mRecord_1.getRecordFileSize();
                     MainActivity.this.txt.setText("錄音已中止.錄音文件:"+AudioFileFunc.getWavFilePath()+"\n文件大小:"+mSize);
                     break;
                 case FLAG_AMR:                   
                     MediaRecordFunc mRecord_2 = MediaRecordFunc.getInstance();
                     mSize = mRecord_2.getRecordFileSize();
                     MainActivity.this.txt.setText("錄音已中止.錄音文件:"+AudioFileFunc.getAMRFilePath()+"\n文件大小:"+mSize);
                     break;
                 }
                 break;
             default:
                 break;
             }
         }
     };
     class UIThread implements Runnable {       
         int mTimeMill = 0;
         boolean vRun = true;
         public void stopThread(){
             vRun = false;
         }
         public void run() {
             while(vRun){
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
                 mTimeMill ++;
                 Log.d("thread", "mThread........"+mTimeMill);
                 Message msg = new Message();
                 Bundle b = new Bundle();// 存放數據
                 b.putInt("cmd",CMD_RECORDING_TIME);
                 b.putInt("msg", mTimeMill);
                 msg.setData(b);
 
                 MainActivity.this.uiHandler.sendMessage(msg); // 向Handler發送消息,更新UI
             }
 
         }
     }
 
}
做者: 風傾清凌
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利.
 

個人github地址:https://github.com/dongweiq/study

歡迎關注,歡迎star o(∩_∩)o 。有什麼問題請郵箱聯繫 dongweiqmail@gmail.com qq714094450

相關文章
相關標籤/搜索