最近由于项目的需要,需要在app中做一个小的录音模块,在录完音后可以进行播放,由于是新手,做的时候遇到了很多的问题,下面就将我写的demo记下来,作为笔记,希望对大家有点帮助!
一.首先是Mediarecorder的部分进行录音:
1.按照google文档的对录音进行初始设置,代码如下:
private void startRecorder() {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
recAudioFile = Utils.createImageFile(this,".amr");
if (!recAudioFile.exists()) {
recAudioFile.mkdirs();
}
mMediaRecorder.setOutputFile(recAudioFile.getAbsolutePath());
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
}
这段代码当中的createImageFile是一个更具时间戳进行命名的字符串生成工具,为的是录制的音频文件名不冲突(这个方法来至google待用系统相机,大家可以去查看下!)。
2.调用上面的代码就可以进行录音了,接下来就是停止录音的代码:
private void stopRecorder() {
if (recAudioFile != null && mMediaRecorder != null) {
mMediaRecorder.stop();
mMediaRecorder.release();
}
}
这段代码就相对简单了,调用此方法我们录的文件就被保存下来了!
3.接下就是我想说的了,就是在录音的过程中实现时间的滚动:
由于mediarecorder里面没有对录音的时间有一个接口回调,我们不能直接实现时间的改变,所以就需要我们写一个子线程,在开始的录音的时候通过handler不断向主线程中发送message来改变时间。
private class UpdateThread extends Thread {
@Override
public void run() {
while (isRecording) {
try {
new Thread().sleep(THREAD_DELAYED);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(UPDATE_TIME_RECORD);
}
}
}
这里我们通过一个标志位来执行线程,isRecorder在录音开始的时候置为true;THREAD_DELAYED是我们间隔多久发一次消息,测试后我设置为100,效果比较理想。
接下来我贴出的就是主线程中处理handler发送来消息的代码,这里面包括了我后面要说的播放录音的代码:
private class MHandler extends Handler {
SimpleDateFormat format = new SimpleDateFormat("mm:ss");
@Override
public void handleMessage(Message msg) {
try {
switch (msg.what) {
case UPDATE_TIME_RECORD:
long currentTimeMillis = System.currentTimeMillis();
String time = format.format(currentTimeMillis - start_time);
record_durationTV.setText(time);
break;
case UPDATE_TIME_PLAY:
UpdateTimeing playThread = new UpdateTimeing();
playThread.start();
break;
case UPDATE_PB_PLAY:
int position = mMediaPlayer.getCurrentPosition();
record_playPB.setProgress(position);
record_total.setText(format.format(mMediaPlayer.getDuration()));
record_current.setText(format.format(position) + "/");
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
二.接下来就是mediaplayer,对录音文件进行播放了:
1.同样的,首先我们对mediaplayer进行初始化:
private void mediaPlayMode(String audioPath) {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mMediaPlayer.setDataSource(audioPath);
mMediaPlayer.prepare();
mMediaPlayer.start();
isPlaying = true;
handler.sendEmptyMessage(UPDATE_TIME_PLAY);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
record_pasueIB.setBackgroundResource(R.drawable.selector_video_play);
isPlaying = false;
isFinish = true;
handler.removeMessages(UPDATE_TIME_PLAY);
}
});
record_playPB.setMax(mMediaPlayer.getDuration());
} catch (IOException e) {
e.printStackTrace();
}
}
这里的代码和上面差不多,都是按照google的文档进行写的,值得注意的就是handler.removeMessage()这个方法,当我们在播放的过程中点击退出的时候,由于主线handlerMessager中还有代码需要mediaplaer的引用,但是在activity的destory方法中,我们已经将mediaplayer对象释放掉,所以会出现空指针的情况。
2.然后就是跟新进度条的线程代码:
private class UpdateTimeing extends Thread {
@Override
public void run() {
while (isPlaying) {
try {
new Thread().sleep(THREAD_DELAYED);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(UPDATE_PB_PLAY);
}
}
}
由于是第一次写学习笔记博客,有不足的地方希望大家指正,以后多多改进,有需要源码的同学可以私信我,下次准备写一篇使用meidaplayer加sufaceview实现视频的本地和在线播放的学习笔记(可以进行全屏切换)。