600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 李长军android语音开发_Android模仿微信录音 发送语音效果实现

李长军android语音开发_Android模仿微信录音 发送语音效果实现

时间:2018-12-02 19:31:10

相关推荐

李长军android语音开发_Android模仿微信录音 发送语音效果实现

在项目开发中,有个需求:实现模仿微信录音,发送语音的功能。长按按钮录音,弹框显示语音时间,以及上滑取消发送。我重写了一个发送语音的控件,以实现该功能。

首先添加权限:

AudioRecorderButton,自己实现的自定义录音控件

public class AudioRecorderButton extends Button {

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 mCurrentState = STATE_NORMAL; // 当前的状态

private boolean isRecording = false;// 已经开始录音

private static final int DISTANCE_Y_CANCEL = 50;

private DialogManager mDialogManager;

private AudioManager mAudioManager;

// 是否触发longClick

private boolean mReady;

android.media.AudioManager audioManager;

private static final int MSG_AUDIO_PREPARED = 0x110;

private static final int MSG_VOICE_CHANGED = 0x111;

private static final int MSG_DIALOG_DIMISS = 0x112;

private static final int MSG_TIME_OUT = 0x113;

private static final int UPDATE_TIME = 0x114;

private boolean mThreadFlag = false;

private int time = 0;

private float mTime;

/*

* 获取音量大小的线程

*/

private Runnable mGetVoiceLevelRunnable = new Runnable() {

public void run() {

while (isRecording) {

try {

Thread.sleep(100);

mTime += 0.1f;

time++;

if (isWantToCancel) {

} else {

if (time % 10 == 0) {

mHandler.sendEmptyMessage(UPDATE_TIME);

}

}

mHandler.sendEmptyMessage(MSG_VOICE_CHANGED);

if (mTime >= 10.0f) {//如果时间超过10秒,自动结束录音

while (!mThreadFlag) {//记录已经结束了录音,不需要再次结束,以免出现问题

mDialogManager.dimissDialog();

mAudioManager.release();

if (audioFinishRecorderListener != null) {

//发消息给主线程,告诉他reset();

mHandler.sendEmptyMessage(MSG_TIME_OUT);

audioFinishRecorderListener.onFinish(mTime, mAudioManager.getCurrentFilePath());

}

mThreadFlag = !mThreadFlag;

}

isRecording = false;

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

};

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case MSG_AUDIO_PREPARED:

// 显示對話框在开始录音以后

mDialogManager.showRecordingDialog();

isRecording = true;

// 开启一个线程

new Thread(mGetVoiceLevelRunnable).start();

break;

case MSG_VOICE_CHANGED:

mDialogManager.updateVoiceLevel(mAudioManager.getVoiceLevel(7));

break;

case MSG_DIALOG_DIMISS:

mDialogManager.dimissDialog();

break;

case MSG_TIME_OUT://录音超时

reset();

break;

case UPDATE_TIME://更新时间

if (time % 10 == 0) {

mDialogManager.updateTime(time / 10);

}

break;

}

}

};

/**

* 以下2个方法是构造方法

*/

public AudioRecorderButton(Context context, AttributeSet attrs) {

super(context, attrs);

mDialogManager = new DialogManager(context);

audioManager = (android.media.AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

String dir = Environment.getExternalStorageDirectory().getPath() + "/" + LibraryContantsUtil.APP_NAME + "/audio";

mAudioManager = AudioManager.getInstance(dir);

mAudioManager.setOnAudioStateListener(new AudioManager.AudioStateListener() {

public void wellPrepared() {

if (!isOverDue) {

mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);//开启线程

}

}

});

// 由于这个类是button所以在构造方法中添加监听事件

setOnLongClickListener(new OnLongClickListener() {

public boolean onLongClick(View v) {

if (!isOverDue) {

mReady = true;

mAudioManager.prepareAudio();

}

return true;

}

});

}

public AudioRecorderButton(Context context) {

this(context, null);

}

/**

* 录音完成后的回调

*/

public interface AudioFinishRecorderListener {

void onFinish(float seconds, String filePath);

}

private AudioFinishRecorderListener audioFinishRecorderListener;

public void setAudioFinishRecorderListener(AudioFinishRecorderListener listener) {

audioFinishRecorderListener = listener;

}

android.media.AudioManager.OnAudioFocusChangeListener afChangeListener = new android.media.AudioManager.OnAudioFocusChangeListener() {

public void onAudioFocusChange(int focusChange) {

if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT) {

// Pause playback

} else if (focusChange == android.media.AudioManager.AUDIOFOCUS_GAIN) {

// Resume playback

LogUtil.e("===", "+++");

} else if (focusChange == android.media.AudioManager.AUDIOFOCUS_LOSS) {

audioManager.abandonAudioFocus(afChangeListener);

// Stop playback

}

}

};

public void myRequestAudioFocus() {

audioManager.requestAudioFocus(afChangeListener, android.media.AudioManager.STREAM_MUSIC, android.media.AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);

}

/**

* 屏幕的触摸事件

*/

@Override

public boolean onTouchEvent(MotionEvent event) {

// int x = (int) event.getX();// 获得x轴坐标

float last = 0;// 获得y轴坐标

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

mThreadFlag = false;

changeState(STATE_RECORDING);

myRequestAudioFocus();

break;

case MotionEvent.ACTION_MOVE:

if (isRecording) {

// 如果想要取消,根据x,y的坐标看是否需要取消

if (event.getY() < 0 && Math.abs(event.getY()) > 120) {

changeState(STATE_WANT_TO_CANCEL);

} else {

changeState(STATE_RECORDING);

}

}

break;

case MotionEvent.ACTION_UP:

if (!mReady) {

reset();

return super.onTouchEvent(event);

}

if (!isRecording || mTime <= 1.0f) {//小于1秒

mDialogManager.tooShort();

mAudioManager.cancel();

mHandler.sendEmptyMessage(MSG_DIALOG_DIMISS);//显示对话框

} else if (mCurrentState == STATE_RECORDING) { // 正在录音的时候,结束

mDialogManager.dimissDialog();

mAudioManager.release();

if (audioFinishRecorderListener != null) {

audioFinishRecorderListener.onFinish(mTime, mAudioManager.getCurrentFilePath());

}

} else if (mCurrentState == STATE_WANT_TO_CANCEL) { // 想要取消

mDialogManager.dimissDialog();

mAudioManager.cancel();

}

reset();

audioManager.abandonAudioFocus(afChangeListener);

}

break;

return super.onTouchEvent(event);

}

