Android使用MediaRecorder实现录音及播放
程序员文章站
2023-12-18 17:14:52
现在项目中有使用到音视频相关技术,在参考了网上各种大牛的资料及根据自己项目实际情况(兼容安卓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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android使用MediaRecorder实现录音及播放
-
Android 使用ViewPager实现左右循环滑动及轮播效果
-
android 通过MediaRecorder实现简单的录音示例
-
Android录音--AudioRecord、MediaRecorder的使用
-
Android使用ListView实现下拉刷新及上拉显示更多的方法
-
ios 流媒体播放器实现流程及FreeStreamer的使用的示例
-
Android编程实现获取系统内存、CPU使用率及状态栏高度的方法示例
-
Android中使用Handler及Countdowntimer实现包含倒计时的闪屏页面
-
android 通过MediaRecorder实现简单的录音示例
-
Android录音--AudioRecord、MediaRecorder的使用