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