package com.anthony.inputlayout.layout;
import android.content.Context;
import android.graphics.drawable.LevelListDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.anthony.inputlayout.utils.Utils;
import com.anthony.inputlayout.audio.AudioPlayerManager;
import com.anthony.inputlayout.audio.AudioRecorderManager;
import com.trs.inputlayout.R;
import java.io.File;
public class RecorderKeyboardLayout extends BaseCustomCompositeView implements AudioRecorderManager.Callback, View.OnTouchListener {
/**
* 录音的最大时间
*/
private static final int RECORDER_MAX_TIME = 60;
private static final int VOICE_LEVEL_COUNT = 9;
private static final int STATE_NORMAL = 1;
private static final int STATE_RECORDING = 2;
private static final int STATE_WANT_CANCEL = 3;
private int mCurrentState = STATE_NORMAL;
private boolean mIsRecording;
/**
* 是否超时,默认不超时
*/
private boolean mIsOvertime = false;
private boolean mHasPermission = false;
private int mDistanceCancel;
private AudioRecorderManager mAudioRecorderManager;
private float mTime;
private Callback mCallback;
private TextView mStatusTv;
private ImageView mAnimIv;
/**
* 上一次提示录音时间太短的时间戳
*/
private long mLastTipTooShortTime;
private Runnable mGetVoiceLevelRunnable = new Runnable() {
@Override
public void run() {
while (mIsRecording) {
try {
Thread.sleep(100);
mTime += 0.1f;
if (mTime <= RECORDER_MAX_TIME) {
refreshVoiceLevel();
} else {
mIsOvertime = true;
handleActionUp();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
public RecorderKeyboardLayout(Context context) {
super(context);
}
public RecorderKeyboardLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RecorderKeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected int getLayoutId() {
return R.layout.layout_recorder_keyboard;
}
@Override
protected void initView() {
mStatusTv = getViewById(R.id.tv_recorder_keyboard_status);
mAnimIv = getViewById(R.id.iv_recorder_keyboard_anim);
}
@Override
protected void setListener() {
mAnimIv.setOnTouchListener(this);
}
@Override
protected void processLogic() {
initLevelListDrawable();
mDistanceCancel = Utils.dip2px(getContext(), 10);
mAudioRecorderManager = new AudioRecorderManager(getContext(), this);
}
private void initLevelListDrawable() {
LevelListDrawable levelListDrawable = new LevelListDrawable();
for (int i = 0; i < 9; i++) {
int resId = getContext().getResources().getIdentifier("voice_level" + (i + 1), "drawable", getContext().getPackageName());
levelListDrawable.addLevel(i, i + 1, Utils.tintDrawable(getContext(), getResources().getDrawable(resId), R.color.mq_chat_audio_recorder_icon));
}
levelListDrawable.addLevel(9, 10, getResources().getDrawable(R.drawable.voice_want_cancel));
mAnimIv.setImageDrawable(levelListDrawable);
}
@Override
public void wellPrepared() {
mIsRecording = true;
new Thread(mGetVoiceLevelRunnable).start();
}
@Override
public void onAudioRecorderNoPermission() {
endRecorder();
reset();
}
private void refreshVoiceLevel() {
post(new Runnable() {
@Override
public void run() {
if (mCurrentState == STATE_RECORDING) {
mAnimIv.setImageLevel(mAudioRecorderManager.getVoiceLevel(VOICE_LEVEL_COUNT));
int remainingTime = Math.round(RECORDER_MAX_TIME - mTime);
if (remainingTime <= 10) {
mStatusTv.setText(getContext().getString(R.string.mq_recorder_remaining_time, remainingTime));
}
}
}
});
}
private void changeState(int status) {
if (mCurrentState != status) {
mCurrentState = status;
switch (mCurrentState) {
case STATE_NORMAL:
mStatusTv.setText(R.string.mq_audio_status_normal);
mAnimIv.setImageLevel(1);
break;
case STATE_RECORDING:
mStatusTv.setText(R.string.mq_audio_status_recording);
break;
case STATE_WANT_CANCEL:
mStatusTv.setText(R.string.mq_audio_status_want_cancel);
mAnimIv.setImageLevel(10);
break;
}
}
}
private boolean isWantCancel(int x, int y) {
if (y < -mDistanceCancel) {
return true;
}
return false;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mIsOvertime = false;
mHasPermission = true;
changeState(STATE_RECORDING);
mAudioRecorderManager.prepareAudio();
break;
case MotionEvent.ACTION_MOVE:
if (!mIsOvertime && mIsRecording && mHasPermission) {
if (isWantCancel(x, y)) {
changeState(STATE_WANT_CANCEL);
} else {
changeState(STATE_RECORDING);
}
}
break;
case MotionEvent.ACTION_UP:
handleActionUp();
break;
case MotionEvent.ACTION_CANCEL:
mAudioRecorderManager.cancel();
reset();
break;
}
return true;
}
private void handleActionUp() {
post(new Runnable() {
@Override
public void run() {
if (!mIsOvertime && mHasPermission) {
// 录音没有超时的情况
if (!mIsRecording || mTime < 1) {
// prepare未完成
mAudioRecorderManager.cancel();
if (System.currentTimeMillis() - mLastTipTooShortTime > 1000) {
mLastTipTooShortTime = System.currentTimeMillis();
mCallback.onAudioRecorderTooShort();
}
} else if (mCurrentState == STATE_RECORDING) {
endRecorder();
} else if (mCurrentState == STATE_WANT_CANCEL) {
mAudioRecorderManager.cancel();
}
} else if (mIsRecording) {
// 录音超时,并且正在录音时
endRecorder();
}
reset();
}
});
}
/**
* 结束录音
*/
private void endRecorder() {
mAudioRecorderManager.release();
if (mCallback != null) {
String currentFilePath = mAudioRecorderManager.getCurrenFilePath();
if (!TextUtils.isEmpty(currentFilePath)) {
File currentFile = new File(currentFilePath);
// 在某些手机上,没有权限录音时,文件大小为6
if (currentFile.exists() && currentFile.length() > 6) {
mCallback.onAudioRecorderFinish(AudioPlayerManager.getDurationByFilePath(getContext(), currentFile.getAbsolutePath()), currentFile.getAbsolutePath());
} else {
mAudioRecorderManager.cancel();
mCallback.onAudioRecorderNoPermission();
}
}
}
}
/**
* 恢复到初始状态
*/
private void reset() {
mIsRecording = false;
mHasPermission = false;
mTime = 0;
changeState(STATE_NORMAL);
}
/**
* 是否正在录音
*
* @return
*/
public boolean isRecording() {
return mCurrentState != STATE_NORMAL;
}
public void setCallback(Callback callback) {
mCallback = callback;
}
public interface Callback {
void onAudioRecorderFinish(int time, String filePath);
void onAudioRecorderTooShort();
void onAudioRecorderNoPermission();
}
}