/**

* 恢复状态及标志位

*/

private void reset() {

isRecording = false;

mTime = 0;

time = 1;

mReady = false;

changeState(STATE_NORMAL);

}

private boolean wantToCancle(int x, int y) {

if (y < 0) {

return true;

} else {

return false;

}

}

boolean isWantToCancel = false;

/**

* 改变

*/

private void changeState(int state) {

if (mCurrentState != state) {

mCurrentState = state;

switch (state) {

case STATE_NORMAL:

setBackgroundResource(R.drawable.shape_voice_chat_circle);

setText("按住说话");

break;

case STATE_RECORDING:

if (isRecording) {

mDialogManager.recording();

}

setBackgroundResource(R.drawable.shape_voice_chat_circle);

setText("松开结束");

isWantToCancel = false;

break;

case STATE_WANT_TO_CANCEL:

setBackgroundResource(R.drawable.shape_voice_chat_circle);

setText("松开手指,取消发送");

mDialogManager.wantToCancel();

isWantToCancel = true;

break;

}

}

}

}

下面是DialogManager,录音时控制Dialog的显示隐藏,以及需要Dialog中需要向用户展示的内容。

public class DialogManager {

private AlertDialog.Builder builder;

private ImageView mIcon;

// private ImageView mVoice;

private TextView mLable;

private Context context;

private AlertDialog dialog;//用于取消AlertDialog.Builder

/**

* 构造方法 传入上下文

*/

public DialogManager(Context context) {

this.context = context;

}

// 显示录音的对话框

public void showRecordingDialog() {

builder = new AlertDialog.Builder(context, R.style.voice_chat_dialog);

LayoutInflater inflater = LayoutInflater.from(context);

View view = inflater.inflate(R.layout.dialog_recorder, null);

mIcon = (ImageView) view.findViewById(R.id.id_recorder_dialog_icon);

mLable = (TextView) view.findViewById(R.id.id_recorder_dialog_label);

// GlideUtil.loadSquarePicture(R.drawable.gif_record, mIcon);

builder.setView(view);

builder.create();

dialog = builder.show();

dialog.setCanceledOnTouchOutside(false);//设置点击外部不消失

}

public void recording() {

if (dialog != null && dialog.isShowing()) { //显示状态

mIcon.setVisibility(View.VISIBLE);

mLable.setVisibility(View.VISIBLE);

// GlideUtil.loadSquarePicture(R.drawable.gif_record, mIcon);

mIcon.setImageResource(R.mipmap.ic_record);

mLable.setText("手指上滑,取消发送");

}

}

// 显示想取消的对话框

public void wantToCancel() {

if (dialog != null && dialog.isShowing()) { //显示状态

mIcon.setVisibility(View.VISIBLE);

mLable.setVisibility(View.VISIBLE);

mIcon.setImageResource(R.mipmap.ic_release_to_cancel);

mLable.setText("松开手指,取消发送");

}

}

public void updateTime(int time) {

if (dialog != null && dialog.isShowing()) { //显示状态

mIcon.setVisibility(View.VISIBLE);

mLable.setVisibility(View.VISIBLE);

mLable.setText(time + "s");

}

}

// 显示时间过短的对话框

public void tooShort() {

if (dialog != null && dialog.isShowing()) { //显示状态

mIcon.setVisibility(View.VISIBLE);

mLable.setVisibility(View.VISIBLE);

mLable.setText("录音时间过短");

}

}

// 显示取消的对话框

public void dimissDialog() {

if (dialog != null && dialog.isShowing()) { //显示状态

dialog.dismiss();

dialog = null;

}

}

// 显示更新音量级别的对话框

public void updateVoiceLevel(int level) {

if (dialog != null && dialog.isShowing()) { //显示状态

mIcon.setVisibility(View.VISIBLE);

mLable.setVisibility(View.VISIBLE);

// 在这里没有做操作

//可以再这里根据音量大小,设置图片,实现效果;

}

}

}

