录音时间过短显示不正常
为什么显示“录音时间过短”有问题呢?求解,谢谢了!log执行到了,就是对话框显示不正常,显示的是Normal状态
AudioRecorderButton类:
package com.imooc.recorder.view;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import com.imooc.recorder.R;
import com.imooc.recorder.view.AudioManager.AudioStateListener;
public class AudioRecorderButton extends Button implements AudioStateListener {
private static final int DISTANCE_Y_CANCEL = 50;
private static final int STATE_NORMAL = 1; // 默认状态
private static final int STATE_RECORDING = 2; // 录音状态
private static final int STATE_WANT_TO_CANCEL = 3; // 取消
private int mCurState = STATE_NORMAL;
/**
* 记录是否正在录音中
*/
private boolean isRecording = false;
private DialogManager mDialogManager = null;
private AudioManager mAudioManager = null;
/**
* 计时
*/
private float mTime;
/**
* 是否触发longClick
*/
private boolean isReady;
/**
* 最大音量
*/
protected static final int MAX_VOICE_LEVEL = 7;
/**
* 录音完成后的回调
* @author Archer
*
*/
public interface AudioRecordFinishListener {
void onFinish(float seconds, String filePath);
}
private AudioRecordFinishListener mListener;
public void setOnAudioRecordFinishListener(AudioRecordFinishListener listener) {
mListener = listener;
}
public AudioRecorderButton(Context context) {
this(context, null);
}
public AudioRecorderButton(Context context, AttributeSet attrs) {
super(context, attrs);
mDialogManager = new DialogManager(getContext());
String dir = Environment.getExternalStorageDirectory() + "/imooc_recorder_audios";
mAudioManager = AudioManager.getInstance(dir);
mAudioManager.setOnAudioStateListener(this);
setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
isReady = true;
mAudioManager.prepareAudio();
return false;
}
});
}
/**
* 获取音量大小的Runnable and 录音计时
*/
private Runnable mGetVoiceLevelRunnable = new Runnable() {
@Override
public void run() {
while (isRecording) {
try {
Thread.sleep(100);
mTime += 0.1f;
mHandler.sendEmptyMessage(MSG_VOICE_CHANGED);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
private static final int MSG_AUDIO_PREPARED = 0x110;
private static final int MSG_VOICE_CHANGED = 0x111;
private static final int MSG_DIALOG_DISMISS = 0x112;
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_AUDIO_PREPARED:
// 显示应该在 audio end prepared 以后
mDialogManager.showRecordingDialog();
isRecording = true;
new Thread(mGetVoiceLevelRunnable).start();
break;
case MSG_VOICE_CHANGED:
int voiceLevel = mAudioManager.getVoiceLevel(MAX_VOICE_LEVEL);
mDialogManager.updateVoiceLevel(voiceLevel);
break;
case MSG_DIALOG_DISMISS:
mDialogManager.dismissDialog();
break;
}
};
};
@Override
public void wellPrepared() {
mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
changeState(STATE_RECORDING);
break;
case MotionEvent.ACTION_MOVE:
if (isRecording) {
if (wantToCancel(x, y)) {
changeState(STATE_WANT_TO_CANCEL);
} else {
changeState(STATE_RECORDING);
}
}
break;
case MotionEvent.ACTION_UP:
if (!isReady) {
reset();
return super.onTouchEvent(event);
}
if (!isRecording || mTime < 0.6f) { // audio没有prepared 或者 mTime小于0.6f
Log.i("recorder", "tooShort");
mDialogManager.tooShort();
mAudioManager.cancel();
// 1.3s以后关闭tooShortDialog
mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DISMISS, 1300);
} else if (mCurState == STATE_RECORDING) { // 正常录制结束
mDialogManager.dismissDialog();
// audio release
mAudioManager.release();
// callBackToActivity
if (mListener != null) {
mListener.onFinish(mTime, mAudioManager.getCurrentFilePath());
}
} else if (mCurState == STATE_WANT_TO_CANCEL) {
mDialogManager.dismissDialog();
// audio cancel
mAudioManager.cancel();
}
reset();
break;
}
return super.onTouchEvent(event);
}
/**
* 恢复状态及标志位
*/
private void reset() {
isRecording = false;
isReady = false;
mTime = 0;
changeState(STATE_NORMAL);
}
/**
* 根据x,y的值判断是否想要取消
*
* @param x
* @param y
* @return
*/
private boolean wantToCancel(int x, int y) {
if (x < 0 || x > getWidth()) {
// 判断手指横坐标是否超出按钮范围
return true;
}
if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
return true;
}
return false;
}
private void changeState(int state) {
if (mCurState != state) {
mCurState = state;
switch (state) {
case STATE_NORMAL:
setBackgroundResource(R.drawable.btn_recorder_normal);
setText(R.string.str_recorder_normal);
break;
case STATE_RECORDING:
setBackgroundResource(R.drawable.btn_recorder_recording);
setText(R.string.str_recorder_recording);
if (isRecording) {
// TODO Dialog.recording()
mDialogManager.recording();
}
break;
case STATE_WANT_TO_CANCEL:
setBackgroundResource(R.drawable.btn_recorder_recording);
setText(R.string.str_recorder_want_to_cancel);
// TODO Dialog.wantToCancel()
mDialogManager.wantToCancel();
break;
}
}
}
}DialogManager类:
package com.imooc.recorder.view;
import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.imooc.recorder.R;
public class DialogManager {
private Context mContext;
private Dialog mDialog;
private ImageView mIcon;
private ImageView mVoice;
private TextView mLabel;
public DialogManager(Context context) {
mContext = context;
}
public void showRecordingDialog() {
mDialog = new Dialog(mContext, R.style.Theme_AudioRecorderDialog);
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.dialog_recorder, null);
mDialog.setContentView(view);
mIcon = (ImageView) mDialog.findViewById(R.id.id_recorder_dialog_icon);
mVoice = (ImageView) mDialog.findViewById(R.id.id_recorder_dialog_voice);
mLabel = (TextView) mDialog.findViewById(R.id.id_recorder_dialog_label);
mDialog.show();
}
public void recording() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mVoice.setVisibility(View.VISIBLE);
mLabel.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.recorder);
mLabel.setText(R.string.str_recorder_dialog_recording);
}
}
public void wantToCancel() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mVoice.setVisibility(View.GONE);
mLabel.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.cancel);
mLabel.setText(R.string.str_recorder_dialog_want_to_cancel);
}
}
public void tooShort() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mVoice.setVisibility(View.GONE);
mLabel.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.voice_to_short);
mLabel.setText(R.string.str_recorder_dialog_too_short);
}
}
public void dismissDialog() {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
mDialog = null;
}
}
/**
* 通过level更新voice上的图片
*
* @param level
* 1-7
*/
public void updateVoiceLevel(int level) {
if (mDialog != null && mDialog.isShowing()) {
// 通过方法名找到资源
int resId = mContext.getResources().getIdentifier("v" + level, "drawable",
mContext.getPackageName());
mVoice.setImageResource(resId);
}
}
}AudioManager类:
package com.imooc.recorder.view;
import java.io.File;
import java.util.UUID;
import android.media.MediaRecorder;
public class AudioManager {
private MediaRecorder mMediaRecorder;
private String mDir;
private String mCurFilePath;
private static AudioManager mInstance;
private boolean isPrepared = false;
public interface AudioStateListener {
void wellPrepared();
}
private AudioStateListener mListener;
public void setOnAudioStateListener(AudioStateListener listener) {
mListener = listener;
}
private AudioManager(String dir) {
mDir = dir;
}
public static AudioManager getInstance(String dir) {
if (mInstance == null) {
synchronized (AudioManager.class) {
if (mInstance == null) {
mInstance = new AudioManager(dir);
}
}
}
return mInstance;
}
public void prepareAudio() {
try {
isPrepared = false;
File dir = new File(mDir);
if (!dir.exists()) {
dir.mkdirs();
}
String fileName = generateFileName();
File file = new File(dir, fileName);
mCurFilePath = file.getAbsolutePath();
mMediaRecorder = new MediaRecorder();
// 设置输出文件
mMediaRecorder.setOutputFile(mCurFilePath);
// 设置音频源为麦克风
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 设置音频格式
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
// 设置音频编码
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.prepare();
mMediaRecorder.start();
// 准备结束
isPrepared = true;
if (mListener != null) {
mListener.wellPrepared();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String generateFileName() {
return UUID.randomUUID().toString() + ".amr";
}
public int getVoiceLevel(int maxLevel) {
if (isPrepared) {
try {
return maxLevel * mMediaRecorder.getMaxAmplitude() / 32768 + 1;
} catch (Exception e) {
e.printStackTrace();
}
}
return 1;
}
public void release() {
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
}
public void cancel() {
release();
if (mCurFilePath != null) {
File file = new File(mCurFilePath);
file.delete();
mCurFilePath = null;
}
}
public String getCurrentFilePath() {
return mCurFilePath;
}
}