Android实现录音方法(仿微信语音、麦克风录音、发送语音

7
回复
1092
查看
打印 上一主题 下一主题
[复制链接]

501

主题

1239

帖子

302

安币

手工艺人

楼主
发表于 2018-5-2 12:08:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

            

        先给大?#33402;?#31034;下效果图,如果大家感觉不错,请参考使用方法,

        效果图如下所示:

        

        使用方法:

        录音工具类:audiorecoderutils.java,代码如下:

[Java] 查看源文件 复制代码
public class audiorecoderutils {
 //文件路径
 private string filepath;
 //文件?#26032;?#24452;
 private string folderpath;
 private mediarecorder mmediarecorder;
 private final string tag = "fan";
 public static final int max_length = 1000 * 60 * 10;// 最大录音时长1000*60*10;
 private onaudiostatusupdatelistener audiostatusupdatelistener;
 /**
  * 文件存储默认sdcard/record
  */
 public audiorecoderutils(){
  //默认保存路径为/sdcard/record/下
  this(environment.getexternalstoragedirectory()+"/record/");
 }
 public audiorecoderutils(string filepath) {
  file path = new file(filepath);
  if(!path.exists())
   path.mkdirs();
  this.folderpath = filepath;
 }
 private long starttime;
 private long endtime;
 /**
  * 开始录音 使用amr格式
  *  录音文件
  * @return
  */
 public void startrecord() {
  // 开始录音
  /* ①initial:实例化mediarecorder对象 */
  if (mmediarecorder == null)
   mmediarecorder = new mediarecorder();
  try {
   /* ②setaudiosource/setvediosource */
   mmediarecorder.setaudiosource(mediarecorder.audiosource.mic);// 设置麦克风
   /* ②设置音频文件的编码:aac/amr_nb/amr_mb/default 声音?#27169;?#27874;形)的采样 */
   mmediarecorder.setoutputformat(mediarecorder.outputformat.default);
   /*
    * ②设置输出文件的格式:three_gpp/mpeg-4/raw_amr/default three_gpp(3gp格式
    * ,h263视频/arm音频编码)、mpeg-4、raw_amr(只支持音?#30331;?#38899;频编码要求为amr_nb)
    */
   mmediarecorder.setaudioencoder(mediarecorder.audioencoder.amr_nb);
   filepath = folderpath + timeutils.getcurrenttime() + ".amr" ;
   /* ③准备 */
   mmediarecorder.setoutputfile(filepath);
   mmediarecorder.setmaxduration(max_length);
   mmediarecorder.prepare();
   /* ④开始 */
   mmediarecorder.start();
   // audiorecord audiorecord.
   /* 获取开始时间* */
   starttime = system.currenttimemillis();
   updatemicstatus();
   log.e("fan", "starttime" + starttime);
  } catch (illegalstateexception e) {
   log.i(tag, "call startamr(file mrecaudiofile) failed!" + e.getmessage());
  } catch (ioexception e) {
   log.i(tag, "call startamr(file mrecaudiofile) failed!" + e.getmessage());
  }
 }
 /**
  * 停止录音
  */
 public long stoprecord() {
  if (mmediarecorder == null)
   return 0l;
  endtime = system.currenttimemillis();
  //有一些网友反应在5.0以上在调用stop的时候会报错,翻阅了一下谷歌文档发现上面确实写的有可能会报错的情况,捕获异常清理一下就行了,感谢大家反馈!
  try {
   mmediarecorder.stop();
   mmediarecorder.reset();
   mmediarecorder.release();
   mmediarecorder = null;
   audiostatusupdatelistener.onstop(filepath);
   filepath = "";
  }catch (runtimeexception e){
   mmediarecorder.reset();
   mmediarecorder.release();
   mmediarecorder = null;
   file file = new file(filepath);
   if (file.exists())
    file.delete();
   filepath = "";
  }
  return endtime - starttime;
 }
 /**
  * 取消录音
  */
 public void cancelrecord(){
  try {
   mmediarecorder.stop();
   mmediarecorder.reset();
   mmediarecorder.release();
   mmediarecorder = null;
  }catch (runtimeexception e){
   mmediarecorder.reset();
   mmediarecorder.release();
   mmediarecorder = null;
  }
  file file = new file(filepath);
  if (file.exists())
   file.delete();
  filepath = "";
 }
 private final handler mhandler = new handler();
 private runnable mupdatemicstatustimer = new runnable() {
  public void run() {
   updatemicstatus();
  }
 };
 private int base = 1;
 private int space = 100;// 间隔取样时间
 public void setonaudiostatusupdatelistener(onaudiostatusupdatelistener audiostatusupdatelistener) {
  this.audiostatusupdatelistener = audiostatusupdatelistener;
 }
 /**
  * 更新麦克状态
  */
 private void updatemicstatus() {
  if (mmediarecorder != null) {
   double ratio = (double)mmediarecorder.getmaxamplitude() / base;
   double db = 0;// 分贝
   if (ratio > 1) {
    db = 20 * math.log10(ratio);
    if(null != audiostatusupdatelistener) {
     audiostatusupdatelistener.onupdate(db,system.currenttimemillis()-starttime);
    }
   }
   mhandler.postdelayed(mupdatemicstatustimer, space);
  }
 }
 public interface onaudiostatusupdatelistener {
  /**
   * 录音中...
   * @param db 当前声音分贝
   * @param time 录音时长
   */
  public void onupdate(double db,long time);
  /**
   * 停止录音
   * @param filepath 保存路径
   */
  public void onstop(string filepath);
 }
}

        使用很简单,主要就是开始录音startrecord()、取消录音cancelrecord()、结束录音stoprecord()和录音监听setonaudiostatusupdatelistener(),注意,取消录音不保存文件,结束录音会保存文件!

        在布局文件中添加一个控件(任意一个?#22841;校?/font>

[Java] 查看源文件 复制代码
<button
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="按住说话"
 android:textcolor="@android:color/white"
 android:id="@+id/button"
 android:background="@color/colorprimary"
 />

        在activity中使用:

[Java] 查看源文件 复制代码
//当?#23433;?#23616;文件的根layout
  final relativelayout rl = (relativelayout) findviewbyid(r.id.rl);
  mbutton = (button) findviewbyid(r.id.button);
  //popupwindow的布局文件
  final view view = view.inflate(this, r.layout.layout_microphone, null);
  final popupwindowfactory mpop = new popupwindowfactory(this,view);
  //popupwindow布局文件里面的控件
  mimageview = (imageview) view.findviewbyid(r.id.iv_recording_icon);
  mtextview = (textview) view.findviewbyid(r.id.tv_recording_time);
  maudiorecoderutils = new audiorecoderutils();
  //录音回调
  maudiorecoderutils.setonaudiostatusupdatelistener(new audiorecoderutils.onaudiostatusupdatelistener() {
   //录音中....db为声音分贝,time为录音时长
   @override
   public void onupdate(double db, long time) {
    //根据分贝值来设置录音时?#24052;?#22270;标的上下波动,下面有讲解
    mimageview.getdrawable().setlevel((int) (3000 + 6000 * db / 100));
    mtextview.settext(timeutils.long2string(time));
   }
   //录音结束,filepath为保存路径
   @override
   public void onstop(string filepath) {
    toast.maketext(mainactivity.this, "录音保存在:" + filepath, toast.length_short).show();
    mtextview.settext(timeutils.long2string(0));
   }
  });
  //button的touch监听
  mbutton.setontouchlistener(new view.ontouchlistener() {
   @override
   public boolean ontouch(view v, motionevent event) {
    switch (event.getaction()){
     case motionevent.action_down:
      mpop.showatlocation(rl,gravity.center,0,0);
      mbutton.settext("松开保存");
      maudiorecoderutils.startrecord();
      break;
     case motionevent.action_up:
      maudiorecoderutils.stoprecord();  //结束录音(保存录音文件)
//      maudiorecoderutils.cancelrecord(); //取消录音(不保存录音文件)
      mpop.dismiss();
      mbutton.settext("按住说话");
      break;
    }
    return true;
   }
  });

        总结






        
分享到:  QQ好友和群 QQ空间 微信
收藏
收藏1
支持
支持0
反对
反对0

62

主题

9832

帖子

899

安币

代码手工艺人

学海无涯

Rank: 4

QQ达人

沙发
发表于 2018-5-2 14:57:38 | 只看该作者
楼主威武,以后多发干货,多办活动~!

317

主题

995

帖子

688

安币

手工艺人

板凳
发表于 2018-5-2 18:35:29 | 只看该作者
不错不错,楼主辛苦了。。。

28

主题

1万

帖子

1362

安币

Android大神

小白

Rank: 6Rank: 6

地板
发表于 2018-5-2 21:52:22 | 只看该作者
安卓巴士是个不错的网站,我来顶个贴~

0

主题

1万

帖子

2395

安币

Android大神

Rank: 6Rank: 6

5#
发表于 2018-5-3 00:39:13 | 只看该作者
安卓巴士是个不错的网站,我来顶个贴~

0

主题

9263

帖子

2054

安币

Android大神

Rank: 6Rank: 6

6#
发表于 2018-5-3 03:27:07 | 只看该作者
帮帮顶顶!!

9

主题

9487

帖子

1804

安币

Android大神

Rank: 6Rank: 6

QQ达人

7#
发表于 2018-5-3 05:42:06 | 只看该作者
感谢分享,楼主V5~

1

主题

12

帖子

57

安币

程序猿

Rank: 2

8#
发表于 2019-12-27 08:39:49 | 只看该作者
正需要啊,感谢楼主无私分享!
您需要登录后才可以回帖 登录 | 立即注册

本版积?#27490;?#21017;

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:[email protected]

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )

招财童子彩金
中超直播新浪 澳洲幸运5计划软件手机版 足球比赛比分查询 极速飞艇官方网站 澳克竞彩比分直播 杭州麻将胡牌公式 股票可以在线开户吗 湖南幸运赛车开奖结果 重庆麻将骰子怎么看 20010期七乐彩开奖结果 法国对比利时比分预测 吉林11选5遗漏 黑龙江20选8快乐 熊猫娱乐棋牌官方版下载 疯狂飞艇开奖记录官方 棒球比分直播雪缘园