Android应用如果需要录入用户语音,则有两种方式:一种是简单的方式;一种是稍微复杂的方式。\(^o^)/~
简单的方式
通过标准的Intent,和启动摄像头拍照一样,代码如下:
Java
private void setting() {
Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
final String EXTRA_MAX_BYTES = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES;
long bytes = (long) (5900 * 4L);
//设置录音文件的大小,10K左右大小在默认比特率下可以录音6秒左右
//注意:该值为long型的,否则该设置不起作用
intent.putExtra(EXTRA_MAX_BYTES, bytes);
if (isAvailable(getApplicationContext(), intent)) {
startActivityForResult(intent, REQUESTCODE_RECORDING);
}
}
1
2
3
4
5
6
7
8
9
10
11
privatevoidsetting(){
Intentintent=newIntent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
finalStringEXTRA_MAX_BYTES=android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES;
longbytes=(long)(5900*4L);
//设置录音文件的大小,10K左右大小在默认比特率下可以录音6秒左右
//注意:该值为long型的,否则该设置不起作用
intent.putExtra(EXTRA_MAX_BYTES,bytes);
if(isAvailable(getApplicationContext(),intent)){
startActivityForResult(intent,REQUESTCODE_RECORDING);
}
}
不过在使用之前,需要检查下该Intent Action对应的功能是否可用,放置没有app可以响应该Intent照成程序Crash:
Java
/**检查该intent是否可用*/
public static boolean isAvailable(Context ctx, Intent intent) {
final PackageManager mgr = ctx.getPackageManager();
List list = mgr.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
1
2
3
4
5
6
/**检查该intent是否可用*/
publicstaticbooleanisAvailable(Contextctx,Intentintent){
finalPackageManagermgr=ctx.getPackageManager();
Listlist=mgr.queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY);
returnlist.size()>0;
}
然后在 onActivityResult 中处理返回的结果:
Java
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUESTCODE_RECORDING) {
if (resultCode == RESULT_OK) {
// 录音成功,获取录音文件的URI
Uri audioUri = intent.getData();
} else {
// 录音失败,有可能是用户点击了取消
}
} else {
super.onActivityResult(requestCode, resultCode, intent);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentintent){
if(requestCode==REQUESTCODE_RECORDING){
if(resultCode==RESULT_OK){
// 录音成功,获取录音文件的URI
UriaudioUri=intent.getData();
}else{
// 录音失败,有可能是用户点击了取消
}
}else{
super.onActivityResult(requestCode,resultCode,intent);
}
}
由于返回的结果是一个URI,录音文件保存在设备的SDCard根目录中,这种情况是很不好的,如果用户录音了多次,发现SDCard根目录下面有一堆音频文件,用户会愤怒的。所以我们需要把这些录音文件复制到自己应用的数据目录中去。
Java
// 录音成功,获取录音文件的URI
Uri audioUri = intent.getData();
String sourcePath = getRealPathFromURI(audioUri);
File root = Environment.getExternalStorageDirectory();
String destPath = root.getPath() + File.separator + "newName.txt";
File sourceF = new File(sourcePath);
try {
sourceF.renameTo(new File(destPath));
} catch (Exception e) {
Toast.makeText(this, "移动文件出错:" + e.getMessage(), Toast.LENGTH_LONG).show();
}
/**
* 来源:
* http://stackoverflow.com/questions/3401579/get-filename-and-path-from-
* uri-from-mediastore
*/
public String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Audio.Media.DATA };
@SuppressWarnings("deprecation")
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
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
// 录音成功,获取录音文件的URI
UriaudioUri=intent.getData();
StringsourcePath=getRealPathFromURI(audioUri);
Fileroot=Environment.getExternalStorageDirectory();
StringdestPath=root.getPath()+File.separator+"newName.txt";
FilesourceF=newFile(sourcePath);
try{
sourceF.renameTo(newFile(destPath));
}catch(Exceptione){
Toast.makeText(this,"移动文件出错:"+e.getMessage(),Toast.LENGTH_LONG).show();
}
/**
* 来源:
* http://stackoverflow.com/questions/3401579/get-filename-and-path-from-
* uri-from-mediastore
*/
publicStringgetRealPathFromURI(UricontentUri){
String[]proj={MediaStore.Audio.Media.DATA};
@SuppressWarnings("deprecation")
Cursorcursor=managedQuery(contentUri,proj,null,null,null);
intcolumn_index=cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
returncursor.getString(column_index);
}
注意不要忘记添加读写SDCard的权限:
如果您不确定需要保存到那个目录,则参考Android如何正确的保存文件
由于SoundRecorder Activity的intent-filter声明的问题,导致通过上面的方式 无法设置录音的格式。默认的录音格式为3gpp,如果您想使用AMR格式,则可以通过下面的方式来设置Intent:
Java
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.android.soundrecorder", "com.android.soundrecorder.SoundRecorder");
intent.setType(AUDIO_AMR);
final String EXTRA_MAX_BYTES = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES;
long bytes = (long) (5900 * 4L);
//设置录音文件的大小,10K左右大小在默认比特率下可以录音6秒左右
//注意:该值为long型的,否则该设置不起作用
intent.putExtra(EXTRA_MAX_BYTES, bytes);
1
2
3
4
5
6
7
8
Intentintent=newIntent(Intent.ACTION_MAIN);
intent.setClassName("com.android.soundrecorder","com.android.soundrecorder.SoundRecorder");
intent.setType(AUDIO_AMR);
finalStringEXTRA_MAX_BYTES=android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES;
longbytes=(long)(5900*4L);
//设置录音文件的大小,10K左右大小在默认比特率下可以录音6秒左右
//注意:该值为long型的,否则该设置不起作用
intent.putExtra(EXTRA_MAX_BYTES,bytes);
下面是在Galaxy Nexus手机中的录音界面:
稍微复杂的录音方式
如果您需要更多的控制录音的参数,则可以自己使用MediaRecorder 或者 AudioRecord 来实现,具体实现方式参考下面的连接:
MediaRecorder录音代码
AudioRecord 录音代码