这两天项目中要做一个音频录制与播放的功能,大家可以参考一下 QQ聊天中的录音功能,我基本就是仿照这个功能来做的。
之前也没有接触音频模块,这两天通过一个小demo彻底明白.
不明白的地方都有注释。效果图如下
package com.king_mi.demo;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
/**
* 音频播放与录制
*/
public class RecordActivity extends BaseActivity implements View.OnClickListener {
private MediaRecorder mMediaRecorder = null;
private MediaPlayer mPlayer = null;
private TextView tvRecordTime, tvRecordTag;
private ImageView ivControl, ivSubmit, ivRecordAgain;
public String voicePath = ""; //录制的文件路径
private static final int MAX_TIME = 5; //录制最长时间
private int voiceTime = 0; // 录音时长
private int playTime = 0; // 播音时长
private double voiceSize; //voice体积大小
private boolean isRunning = false; // 定义一个布尔类型的变量来监控是否正在录音
private boolean isRecordOk = false; //是否已经录制好了
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.zx_detail_record_audio);
initView();
}
private void initView() {
tvRecordTime = (TextView) findViewById(R.id.tv_record_time);
tvRecordTag = (TextView) findViewById(R.id.tv_record_tag);
tvRecordTag.setText("语音回答,最多录制60秒,点击开始");
ivRecordAgain = (ImageView) findViewById(R.id.iv_record_again);
ivRecordAgain.setOnClickListener(this);
ivRecordAgain.setEnabled(false);
ivSubmit = (ImageView) findViewById(R.id.iv_submit);
ivSubmit.setOnClickListener(this);
ivSubmit.setEnabled(false);
ivControl = (ImageView) findViewById(R.id.iv_control);
ivControl.setOnClickListener(this);
}
//开始录音
private void startRecord() {
tvRecordTag.setText("录音中...点击录音停止");
ivControl.setImageResource(R.drawable.zx_detail_btn_stop);
hanlder.postDelayed(runnable, 1000);
mMediaRecorder = null; //这里必须要释放,否则重复播放的时候会出现异常
if (mMediaRecorder == null) {
mMediaRecorder = new MediaRecorder(); // 判断是都为空 如果为空new 一个对象
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置输入源为麦克风
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // 设置输出格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置音频的编码
voicePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/test_Audio.mp3"; // 创建一个临时文件来存储音频
mMediaRecorder.setOutputFile(voicePath);
try {
mMediaRecorder.prepare(); // 准备录音
} catch (Exception e) {
e.printStackTrace();
}
mMediaRecorder.start(); // 开启录音
isRunning = true; // 正在录音
}
}
//停止录音
private void stopRecord() {
if (isRunning) { // 如果正在录音
mMediaRecorder.stop(); // 停止录音
mMediaRecorder.release(); // 释放资源
}
ivRecordAgain.setEnabled(true);
ivSubmit.setEnabled(true);
tvRecordTag.setText("播放试听");
hanlder.removeCallbacks(runnable);
ivControl.setImageResource(R.drawable.zx_detail_btn_play);
isRecordOk = true;
isRunning = false;
}
//开始播放
private void starPlaying() {
ivRecordAgain.setEnabled(false);
ivSubmit.setEnabled(false);
playTime = voiceTime;
tvRecordTime.setText(String.valueOf(playTime));
tvRecordTag.setText("播放中...点击停止播放");
ivControl.setImageResource(R.drawable.zx_detail_btn_stop);
mPlayer = null;//这里必须要释放,
if (null == mPlayer) {
mPlayer = new MediaPlayer();
try {
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
tvRecordTime.setText(String.valueOf(0)); //有时候时间表示不同步,强制设为0
stopPlaying();
}
});
mPlayer.setDataSource(voicePath); // 设置要播放的文件
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
e.printStackTrace();
mPlayer.release();
}
hanlder.postDelayed(runnable, 1000);
}
}
// 停止播放
private void stopPlaying() {
ivRecordAgain.setEnabled(true);
ivSubmit.setEnabled(true);
ivControl.setImageResource(R.drawable.zx_detail_btn_play);
hanlder.removeCallbacks(runnable);
if (mPlayer == null) {
Toast.makeText(this, "您还没播放任何音频", Toast.LENGTH_SHORT).show();
} else {
tvRecordTag.setText("播放试听");
mPlayer.stop();
Toast.makeText(this, "已终止播放", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.iv_submit:
BToast.show(mActivity, "准备提交数据了...");
break;
case R.id.iv_record_again:
ivControl.setImageResource(R.drawable.zx_detail_btn_play);
ivRecordAgain.setEnabled(false);
ivSubmit.setEnabled(false);
voicePath = null;
isRecordOk = false;
voiceTime = 0;
tvRecordTime.setText(String.valueOf(voiceTime));
break;
case R.id.iv_control:
if (!isRecordOk) { //没有录制好,就录制
if (!isRunning) {
startRecord();
} else {
stopRecord();
}
} else { //录制好了,就播放
if (null != mPlayer && mPlayer.isPlaying()) {
stopPlaying();
} else {
starPlaying();
}
}
break;
}
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
hanlder.postDelayed(this, 1000);
if (!isRecordOk) { //没有录制好,就录制,且控制录制的时候时间
voiceTime++;
tvRecordTime.setText(String.valueOf(voiceTime));
if (voiceTime >= MAX_TIME) {
stopRecord();
}
} else { //录制好了,就播放,且控制播放的时候时间
if (playTime < 0) {
stopRecord();
}
playTime--;
tvRecordTime.setText(String.valueOf(playTime));
}
}
};
private Handler hanlder = new Handler();
@Override
protected void onDestroy() {
super.onDestroy();
mPlayer.release(); // Now the object cannot be reused
mPlayer = null;
mMediaRecorder.release(); // Now the object cannot be reused
mMediaRecorder = null;
}
}