欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android使用MediaRecorder实现录音及播放

程序员文章站 2023-12-20 19:54:05
现在项目中有使用到音视频相关技术,在参考了网上各种大牛的资料及根据自己项目实际情况(兼容安卓6.0以上版本动态权限管理等),把声音录制及播放相关代码做个记录。...

现在项目中有使用到音视频相关技术,在参考了网上各种大牛的资料及根据自己项目实际情况(兼容安卓6.0以上版本动态权限管理等),把声音录制及播放相关代码做个记录。

public class mediarecorderactivity extends baseactivity {
  private button start_tv;
  private listview listview;
  //线程操作
  private executorservice mexecutorservice;
  //录音api
  private mediarecorder mmediarecorder;
  //录音开始时间与结束时间
  private long starttime, endtime;
  //录音所保存的文件
  private file maudiofile;
  //文件列表数据
  private list<filebean> datalist;
  //录音文件数据列表适配器
  private audioadapter maudioadapter;
  //录音文件保存位置
  private string mfilepath = environment.getexternalstoragedirectory().getabsolutepath() + "/audio/";
  //当前是否正在播放
  private volatile boolean isplaying;
  //播放音频文件api
  private mediaplayer mediaplayer;
  //使用handler更新ui线程
  private handler mhandler = new handler() {
    @override
    public void handlemessage(message msg) {
      super.handlemessage(msg);
      switch (msg.what) {
        case constant.record_success:
          //录音成功,展示数据
          if (null == maudioadapter) {
            maudioadapter = new audioadapter(mediarecorderactivity.this, datalist, r.layout.file_item_layout);
          }
          listview.setadapter(maudioadapter);
          break;
        //录音失败
        case constant.record_fail:
          showtoastmsg(getstring(r.string.record_fail));
          break;
        //录音时间太短
        case constant.record_too_short:
          showtoastmsg(getstring(r.string.time_too_short));
          break;
        case constant.play_completion:
          showtoastmsg(getstring(r.string.play_over));
          break;
        case constant.play_error:
          showtoastmsg(getstring(r.string.play_error));
          break;

      }
    }
  };

  @override
  protected void setwindowview() {
    setcontentview(r.layout.activity_record);
    //录音及播放要使用单线程操作
    mexecutorservice = executors.newsinglethreadexecutor();
    datalist = new arraylist<>();
  }

  @override
  protected void initviews() {
    this.start_tv = (button) findviewbyid(r.id.start_tv);
    this.listview = (listview) findviewbyid(r.id.listview);
  }

  @override
  protected void initevents() {
    //类似微信等应用按住说话进行录音,所以用ontouch事件
    this.start_tv.setontouchlistener(new view.ontouchlistener() {
      @override
      public boolean ontouch(view view, motionevent motionevent) {
        switch (motionevent.getaction()) {
          //按下操作
          case motionevent.action_down:
            //安卓6.0以上录音相应权限处理
            if (build.version.sdk_int > 22) {
              permissionform();
            } else {
              startrecord();
            }
            break;
          //松开操作
          case motionevent.action_cancel:
          case motionevent.action_up:
            stoprecord();
            break;
        }
        //对ontouch事件做了处理,返回true
        return true;
      }
    });
    //点击播放对应的录音文件
    this.listview.setonitemclicklistener(new adapterview.onitemclicklistener() {
      @override
      public void onitemclick(adapterview<?> adapterview, view view, int i, long l) {
        //使用mediaplayer播放声音文件
        startplay(datalist.get(i).getfile());
      }
    });
  }


  /**
   * @description 开始进行录音
   * @author ldm
   * @time 2017/2/9 9:18
   */
  private void startrecord() {
    start_tv.settext(r.string.stop_by_up);
    start_tv.setbackgroundresource(r.drawable.bg_gray_round);
    //异步任务执行录音操作
    mexecutorservice.submit(new runnable() {
      @override
      public void run() {
        //播放前释放资源
        releaserecorder();
        //执行录音操作
        recordoperation();
      }
    });
  }

