如何使用Android仿微信语音对讲录音功能

这篇文章主要介绍如何使用Android仿微信语音对讲录音功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

为兴安盟等地区用户提供了全套网页设计制作服务,及兴安盟网站建设行业解决方案。主营业务为成都网站设计、网站建设、兴安盟网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

实现思路:

1.在微信中我们可以看到实现语音对讲的是通过点按按钮来完成的,因此在这里我选择重新自己的控件使其继承自Button并重写onTouchEvent方法,来实现对录音的判断。

2.在onTouchEvent方法中,

当我们按下按钮时,首先显示录音的对话框,然后调用录音准备方法并开始录音,接着开启一个计时线程,每隔0.1秒的时间获取一次录音音量的大小,并通过Handler根据音量大小更新Dialog中的显示图片;

当我们移动手指时,若手指向上移动距离大于50,在Dialog中显示松开手指取消录音的提示,并将isCanceled变量(表示我们最后是否取消了录音)置为true,上移动距离小于20时,我们恢复Dialog的图片,并将isCanceled置为false; 当抬起手指时,我们首先关闭录音对话框,接着调用录音停止方法并关闭计时线程,然后我们判断是否取消录音,若是的话则删除录音文件,否则判断计时时间是否太短,最后调用回调接口中的recordEnd方法。

3.在这里为了适应不同的录音需求,我使用了策略模式来进行处理,将每一个不同的录音方法视为一种不同的策略,根据自己的需要去改写。

注意问题

1.在onTouchEvent的返回值中应该返回true,这样才能屏蔽之后其他的触摸事件,否则当手指滑动离开Button之后将不能在响应我们的触摸方法。 2.不要忘记为自己的App添加权限:

代码参考

RecordButton 类,我们的自定义控件,重新复写了onTouchEvent方法

