android语音聊天的简单实现,本博客分为两部
分来做讲解,第一部分是:录音实现,第二部分是播放语音的实现。
一、录音
在android中实现录音功能,提供了两个类都可以实现语音的功能。MediaRecorder和AudioRecord两个类,本文主要讲解用MediaRecorder实现的录音功能。其实要想实现录音很简单,MediaRecorder就能实现,并且代码也很简单。但是难就难在MediaRecorder没有提供暂停的功能,那么暂停的功能,就只能我们自己来实现了。
<span style="font-size:18px;color:#3366ff;">/**在这里我设置输出的音频文件格式为.amr的文件格式,那是因为.amr的音频文件其头文件大小都是固定的,6个字节,这样方便我们后续做暂停录音,最好合并音频文件
* 开始录音
*/
public void start() {
if(isRecording){ // 正在录音
Log.e("AudioManager", "系统录音中!");
return;
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置音频来源为 麦克风
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); // 定义输出格式为.amr
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置编码器
// 以当前时间的long型作为音频文件的名称
String fileName = System.currentTimeMillis() + ".amr";
fileNames.add(fileName); // 添加文件名称到集合中
recorder.setOutputFile(fileUtils.getFileDirector() + File.separator + fileName); // 设置录音的输出文件
try {
recorder.prepare(); // 准备
recorder.start(); // 开始录音
isRecording = true; // 标识正在进行录音
schedule = Executors.newScheduledThreadPool(5); // 构建定时任务
// 每隔1秒执行一次
schedule.scheduleWithFixedDelay(new TimerTask(), 1, 1, TimeUnit.SECONDS);
} catch (IOException e) {
e.printStackTrace();
}
}</span>
<span style="font-size:18px;color:#3333ff;">/**最后是停止录音,停止录音的时候,除了要恢复默认状态外,还要合并之前暂停的音频文件为一个文件。
* 暂停录音
*/
public void pause() {
if(isRecording) { // 如果正在进行录音
if(!schedule.isShutdown()) {
schedule.shutdown(); // 终止所有的线程
}
recorder.stop(); // 停止录音
recorder.reset(); // 重置为初始状态
isRecording = false; // 标识已经停止录音
}else{
Log.e("AudioManager", "已经停止录音了,不需要重复停止!");
}
}</span>
<span style="font-size:18px;color:#000066;"> /**合并音频文件
* 停止录音
*/
public void stop() {
// 如果正在进行录音,则停止录音
if(isRecording) {
if(!schedule.isShutdown()) {
schedule.shutdown(); // 终止所有的线程
}
recorder.stop(); // 停止录音
recorder.reset(); // 重置为初始状态
isRecording = false; // 标识已经停止录音
times = 0; // 重置录音时间为0
}else{
Log.e("AudioManager", "已经停止录音了,不需要重复停止!");
}
mergeFiles(); // 合并音频文件
}</span>
<span style="font-size:18px;color:#3366ff;"> /**
* 合并所有的音频文件为一个音频文件(后缀名为.amr)
* 由于.amr的文件的头文件大小固定都是6个字节
* 所以合并的时候,只需要把除去第一个文件外的头文件(6个字节)然后拼接在一起
* @param fileNames 文件名称集合
* @return 合并后的文件File
*/
public File mergeAudioFiles(List<String> fileNames) throws IOException {
// 创建临时文件保存合并后的文件
tempFile = new File(file, System.currentTimeMillis() + "_temp.amr");
if(tempFile.exists()){ // 如果文件存在,则删除文件
tempFile.delete(); // 删除文件
}
tempFile.createNewFile(); // 重新创建新文件
// 构建文件输出流,用来写数据到文件中
FileOutputStream os = new FileOutputStream(tempFile);
RandomAccessFile raf;
// 循环依次读取每一个文件的音频信息
for (int i = 0; i < fileNames.size(); i++) {
// 以只读模式打开文件流
raf = new RandomAccessFile(new File(file, fileNames.get(i)), "r");
// 如果不是第一个文件,则跳过文件头,直接读取音频帧信息
if(i != 0) {
raf.seek(6); // 跳过文件头,.amr文件头为固定的6个字节
}
// 构建临时缓存数组
byte[] bytes = new byte[1024];
int len; // 保存每次读取的数据长度
// 循环依次读取数据
while ((len = raf.read(bytes)) != -1) {
// 将读取的数据写入文件
os.write(bytes, 0, len);
}
raf.close(); // 关闭流
}
// 数据写入完成后
os.close(); // 关闭流
return tempFile;
}</span>