  /**
   * @description 录音失败处理
   * @author ldm
   * @time 2017/2/9 9:35
   */
  private void recordfail() {
    maudiofile = null;
    mhandler.sendemptymessage(constant.record_fail);
  }

  /**
   * @description 录音操作
   * @author ldm
   * @time 2017/2/9 9:34
   */
  private void recordoperation() {
    //创建mediarecorder对象
    mmediarecorder = new mediarecorder();
    //创建录音文件,.m4a为mpeg-4音频标准的文件的扩展名
    maudiofile = new file(mfilepath + system.currenttimemillis() + ".m4a");
    //创建父文件夹
    maudiofile.getparentfile().mkdirs();
    try {
      //创建文件
      maudiofile.createnewfile();
      //配置mmediarecorder相应参数
      //从麦克风采集声音数据
      mmediarecorder.setaudiosource(mediarecorder.audiosource.mic);
      //设置保存文件格式为mp4
      mmediarecorder.setoutputformat(mediarecorder.outputformat.mpeg_4);
      //设置采样频率,44100是所有安卓设备都支持的频率,频率越高,音质越好,当然文件越大
      mmediarecorder.setaudiosamplingrate(44100);
      //设置声音数据编码格式,音频通用格式是aac
      mmediarecorder.setaudioencoder(mediarecorder.audioencoder.aac);
      //设置编码频率
      mmediarecorder.setaudioencodingbitrate(96000);
      //设置录音保存的文件
      mmediarecorder.setoutputfile(maudiofile.getabsolutepath());
      //开始录音
      mmediarecorder.prepare();
      mmediarecorder.start();
      //记录开始录音时间
      starttime = system.currenttimemillis();
    } catch (exception e) {
      e.printstacktrace();
      recordfail();
    }
  }


  /**
   * @description 结束录音操作
   * @author ldm
   * @time 2017/2/9 9:18
   */
  private void stoprecord() {
    start_tv.settext(r.string.speak_by_press);
    start_tv.setbackgroundresource(r.drawable.bg_white_round);
    //停止录音
    mmediarecorder.stop();
    //记录停止时间
    endtime = system.currenttimemillis();
    //录音时间处理,比如只有大于2秒的录音才算成功
    int time = (int) ((endtime - starttime) / 1000);
    if (time >= 3) {
      //录音成功,添加数据
      filebean bean = new filebean();
      bean.setfile(maudiofile);
      bean.setfilelength(time);
      datalist.add(bean);
      //录音成功,发message
      mhandler.sendemptymessage(constant.record_success);
    } else {
      maudiofile = null;
      mhandler.sendemptymessage(constant.record_too_short);
    }
    //录音完成释放资源
    releaserecorder();
  }

  /**
   * @description 翻放录音相关资源
   * @author ldm
   * @time 2017/2/9 9:33
   */
  private void releaserecorder() {
    if (null != mmediarecorder) {
      mmediarecorder.release();
      mmediarecorder = null;
    }
  }

  @override
  public void onclick(view view) {

  }

  @override
  protected void ondestroy() {
    super.ondestroy();
    //页面销毁,线程要关闭
    mexecutorservice.shutdownnow();
  }
  /*******6.0以上版本手机权限处理***************************/
  /**
   * @description 兼容手机6.0权限管理
   * @author ldm
   * @time 2016/5/24 14:59
   */
  private void permissionform() {
    if (contextcompat.checkselfpermission(this,
        manifest.permission.record_audio) != packagemanager.permission_granted || contextcompat.checkselfpermission(this,
        manifest.permission.write_external_storage) != packagemanager.permission_granted) {

      activitycompat.requestpermissions(this,
          new string[]{manifest.permission.record_audio, manifest.permission.write_external_storage},
          constant.permissions_request_for_audio);
    } else {
      startrecord();
    }

  }