下面是AudioManager,录音类

public class AudioManager {

private MediaRecorder mMediaRecorder;

private String mDir;

private String mCurrentFilePath;

private static AudioManager mInstance;

private boolean isPrepare;

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 interface AudioStateListener {

void wellPrepared();

}

public AudioStateListener mAudioStateListener;

/**

* 回调方法

*/

public void setOnAudioStateListener(AudioStateListener listener) {

mAudioStateListener = listener;

}

// 去准备

public void prepareAudio() {

try {

isPrepare = false;

File dir = new File(mDir);

if (!dir.exists()) {

dir.mkdirs();

} else {

if (!dir.isDirectory()) {

dir.delete();

dir.mkdirs();

}

}

String fileName = generateFileName();

File file = new File(dir, fileName);

mCurrentFilePath = file.getAbsolutePath();

mMediaRecorder = new MediaRecorder();

// 设置输出文件

mMediaRecorder.setOutputFile(file.getAbsolutePath());

// 设置MediaRecorder的音频源为麦克风

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

// 设置音频格式

mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);

// 设置音频编码

mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

// 准备录音

mMediaRecorder.prepare();

// 开始

mMediaRecorder.start();

// 准备结束

isPrepare = true;

if (mAudioStateListener != null) {

mAudioStateListener.wellPrepared();

}

} catch (IllegalStateException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 随机生成文件的名称

*/

private String generateFileName() {

return UUID.randomUUID().toString() + ".amr";

}

public int getVoiceLevel(int maxlevel) {

if (isPrepare) {

try {

return maxlevel * mMediaRecorder.getMaxAmplitude() / 32768 + 1;

} catch (Exception e) {

}

}

return 1;

}

/**

* 释放资源

*/

public void release() {

if (mMediaRecorder != null) {

mMediaRecorder.reset();

mMediaRecorder = null;

}

}

/**

* 取消录音

*/

public void cancel() {

release();

if (mCurrentFilePath != null) {

File file = new File(mCurrentFilePath);

file.delete();

mCurrentFilePath = null;

}

}

public String getCurrentFilePath() {

return mCurrentFilePath;

}

}

下面是MediaManager,播放,暂停录音

public class MediaManager {

private static MediaPlayer mMediaPlayer;

private static boolean isPause;

private String currentFilePath;

private AudioManager.AudioStateListener onAudioStateListener;

static Context context;

public MediaManager(Context context) {

this.context = context;

}

/**

* 播放音乐

*

* @param filePath

* @param onCompletionListener

*/

public static void playSound(String filePath, MediaPlayer.OnCompletionListener onCompletionListener) {

if (mMediaPlayer == null) {

mMediaPlayer = new MediaPlayer();

// mMediaPlayer = MediaPlayer.create(context, Uri.fromFile(new File(filePath)));

//设置一个error监听器

mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {

public boolean onError(MediaPlayer arg0, int arg1, int arg2) {

mMediaPlayer.reset();

return false;

}

});

} else {

mMediaPlayer.reset();

}

try {

mMediaPlayer.setAudioStreamType(android.media.AudioManager.STREAM_MUSIC);

mMediaPlayer.setOnCompletionListener(onCompletionListener);

mMediaPlayer.setDataSource(filePath);

mMediaPlayer.prepare();

mMediaPlayer.start();

} catch (Exception e) {

}

}

/**

* 暂停播放

*/

public static void pause() {

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

//正在播放的时候

mMediaPlayer.pause();

isPause = true;

}

}

public static boolean isPlaying() {

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

return true;

} else {

return false;

}

}

/**

* 当前是isPause状态

*/

public static void resume() {

if (mMediaPlayer != null && isPause) {

mMediaPlayer.start();

isPause = false;

}

}

/**

* 释放资源

*/

public static void release() {

if (mMediaPlayer != null) {

mMediaPlayer.release();

mMediaPlayer = null;

}

}

}

至此,其整体的代码已经编写完成了,在需要录音的地方调用:

audioRecorderButton.setAudioFinishRecorderListener(new AudioRecorderButton.AudioFinishRecorderListener() {

@Override

public void onFinish(float seconds, String filePath) {

//seconds 录音时长,filePath 录音文件的位置

//录音完成

upLoadVoice(filePath, (int) seconds);

}

});

Screenshot_-07-25-16-24-38-397_com.zijing.xin.png

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。