package com.example.recordtest;import android.annotation.SuppressLint;import android.app.Dialog;import android.content.Context;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.view.Gravity;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;public class RecordButton extends Button {  private static final int MIN_RECORD_TIME = 1; // 最短录音时间,单位秒  private static final int RECORD_OFF = 0; // 不在录音  private static final int RECORD_ON = 1; // 正在录音  private Dialog mRecordDialog;  private RecordStrategy mAudioRecorder;  private Thread mRecordThread;  private RecordListener listener;  private int recordState = 0; // 录音状态  private float recodeTime = 0.0f; // 录音时长,如果录音时间太短则录音失败  private double voiceValue = 0.0; // 录音的音量值  private boolean isCanceled = false; // 是否取消录音  private float downY;  private TextView dialogTextView;  private ImageView dialogImg;  private Context mContext;  public RecordButton(Context context) {    super(context);    // TODO Auto-generated constructor stub    init(context);  }  public RecordButton(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);    // TODO Auto-generated constructor stub    init(context);  }  public RecordButton(Context context, AttributeSet attrs) {    super(context, attrs);    // TODO Auto-generated constructor stub    init(context);  }  private void init(Context context) {    mContext = context;    this.setText("按住 说话");  }  public void setAudioRecord(RecordStrategy record) {    this.mAudioRecorder = record;  }  public void setRecordListener(RecordListener listener) {    this.listener = listener;  }  // 录音时显示Dialog  private void showVoiceDialog(int flag) {    if (mRecordDialog == null) {      mRecordDialog = new Dialog(mContext, R.style.Dialogstyle);      mRecordDialog.setContentView(R.layout.dialog_record);      dialogImg = (ImageView) mRecordDialog          .findViewById(R.id.record_dialog_img);      dialogTextView = (TextView) mRecordDialog          .findViewById(R.id.record_dialog_txt);    }    switch (flag) {    case 1:      dialogImg.setImageResource(R.drawable.record_cancel);      dialogTextView.setText("松开手指可取消录音");      this.setText("松开手指 取消录音");      break;    default:      dialogImg.setImageResource(R.drawable.record_animate_01);      dialogTextView.setText("向上滑动可取消录音");      this.setText("松开手指 完成录音");      break;    }    dialogTextView.setTextSize(14);    mRecordDialog.show();  }  // 录音时间太短时Toast显示  private void showWarnToast(String toastText) {    Toast toast = new Toast(mContext);    View warnView = LayoutInflater.from(mContext).inflate(        R.layout.toast_warn, null);    toast.setView(warnView);    toast.setGravity(Gravity.CENTER, 0, 0);// 起点位置为中间    toast.show();  }  // 开启录音计时线程  private void callRecordTimeThread() {    mRecordThread = new Thread(recordThread);    mRecordThread.start();  }  // 录音Dialog图片随录音音量大小切换  private void setDialogImage() {    if (voiceValue < 600.0) {      dialogImg.setImageResource(R.drawable.record_animate_01);    } else if (voiceValue > 600.0 && voiceValue < 1000.0) {      dialogImg.setImageResource(R.drawable.record_animate_02);    } else if (voiceValue > 1000.0 && voiceValue < 1200.0) {      dialogImg.setImageResource(R.drawable.record_animate_03);    } else if (voiceValue > 1200.0 && voiceValue < 1400.0) {      dialogImg.setImageResource(R.drawable.record_animate_04);    } else if (voiceValue > 1400.0 && voiceValue < 1600.0) {      dialogImg.setImageResource(R.drawable.record_animate_05);    } else if (voiceValue > 1600.0 && voiceValue < 1800.0) {      dialogImg.setImageResource(R.drawable.record_animate_06);    } else if (voiceValue > 1800.0 && voiceValue < 2000.0) {      dialogImg.setImageResource(R.drawable.record_animate_07);    } else if (voiceValue > 2000.0 && voiceValue < 3000.0) {      dialogImg.setImageResource(R.drawable.record_animate_08);    } else if (voiceValue > 3000.0 && voiceValue < 4000.0) {      dialogImg.setImageResource(R.drawable.record_animate_09);    } else if (voiceValue > 4000.0 && voiceValue < 6000.0) {      dialogImg.setImageResource(R.drawable.record_animate_10);    } else if (voiceValue > 6000.0 && voiceValue < 8000.0) {      dialogImg.setImageResource(R.drawable.record_animate_11);    } else if (voiceValue > 8000.0 && voiceValue < 10000.0) {      dialogImg.setImageResource(R.drawable.record_animate_12);    } else if (voiceValue > 10000.0 && voiceValue < 12000.0) {      dialogImg.setImageResource(R.drawable.record_animate_13);    } else if (voiceValue > 12000.0) {      dialogImg.setImageResource(R.drawable.record_animate_14);    }  }  // 录音线程  private Runnable recordThread = new Runnable() {    @Override    public void run() {      recodeTime = 0.0f;      while (recordState == RECORD_ON) {        {          try {            Thread.sleep(100);            recodeTime += 0.1;            // 获取音量,更新dialog            if (!isCanceled) {              voiceValue = mAudioRecorder.getAmplitude();              recordHandler.sendEmptyMessage(1);            }          } catch (InterruptedException e) {            e.printStackTrace();          }        }      }    }  };  @SuppressLint("HandlerLeak")  private Handler recordHandler = new Handler() {    @Override    public void handleMessage(Message msg) {      setDialogImage();    }  };  @Override  public boolean onTouchEvent(MotionEvent event) {    // TODO Auto-generated method stub    switch (event.getAction()) {    case MotionEvent.ACTION_DOWN: // 按下按钮      if (recordState != RECORD_ON) {        showVoiceDialog(0);        downY = event.getY();        if (mAudioRecorder != null) {          mAudioRecorder.ready();          recordState = RECORD_ON;          mAudioRecorder.start();          callRecordTimeThread();        }      }      break;    case MotionEvent.ACTION_MOVE: // 滑动手指      float moveY = event.getY();      if (downY - moveY > 50) {        isCanceled = true;        showVoiceDialog(1);      }      if (downY - moveY < 20) {        isCanceled = false;        showVoiceDialog(0);      }      break;    case MotionEvent.ACTION_UP: // 松开手指      if (recordState == RECORD_ON) {        recordState = RECORD_OFF;        if (mRecordDialog.isShowing()) {          mRecordDialog.dismiss();        }        mAudioRecorder.stop();        mRecordThread.interrupt();        voiceValue = 0.0;        if (isCanceled) {          mAudioRecorder.deleteOldFile();        } else {          if (recodeTime < MIN_RECORD_TIME) {            showWarnToast("时间太短 录音失败");            mAudioRecorder.deleteOldFile();          } else {            if (listener != null) {              listener.recordEnd(mAudioRecorder.getFilePath());            }          }        }        isCanceled = false;        this.setText("按住 说话");      }      break;    }    return true;  }  public interface RecordListener {    public void recordEnd(String filePath);  }}

Dialog布局:

   

录音时间太短的Toast布局:

   

自定义的Dialogstyle,对话框样式

RecordStrategy 录音策略接口

package com.example.recordtest;/** * RecordStrategy 录音策略接口 * @author acer */public interface RecordStrategy {  /**   * 在这里进行录音准备工作,重置录音文件名等   */  public void ready();  /**   * 开始录音   */  public void start();  /**   * 录音结束   */  public void stop();  /**   * 录音失败时删除原来的旧文件   */  public void deleteOldFile();  /**   * 获取录音音量的大小   * @return   */  public double getAmplitude();  /**   * 返回录音文件完整路径   * @return   */  public String getFilePath();}

个人写的一个录音实践策略

package com.example.recordtest;import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import android.media.MediaRecorder;import android.os.Environment;public class AudioRecorder implements RecordStrategy {  private MediaRecorder recorder;  private String fileName;  private String fileFolder = Environment.getExternalStorageDirectory()      .getPath() + "/TestRecord";  private boolean isRecording = false;  @Override  public void ready() {    // TODO Auto-generated method stub    File file = new File(fileFolder);    if (!file.exists()) {      file.mkdir();    }    fileName = getCurrentDate();    recorder = new MediaRecorder();    recorder.setOutputFile(fileFolder + "/" + fileName + ".amr");    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置MediaRecorder的音频源为麦克风    recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);// 设置MediaRecorder录制的音频格式    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 设置MediaRecorder录制音频的编码为amr  }  // 以当前时间作为文件名  private String getCurrentDate() {    SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HHmmss");    Date curDate = new Date(System.currentTimeMillis());// 获取当前时间    String str = formatter.format(curDate);    return str;  }  @Override  public void start() {    // TODO Auto-generated method stub    if (!isRecording) {      try {        recorder.prepare();        recorder.start();      } catch (IllegalStateException e) {        // TODO Auto-generated catch block        e.printStackTrace();      } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();      }      isRecording = true;    }  }  @Override  public void stop() {    // TODO Auto-generated method stub    if (isRecording) {      recorder.stop();      recorder.release();      isRecording = false;    }  }  @Override  public void deleteOldFile() {    // TODO Auto-generated method stub    File file = new File(fileFolder + "/" + fileName + ".amr");    file.deleteOnExit();  }  @Override  public double getAmplitude() {    // TODO Auto-generated method stub    if (!isRecording) {      return 0;    }    return recorder.getMaxAmplitude();  }  @Override  public String getFilePath() {    // TODO Auto-generated method stub    return fileFolder + "/" + fileName + ".amr";  }}

MainActivity

package com.example.recordtest;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity {  RecordButton button;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    button = (RecordButton) findViewById(R.id.btn_record);    button.setAudioRecord(new AudioRecorder());  }  @Override  public boolean onCreateOptionsMenu(Menu menu) {    // Inflate the menu; this adds items to the action bar if it is present.    getMenuInflater().inflate(R.menu.main, menu);    return true;  }}

以上是“如何使用Android仿微信语音对讲录音功能”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注创新互联行业资讯频道!


分享文章:如何使用Android仿微信语音对讲录音功能
网站路径:http://bzwzjz.com/article/pphgej.html

其他资讯

Copyright © 2007-2020 广东宝晨空调科技有限公司 All Rights Reserved 粤ICP备2022107769号
友情链接: 重庆网站建设 成都做网站建设公司 梓潼网站设计 响应式网站建设 网站建设公司 网站建设 成都网站建设公司 重庆企业网站建设 成都网站制作公司 定制网站设计 定制网站建设 成都网站建设公司 成都网站设计 网站制作报价 成都网站制作 成都网站建设 成都网站制作 品牌网站建设 高端定制网站设计 专业网站设计 四川成都网站建设 手机网站制作