  @override
  public void onrequestpermissionsresult(int requestcode,
                      @nonnull string[] permissions, @nonnull int[] grantresults) {

    if (requestcode == constant.permissions_request_for_audio) {
      if (grantresults[0] == packagemanager.permission_granted) {
        startrecord();
      }
      return;
    }
    super.onrequestpermissionsresult(requestcode, permissions, grantresults);
  }

  /**
   * @description 播放音频
   * @author ldm
   * @time 2017/2/9 16:54
   */
  private void playaudio(final file mfile) {
    if (null != mfile && !isplaying) {
      isplaying = true;
      mexecutorservice.submit(new runnable() {
        @override
        public void run() {
          startplay(mfile);
        }
      });
    }
  }

  /**
   * @description 开始播放音频文件
   * @author ldm
   * @time 2017/2/9 16:56
   */
  private void startplay(file mfile) {
    try {
      //初始化播放器
      mediaplayer = new mediaplayer();
      //设置播放音频数据文件
      mediaplayer.setdatasource(mfile.getabsolutepath());
      //设置播放监听事件
      mediaplayer.setoncompletionlistener(new mediaplayer.oncompletionlistener() {
        @override
        public void oncompletion(mediaplayer mediaplayer) {
          //播放完成
          playendorfail(true);
        }
      });
      //播放发生错误监听事件
      mediaplayer.setonerrorlistener(new mediaplayer.onerrorlistener() {
        @override
        public boolean onerror(mediaplayer mediaplayer, int i, int i1) {
          playendorfail(false);
          return true;
        }
      });
      //播放器音量配置
      mediaplayer.setvolume(1, 1);
      //是否循环播放
      mediaplayer.setlooping(false);
      //准备及播放
      mediaplayer.prepare();
      mediaplayer.start();
    } catch (ioexception e) {
      e.printstacktrace();
      //播放失败正理
      playendorfail(false);
    }

  }

  /**
   * @description 停止播放或播放失败处理
   * @author ldm
   * @time 2017/2/9 16:58
   */
  private void playendorfail(boolean isend) {
    isplaying = false;
    if (isend) {
      mhandler.sendemptymessage(constant.play_completion);
    } else {
      mhandler.sendemptymessage(constant.play_error);
    }
    if (null != mediaplayer) {
      mediaplayer.setoncompletionlistener(null);
      mediaplayer.setonerrorlistener(null);
      mediaplayer.stop();
      mediaplayer.reset();
      mediaplayer.release();
      mediaplayer = null;
    }
  }
}

页面布局

<linearlayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingleft="@dimen/activity_horizontal_margin"
    android:paddingright="@dimen/activity_horizontal_margin"
    android:paddingtop="@dimen/activity_vertical_margin"
    android:paddingbottom="@dimen/activity_vertical_margin">

  <button
      android:id="@+id/start_tv"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="开始录音"
      android:textsize="16sp"
      />

  <listview
      android:id="@+id/listview"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:divider="#d1d1d1"
      android:dividerheight="1dp"
      android:scrollbars="none"
      android:layout_margintop="10dp"
      android:layout_marginbottom="10dp"></listview>

</linearlayout>

对应资源文件strings.xml:

<resources>
  <string name="app_name">mediarecorder</string>
  <string name="record_fail">录音失败</string>
  <string name="time_too_short">时间太短,请重新录音</string>
  <string name="play_over">播放完成</string>
  <string name="play_error">抱歉,播放发生异常</string>
  <string name="stop_by_up">松开停止录音</string>
  <string name="speak_by_press">按住说话</string>
  <string name="start_record">开始录音</string>
  <string name="stop_record">停止录音</string>
</resources>

录音相关权限 :

<!--sd卡权限-->
<uses-permission android:name="android.permission.write_external_storage"/>
<!--录音权限-->
<uses-permission android:name="android.permission.record_audio"/>


安卓录制播放音频:https://github.com/ldm520/android_media

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: