封装MediaRecorder录音工具类,实现微信录音效果,如图:
xml文件布局
录音工具类
/**
* Created by epdc on 2016/5/19.
* 录音工具类
*/
public class RecorderVoiceUtil {
public static String TAG = "epdc";
private static MediaRecorder mediaRecorder;
private static OnRecorderListener mListener;
private static String mOutputPath;
private static int mMaxDurationMs;
private static long startRecorderTime, endRecorderTime;
/**
* 开始录音
* @param outputPath
* @param maxDurationMs 录音最大时间
* @param listener
*/
public static void startRecorder(String outputPath, final int maxDurationMs, final OnRecorderListener listener) {
mListener = listener;
mOutputPath = outputPath;
mMaxDurationMs = maxDurationMs;
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
if (mMaxDurationMs <= 0) {
mediaRecorder.setMaxDuration(mMaxDurationMs);
}
mediaRecorder.setOutputFile(mOutputPath);
//第一次获取为0
mediaRecorder.getMaxAmplitude();
mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
mListener.onReachMax(mOutputPath, mMaxDurationMs);
stopRecorder();
}
}
});
mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
@Override
public void onError(MediaRecorder mr, int what, int extra) {
Log.e(TAG, "recorder error");
mListener.onError();
}
});
try {
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "recorder io error");
mListener.onError();
clear();
}
try {
mediaRecorder.start();
startRecorderTime = System.currentTimeMillis();
Log.i(TAG, "recorder start");
mListener.onStart();
} catch (RuntimeException e) {
e.printStackTrace();
//没有录音权限报错,6.0以下版本应该是这样
Log.e(TAG, "recorder permission error");
mListener.onPermissionError();
}
}
public static int getMaxAmplitude(){
return mediaRecorder.getMaxAmplitude();
}
/**
* 停止录音
*/
public static void stopRecorder() {
clear();
endRecorderTime = System.currentTimeMillis();
Log.i(TAG, "recorder success");
Log.i(TAG, "recorder voiceLength:"+(endRecorderTime - startRecorderTime));
mListener.onSuccess(mOutputPath, (endRecorderTime - startRecorderTime));
}
/**
* 取消录音
*/
public static void cancelRecorder() {
clear();
File file = new File(mOutputPath);
file.delete();
Log.w(TAG, "recorder cancel");
mListener.onCancel();
}
/**
* 释放资源
*/
private static void clear(){
//start后,一秒内stop录音会报RuntimeException
try {
mediaRecorder.stop();
} catch (RuntimeException e){
e.printStackTrace();
}
mediaRecorder.release();
mediaRecorder = null;
}
public interface OnRecorderListener {
void onReachMax(String outputPath, int maxDurationMs);
void onError();
void onPermissionError();
void onStart();
void onCancel();
void onSuccess(String outputPath, long voiceLength);
}
public static class SimpleRecorderListener implements OnRecorderListener {
@Override
public void onReachMax(String outputPath, int maxDurationMs) {
}
@Override
public void onError() {
}
@Override
public void onPermissionError() {
}
@Override
public void onStart() {
}
@Override
public void onCancel() {
}
@Override
public void onSuccess(String outputPath, long voiceLength) {
}
}
}
线程类,根据录音时声音大小更新界面
public class RecorderTask extends TimerTask {
public static String TAG = "epdc";
private final ImageView imageSay;
private Activity activity;
private boolean isCancel;
public RecorderTask(Activity activity, ImageView imageSay) {
this.activity = activity;
this.imageSay = imageSay;
}
@Override
public void run() {
if (!isCancel){
int maxAmplitude = RecorderVoiceUtil.getMaxAmplitude();
Log.i(TAG, "maxAmplitude为:" + maxAmplitude);
if (maxAmplitude > 1) {
final double db = 20 * Math.log10(maxAmplitude);
Log.i(TAG, "音量为:" + db);
Log.i(TAG, "imageSay:" + imageSay+", isCancel"+isCancel);
if (imageSay != null && !isCancel) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (db <= 15) {
imageSay.setImageResource(R.drawable.mic_1);
} else if (db > 15 && db <= 30) {
imageSay.setImageResource(R.drawable.mic_2);
} else if (db > 30 && db <= 45) {
imageSay.setImageResource(R.drawable.mic_3);
} else if (db > 45 && db <= 60) {
imageSay.setImageResource(R.drawable.mic_4);
} else if (db > 60 && db <= 75) {
imageSay.setImageResource(R.drawable.mic_5);
} else if (db > 75) {
imageSay.setImageResource(R.drawable.mic_6);
}
}
});
}
}
}
}
public boolean isCancel() {
return isCancel;
}
public void setCancel(boolean cancel) {
isCancel = cancel;
}
}
分贝计算参考链接http://blog.csdn.net/greatpresident/article/details/38402147
MainActivity的实现
/**
* Created by epdc on 2016/5/19.
*/
public class MainActivity extends AppCompatActivity {
String tag = "epdc";
Button btnSay;
ImageView imageSay;
TextView textUpCancel;
Context context;
GestureDetector gestureDetector;
RecorderVoiceUtil.OnRecorderListener recorderListener;
boolean isCancel;
private RecorderTask recorderTask;
private Timer recorderTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
btnSay = (Button) findViewById(R.id.btn_say);
imageSay = (ImageView) findViewById(R.id.image_say);
textUpCancel = (TextView) findViewById(R.id.text_up_cancel);
recorderListener = new RecorderVoiceUtil.SimpleRecorderListener(){
@Override
public void onPermissionError() {
super.onPermissionError();
Toast.makeText(context, "没有录音权限", Toast.LENGTH_LONG).show();
}
@Override
public void onReachMax(String outputPath, int maxDurationMs) {
super.onReachMax(outputPath, maxDurationMs);
cancelRecorder();
}
@Override
public void onError() {
super.onError();
cancelRecorder();
}
};
gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.i(tag, "onScroll distanceY:"+distanceY);
if (distanceY >= 10) {
btnSay.setText(R.string.up_finger_finish);
textUpCancel.setVisibility(View.GONE);
imageSay.setImageResource(R.drawable.mic_cancel);
//线程没有结束,只是不让更新界面
recorderTask.setCancel(true);
isCancel = true;
}
if (distanceY <= -10) {
btnSay.setText(R.string.up_finish);
textUpCancel.setVisibility(View.VISIBLE);
imageSay.setImageResource(R.drawable.mic_1);
recorderTask.setCancel(false);
isCancel = false;
}
return true;
}
@Override
public boolean onDown(MotionEvent e) {
Log.i(tag, "onDown");
startRecorder();
return true;
}
});
btnSay.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
boolean flag = gestureDetector.onTouchEvent(event);
if (flag) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
flag = true;
stopRecorder();
break;
case MotionEvent.ACTION_CANCEL:
cancelRecorder();
flag = true;
break;
}
return flag;
}
});
}
private void startRecorder() {
btnSay.setSelected(true);
btnSay.setText(R.string.up_finish);
textUpCancel.setVisibility(View.VISIBLE);
imageSay.setVisibility(View.VISIBLE);
String filename = "recordvoice" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".mp3";
RecorderVoiceUtil.startRecorder(FileUtil.getPathOfMusic(context, filename), 60 * 1000, recorderListener);
recorderTime = new Timer();
recorderTask = new RecorderTask(this, imageSay);
recorderTime.schedule(recorderTask, 0, 200);
}
private void stopRecorder(){
btnSay.setSelected(false);
btnSay.setText(R.string.pressed_say);
textUpCancel.setVisibility(View.GONE);
imageSay.setVisibility(View.GONE);
recorderTask.setCancel(true);
recorderTime.cancel();
if (isCancel) {
Log.i(tag, "up 取消录音");
RecorderVoiceUtil.cancelRecorder();
} else {
RecorderVoiceUtil.stopRecorder();
}
}
private void cancelRecorder(){
Log.i(tag, "cancel 取消录音");
btnSay.setSelected(false);
textUpCancel.setVisibility(View.GONE);
imageSay.setVisibility(View.GONE);
btnSay.setText(R.string.pressed_say);
recorderTask.setCancel(true);
recorderTime.cancel();
}
}
源代码下载
https://download.csdn.net/download/epdc2/9527241