android MediaRecorder实现录屏时带录音功能
下面说说android的事把
最近是不是也会遇到需求中需要用到录屏录音的功能,最近也是遇到的现在整理完记录一下
首先呢,录音录屏需要权限先贴一个动态权限类
publicclassTalAllow{ /** *RECORD_AUDIO音频权限 *WRITE_EXTERNAL_STORAGE写入权限 *CAMERA相机权限 */ publicstaticvoidrequestPermissions(Contextcontext,intallowCode){ ArrayListps=newArrayList<>(); intper=ContextCompat.checkSelfPermission(context,Manifest.permission.RECORD_AUDIO); if(per!=PackageManager.PERMISSION_GRANTED){ ps.add(Manifest.permission.RECORD_AUDIO); } per=ContextCompat.checkSelfPermission(context,Manifest.permission.WRITE_EXTERNAL_STORAGE); if(per!=PackageManager.PERMISSION_GRANTED){ ps.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); } per=ContextCompat.checkSelfPermission(context,Manifest.permission.CAMERA); if(per!=PackageManager.PERMISSION_GRANTED){ ps.add(Manifest.permission.CAMERA); } per=ContextCompat.checkSelfPermission(context,Manifest.permission.READ_PHONE_STATE); if(per!=PackageManager.PERMISSION_GRANTED){ ps.add(Manifest.permission.READ_PHONE_STATE); } Log.d(TAG,"requestPermissions:ps="+ps.size()); if(!ps.isEmpty()){ String[]ps3=newString[ps.size()]; ps.toArray(ps3); ActivityCompat.requestPermissions((Activity)context,ps3,allowCode); } } }
有需求需要判断权限的呢插入个链接(上面那个类code码为100)
判断是否有权限
下面重点来了
首先说明一下这个录屏和录音是在服务里面做的,所以呢贴一个服务类
这个代码绝对有质量做了很多处理,下面一行一行解读把
//首先呢实现的是Handle.Callback接口主要是做时间及计时时间回调的,会重新写HandleMessage方法,其实我个觉得跟在括号{}里面重写没啥区别就是简洁页面 publicclassTalScreenRecordServiceextendsServiceimplementsHandler.Callback{ //这个就不解释了吧log privatestaticfinalStringTAG="TalScreenRecordService"; //这个类是管理类拿到服务后会通过下面的类申请录屏,点击允许, //其中会回调两个参数,code码和data,都在ActivityForResult中进行判断code privateMediaProjectionManagermProjectionManager; //这个会拿到申请的结果 privateMediaProjectionmMediaProjection; //这个类就是我们主要的录屏录音的类啦 privateMediaRecordermMediaRecorder; //这个就是我们要获取录制屏幕的大小,像素,等等一些数据 //关于这类更详细的介绍https://blog.csdn.net/qq_16628781/article/details/62038163 privateVirtualDisplaymVirtualDisplay; //是否正在录制false没有录制 privatebooleanmIsRunning; //获取屏幕的宽高和像素密度稍后贴类 privateintmRecordWidth=TalScreenParams.getScreenWidth(); privateintmRecordHeight=TalScreenParams.getScreenWidth(); privateintmScreenDpi=TalScreenParams.getScreenDpi(); //codedata就是上面说的允许后回调 privateintmResultCode; privateIntentmResultData; //录屏文件的保存地址 privateStringmRecordFilePath; privateHandlermHandler; //已经录制多少秒了 privateintmRecordSeconds=0; //handle发送消息时的what privatestaticfinalintMSG_TYPE_COUNT_DOWN=110; //这个是继承Service必须重写的方法这是使用的BindService(生命周期的长短跟activity一致) @Override publicIBinderonBind(Intentintent){ returnnewRecordBinder(); } //说一说这个返回值的问题吧 //START_STICKY粘性返回,一次失败,多次启动,不保留Intent对象 //关于返回值问题https://blog.csdn.net/github_37663523/article/details/78811539 @Override publicintonStartCommand(Intentintent,intflags,intstartId){ returnSTART_STICKY; } @Override publicvoidonCreate(){ super.onCreate(); //没有录制 mIsRunning=false; //创建对象在create方法里只执行一次 mMediaRecorder=newMediaRecorder(); //由于实现了CallBack接口,在这里注册一下接口(个人觉得高大的写法,简洁) mHandler=newHandler(Looper.getMainLooper(),this); } @Override publicvoidonDestroy(){ super.onDestroy(); } //数据不为空 publicbooleanisReady(){ returnmMediaProjection!=null&&mResultData!=null; } //清除的方法避免内存泄漏相信都看得懂 @RequiresApi(api=Build.VERSION_CODES.LOLLIPOP) publicvoidclearRecordElement(){ clearAll(); if(mMediaRecorder!=null){ mMediaRecorder.reset(); mMediaRecorder.release(); mMediaRecorder=null; } mResultData=null; //不执行的时候false mIsRunning=false; } //这个就是给是否正在录屏提供一个get方法 publicbooleanismIsRunning(){ returnmIsRunning; } //这个就是设置数据的方法在ActivityForResult中设置数据,说明是允许录屏的 @TargetApi(Build.VERSION_CODES.LOLLIPOP) publicvoidsetResultData(intresultCode,IntentresultData){ mResultCode=resultCode; mResultData=resultData; //拿到这个管理,看不懂跟上面注释结合看 mProjectionManager=(MediaProjectionManager)getSystemService(Context.MEDIA_PROJECTION_SERVICE); //getMediaProjection(code,data)不知道这样写看不看的董 //说白了MediaProjectionManager是申请权限MediaProjection是获取申请结果,防止别人调取隐私 //再通过上面的setResultData方法获取到ActivityForResult中的code,data if(mProjectionManager!=null){ mMediaProjection=mProjectionManager.getMediaProjection(mResultCode,mResultData); } } //开始录制了 @RequiresApi(api=Build.VERSION_CODES.LOLLIPOP) publicbooleanstartRecord(){ //代码执行顺序(false,目前没录屏) if(mIsRunning){ returnfalse; } //再次创建,防止异常 if(mMediaProjection==null){ mMediaProjection=mProjectionManager.getMediaProjection(mResultCode,mResultData); } //关于文件路径还有录屏的一些参数问题 setUpMediaRecorder(); //关于获取录制屏幕的大小,像素,等等一些数据 createVirtualDisplay(); //开始录制 mMediaRecorder.start(); //稍后贴类监听录制情况 TalScreenUtils.startRecord(); //最多录制三分钟 mHandler.sendEmptyMessageDelayed(MSG_TYPE_COUNT_DOWN,1000); //录制时为true mIsRunning=true; Log.d(TAG,"startRecord"); returntrue; } //停止的方法 @RequiresApi(api=Build.VERSION_CODES.LOLLIPOP) publicbooleanstopRecord(Stringtip){ Log.d(TAG,"stopRecord:first"); //mIsRunning默认值为false!mIsRunning就是true。。 if(!mIsRunning){ returnfalse; } mIsRunning=false; Log.w(TAG,"stopRecordmiddle"); try{ //停止抓取异常,该置空的为空 mMediaRecorder.stop(); mMediaRecorder.reset(); mMediaRecorder=null; mVirtualDisplay.release(); mMediaProjection.stop(); Log.w(TAG,"stopRecord"); }catch(Exceptione){ e.printStackTrace(); mMediaRecorder.release(); mMediaRecorder=null; Log.w(TAG,"stopRecordexception"); } mMediaProjection=null; //停止时移出这条消息what mHandler.removeMessages(MSG_TYPE_COUNT_DOWN); //停止的监听tip是处理一些突发情况比如内存不足 TalScreenUtils.stopRecord(tip); Log.i(TAG,"stopRecord:"+mRecordFilePath); //录制时间不到两秒就删除录制文件 if(mRecordSeconds<=2){ TalFileUtils.deleteSDFile(mRecordFilePath); }else{ //录制的视频库,将数据添加到媒体库 //这个算是应用程序之间共享数据,把自己应用的数据添加到手机的媒体库ContentResolver //举个例子,代码添加手机联系人到自己的联系人列表,或者代码添加图片到自己的图库,还有不懂得,贴个链接 //https://blog.csdn.net/bzlj2912009596/article/details/80248272 TalFileUtils.fileScanVideo(this,mRecordFilePath,1280,720,mRecordSeconds); } //mRecordFilePath=null; mRecordSeconds=0; returntrue; } //下面是关于处理在一些activityorfragment中生命周期的做法 publicvoidpauseRecord(){ if(mMediaRecorder!=null){ if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){ mMediaRecorder.pause(); } } } publicvoidresumeRecord(){ if(mMediaRecorder!=null){ if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){ mMediaRecorder.resume(); } } } //这个就是刚才讲过的绘制窗口大小,dpi问题VirtualDisplay @RequiresApi(api=Build.VERSION_CODES.LOLLIPOP) privatevoidcreateVirtualDisplay(){ mVirtualDisplay=mMediaProjection.createVirtualDisplay("MainScreen",1280,720,mScreenDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mMediaRecorder.getSurface(),null,null); } //这个主要是路径,还有设置一些录制视频参数问题separator为字节,占位用 @TargetApi(Build.VERSION_CODES.LOLLIPOP) privatevoidsetUpMediaRecorder(){ mRecordFilePath=getSaveDirectory()+File.separator+System.currentTimeMillis()+".mp4"; Log.i(TAG,"setUpMediaRecorder:"+mRecordFilePath); if(mMediaRecorder==null){ mMediaRecorder=newMediaRecorder(); } //设置音频源 mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); //设置视频源 mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); //设置输出的编码格式 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); if(mRecordFilePath!=null){ mMediaRecorder.setOutputFile(mRecordFilePath); }elseif(mRecordFilePath==null){ mMediaRecorder.setOutputFile(mRecordFilePath); } //设置录屏时屏幕大小,这个可跟mVirtualDisplay一起控制屏幕大小 //mVirtualDisplay是将屏幕设置成多大多小,setVideoSize是输出文件时屏幕多大多小 mMediaRecorder.setVideoSize(1280,720); //图像编码H264较好还有其他选择 mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); //音频编码 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //设置码率高清的话的要数越大 mMediaRecorder.setVideoEncodingBitRate((int)(1280*720*2.6)); //设置帧率,该帧率必须是硬件支持的,可以通过Camera.CameraParameter.getSupportedPreviewFpsRange()方法获取相机支持的帧率 mMediaRecorder.setVideoFrameRate(20); try{ //准备 mMediaRecorder.prepare(); }catch(IOExceptione){ e.printStackTrace(); } } @RequiresApi(api=Build.VERSION_CODES.LOLLIPOP) publicvoidclearAll(){ if(mMediaProjection!=null){ mMediaProjection.stop(); mMediaProjection=null; } } //路径 publicStringgetRecordFilePath(){ returnmRecordFilePath; } //sd下绝对路径,先判断sd卡是否挂载 publicStringgetSaveDirectory(){ if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ returnEnvironment.getExternalStorageDirectory().getAbsolutePath(); }else{ returnnull; } } //这是实现了Handle.CallBack中重写方法handleMessage @RequiresApi(api=Build.VERSION_CODES.LOLLIPOP) @Override publicbooleanhandleMessage(Messagemsg){ switch(msg.what){ caseMSG_TYPE_COUNT_DOWN:{ Stringstr=null; //这是内存 booleanenough=TalFileUtils.getSDFreeMemory()/(1024*1024)<4; if(enough){ //空间不足,停止录屏 str="空间不足"; //停止录屏时通过接口回调一个信息,是因为什么停止录屏的 stopRecord(str); mRecordSeconds=0; break; } mRecordSeconds++; intminute=0,second=0; if(mRecordSeconds>=60){ minute=mRecordSeconds/60; second=mRecordSeconds%60; }else{ second=mRecordSeconds; } TalScreenUtils.onRecording("0"+minute+":"+(second<10?"0"+second:second+"")); if(mRecordSeconds<5*60){ mHandler.sendEmptyMessageDelayed(MSG_TYPE_COUNT_DOWN,1000); }elseif(mRecordSeconds==5*60){ str="录制已到限定时长"; stopRecord(str); mRecordSeconds=0; } break; } } returntrue; } publicclassRecordBinderextendsBinder{ publicTalScreenRecordServicegetRecordService(){ returnTalScreenRecordService.this; } } }
下面贴关于手机像素还有dpi的类
publicclassTalScreenParams{ privatestaticintmScreenWidth; privatestaticintmScreenHeight; privatestaticintmScreenDpi; publicstaticvoidinit(Activityactivity){ Displaydisplay=activity.getWindowManager().getDefaultDisplay(); DisplayMetricsmetrics=newDisplayMetrics(); display.getMetrics(metrics); mScreenWidth=metrics.widthPixels; mScreenHeight=metrics.heightPixels; mScreenDpi=metrics.densityDpi; } publicstaticintgetScreenWidth(){ returnmScreenWidth; } publicstaticintgetScreenHeight(){ returnmScreenHeight; } publicstaticintgetScreenDpi(){ returnmScreenDpi; }
下面贴关于删除文件,添加到媒体库的类这里就使用到了ContentResolver
publicclassTalFileUtils{ /** *删除SD卡中的文件或目录 * *@parampath *@return */ publicstaticbooleandeleteSDFile(Stringpath){ returndeleteSDFile(path,false); } /** *删除SD卡中的文件或目录 * *@parampath *@paramdeleteParenttrue为删除父目录 *@return */ publicstaticbooleandeleteSDFile(Stringpath,booleandeleteParent){ if(TextUtils.isEmpty(path)){ returnfalse; } Filefile=newFile(path); if(!file.exists()){ //不存在 returntrue; } returndeleteFile(file,deleteParent); } /** *@paramfile *@paramdeleteParenttrue为删除父目录 *@return */ publicstaticbooleandeleteFile(Filefile,booleandeleteParent){ booleanflag=false; if(file==null){ returnflag; } if(file.isDirectory()){ //是文件夹 File[]files=file.listFiles(); if(files.length>0){ for(inti=0;i还有一个类是为整个Service提供了便捷访问的类,将一些监听service中的变化放到集合里来做
publicclassTalScreenUtils{ privatestaticTalScreenRecordServices_ScreenRecordService; privatestaticLists_RecordListener=newArrayList<>(); privatestaticList s_PageRecordListener=newArrayList<>(); //true,录制结束的提示语正在显示 publicstaticbooleans_IsRecordingTipShowing=false; /** *录屏功能5.0+的手机才能使用 *@return */ publicstaticbooleanisScreenRecordEnable(){ returnBuild.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP; } publicstaticvoidsetScreenService(TalScreenRecordServicescreenService){ s_ScreenRecordService=screenService; } publicstaticvoidclear(){ if(isScreenRecordEnable()&&s_ScreenRecordService!=null){ s_ScreenRecordService.clearAll(); s_ScreenRecordService=null; } if(s_RecordListener!=null&&s_RecordListener.size()>0){ s_RecordListener.clear(); } if(s_PageRecordListener!=null&&s_PageRecordListener.size()>0){ s_PageRecordListener.clear(); } } /** *开始录制 */ publicstaticvoidstartScreenRecord(Activityactivity,intrequestCode){ if(isScreenRecordEnable()){ if(s_ScreenRecordService!=null&&!s_ScreenRecordService.ismIsRunning()){ if(!s_ScreenRecordService.isReady()){ MediaProjectionManagermediaProjectionManager=(MediaProjectionManager)activity. getSystemService(Context.MEDIA_PROJECTION_SERVICE); if(mediaProjectionManager!=null){ Intentintent=mediaProjectionManager.createScreenCaptureIntent(); PackageManagerpackageManager=activity.getPackageManager(); if(packageManager.resolveActivity(intent,PackageManager.MATCH_DEFAULT_ONLY)!=null){ //存在录屏授权的Activity activity.startActivityForResult(intent,requestCode); }else{ Toast.makeText(activity,"不能录音",Toast.LENGTH_SHORT).show(); } } }else{ s_ScreenRecordService.startRecord(); } } } } /** *获取用户允许录屏后,设置必要的数据 *@paramresultCode *@paramresultData */ publicstaticvoidsetUpData(intresultCode,IntentresultData)throwsException{ if(isScreenRecordEnable()){ if(s_ScreenRecordService!=null&&!s_ScreenRecordService.ismIsRunning()){ s_ScreenRecordService.setResultData(resultCode,resultData); s_ScreenRecordService.startRecord(); } } } /** *停止录制 */ publicstaticvoidstopScreenRecord(Contextcontext){ if(isScreenRecordEnable()){ if(s_ScreenRecordService!=null&&s_ScreenRecordService.ismIsRunning()){ Stringstr="停止录制"; s_ScreenRecordService.stopRecord(str); } } } /** *获取录制后的文件地址 *@return */ publicstaticStringgetScreenRecordFilePath(){ if(isScreenRecordEnable()&&s_ScreenRecordService!=null){ returns_ScreenRecordService.getRecordFilePath(); } returnnull; } /** *判断当前是否在录制 *@return */ publicstaticbooleanisCurrentRecording(){ if(isScreenRecordEnable()&&s_ScreenRecordService!=null){ returns_ScreenRecordService.ismIsRunning(); } returnfalse; } /** *true,录制结束的提示语正在显示 *@return */ publicstaticbooleanisRecodingTipShow(){ returns_IsRecordingTipShowing; } publicstaticvoidsetRecordingStatus(booleanisShow){ s_IsRecordingTipShowing=isShow; } /** *系统正在录屏,app录屏会有冲突,清理掉一些数据 */ publicstaticvoidclearRecordElement(){ if(isScreenRecordEnable()){ if(s_ScreenRecordService!=null){ s_ScreenRecordService.clearRecordElement(); } } } publicstaticvoidaddRecordListener(RecordListenerlistener){ if(listener!=null&&!s_RecordListener.contains(listener)){ s_RecordListener.add(listener); } } publicstaticvoidremoveRecordListener(RecordListenerlistener){ if(listener!=null&&s_RecordListener.contains(listener)){ s_RecordListener.remove(listener); } } publicstaticvoidaddPageRecordListener(OnPageRecordListenerlistener){ if(listener!=null&&!s_PageRecordListener.contains(listener)){ s_PageRecordListener.add(listener); } } publicstaticvoidremovePageRecordListener(OnPageRecordListenerlistener){ if(listener!=null&&s_PageRecordListener.contains(listener)){ s_PageRecordListener.remove(listener); } } publicstaticvoidonPageRecordStart(){ if(s_PageRecordListener!=null&&s_PageRecordListener.size()>0){ for(OnPageRecordListenerlistener:s_PageRecordListener){ listener.onStartRecord(); } } } publicstaticvoidonPageRecordStop(){ if(s_PageRecordListener!=null&&s_PageRecordListener.size()>0){ for(OnPageRecordListenerlistener:s_PageRecordListener){ listener.onStopRecord(); } } } publicstaticvoidonPageBeforeShowAnim(){ if(s_PageRecordListener!=null&&s_PageRecordListener.size()>0){ for(OnPageRecordListenerlistener:s_PageRecordListener){ listener.onBeforeShowAnim(); } } } publicstaticvoidonPageAfterHideAnim(){ if(s_PageRecordListener!=null&&s_PageRecordListener.size()>0){ for(OnPageRecordListenerlistener:s_PageRecordListener){ listener.onAfterHideAnim(); } } } publicstaticvoidstartRecord(){ if(s_RecordListener.size()>0){ for(RecordListenerlistener:s_RecordListener){ listener.onStartRecord(); Log.i("xxx","startRecord:"); } } } publicstaticvoidpauseRecord(){ if(s_RecordListener.size()>0){ for(RecordListenerlistener:s_RecordListener){ listener.onPauseRecord(); } } } publicstaticvoidresumeRecord(){ if(s_RecordListener.size()>0){ for(RecordListenerlistener:s_RecordListener){ listener.onResumeRecord(); } } } publicstaticvoidonRecording(StringtimeTip){ if(s_RecordListener.size()>0){ for(RecordListenerlistener:s_RecordListener){ listener.onRecording(timeTip); } } } publicstaticvoidstopRecord(StringstopTip){ if(s_RecordListener.size()>0){ for(RecordListenerlistener:s_RecordListener){ listener.onStopRecord(stopTip); } } } publicinterfaceRecordListener{ voidonStartRecord(); voidonPauseRecord(); voidonResumeRecord(); voidonStopRecord(StringstopTip); voidonRecording(StringtimeTip); } publicinterfaceOnPageRecordListener{ voidonStartRecord(); voidonStopRecord(); voidonBeforeShowAnim(); voidonAfterHideAnim(); } } 到了最后了,是一些调用时的内容
publicclassMainActivityextendsAppCompatActivity{ privatestaticfinalStringTAG=MainActivity.class.getSimpleName(); privateButtonmBtn; privatefinalintREQUEST_ALLOW=100; privateButtonmButton; //bindService需要创建连接 privateServiceConnectionmConnection=newServiceConnection(){ @Override publicvoidonServiceConnected(ComponentNamename,IBinderservice){ //启动service TalScreenRecordService.RecordBinderrecordBinder=(TalScreenRecordService.RecordBinder)service; TalScreenRecordServicerecordService=recordBinder.getRecordService(); //这个其实是传值在使用的activity中拿到Service TalScreenUtils.setScreenService(recordService); } @Override publicvoidonServiceDisconnected(ComponentNamename){ } }; //开启service,意图跳转到service,别忘了AndroidManifest里面需要注册这个service哦 privatevoidstartService(){ Intentintent=newIntent(MainActivity.this,TalScreenRecordService.class); bindService(intent,mConnection,BIND_AUTO_CREATE); } @Override protectedvoidonCreate(finalBundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtn=findViewById(R.id.btn); mButton=findViewById(R.id.button2); initView(); //两个按钮一个开始一个结束xml不贴了 mBtn.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ if(TalFileUtils.getFreeMem(MainActivity.this)<100){ Toast.makeText(MainActivity.this,"手机内存不足,请清理后再进行录屏",Toast.LENGTH_SHORT).show(); return; } //开始录屏录音 TalScreenUtils.startScreenRecord(MainActivity.this,REQUEST_ALLOW); } }); mButton.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ stop(); Log.i(TAG,"onClick:"+stop()); } //停止录屏录音返回路径 privateStringstop(){ TalScreenUtils.stopScreenRecord(MainActivity.this);//停止 returnTalScreenUtils.getScreenRecordFilePath(); } }); } @Override protectedvoidonStart(){ super.onStart(); } privatevoidinitView(){ //权限申请 TalAllow.requestPermissions(this,REQUEST_ALLOW); //获取屏幕大小在onCreate里面初始化就可以获取 TalScreenParams.init(this); startService(); } @Override protectedvoidonStop(){ super.onStop(); //在对用户可见不可交互的时候防止异常 TalScreenUtils.clear(); } //打印权限获取情况日志 @Override publicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions,@NonNullint[]grantResults){ Toast.makeText(this,permissions[0]+"\n"+grantResults[0],Toast.LENGTH_SHORT).show(); super.onRequestPermissionsResult(requestCode,permissions,grantResults); } //在用户允许录屏后拿到确定的code跟data @Override protectedvoidonActivityResult(intrequestCode,intresultCode,@NullableIntentdata){ super.onActivityResult(requestCode,resultCode,data); if(requestCode==REQUEST_ALLOW&&data!=null){ try{ //设置数据,在用户允许后调用了开始录屏的方法 TalScreenUtils.setUpData(resultCode,data); //拿到路径 StringscreenRecordFilePath=TalScreenUtils.getScreenRecordFilePath(); if(screenRecordFilePath==null){ Toast.makeText(this,"空的",Toast.LENGTH_SHORT).show(); } Toast.makeText(MainActivity.this,""+screenRecordFilePath,Toast.LENGTH_SHORT).show(); Log.i("zlq","onClick:"+screenRecordFilePath); }catch(Exceptione){ e.printStackTrace(); } }else{ Toast.makeText(this,"禁止录屏",Toast.LENGTH_SHORT).show(); } } @Override protectedvoidonDestroy(){ super.onDestroy(); unbindService(mConnection); } }至此,一个还算比较完整的录屏录音功能就可以实现,不足之处请批评指正
总结
到此这篇关于androidMediaRecorder录屏时带录音功能实现的文章就介绍到这了,更多相关androidMediaRecorder录屏带录音内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。