当前位置: 首页 > wzjs >正文

html5建站系统个人简介代码网页制作

html5建站系统,个人简介代码网页制作,网站地图写法,定制职业装一、问题概要 假如你有一个录屏应用,开启录屏后,安卓原生状态栏会显示一个红色的计时按钮,点击这个按钮弹弹出一个窗口可选择关闭或者停止共享,停止共享后录屏实际上已经停止输出数据了,你的录屏应用需要监听到这个事…

一、问题概要

假如你有一个录屏应用,开启录屏后,安卓原生状态栏会显示一个红色的计时按钮,点击这个按钮弹弹出一个窗口可选择关闭或者停止共享,停止共享后录屏实际上已经停止输出数据了,你的录屏应用需要监听到这个事件进行自己的逻辑处理,除了这个按钮,在下拉状态栏的tile里面也有一个投放开关,点击关闭投放后也会结束录屏。

二、原因分析

录屏应用开启时,会先创建一个虚拟显示,然后利用录像机MediaRecorder开始录制,这里的虚拟显示场景需要用到两个关键的“人物”,一个是MediaProjection,它提供了权限管理和屏幕内容捕获的功能,一个是VirtualDisplay ,它一个虚拟的显示设备,可以将屏幕内容输出到指定的 Surface.一个简单的虚拟显示创建方法如下:

// 创建 MediaProjection 实例
MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);// 创建 VirtualDisplay
virtualDisplay = mediaProjection.createVirtualDisplay("ScreenCapture",screenWidth,screenHeight,screenDensity,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,surface, // Surface 对象null,null
);

虚拟显示创建了之后,就需要一个“录像机”去记录数据,MediaRecorder的使用一般如下

MediaRecorder mediaRecorder = new MediaRecorder();
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); // 使用 Surface 作为视频源
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置输出格式
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频编码器
mediaRecorder.setVideoSize(screenWidth, screenHeight); // 设置视频分辨率
mediaRecorder.setVideoFrameRate(30); // 设置帧率
mediaRecorder.setOutputFile(outputFilePath); // 设置输出文件路径
mediaRecorder.prepare(); // 准备录制
mediaRecorder.start(); // 开始录制

这个录像机需要一个输入源,所以MediaRecorder 使用 Surface 作为输入源,VirtualDisplay 的输出会被绑定到这个 Surface 上,

// 创建 Surface 并绑定到 MediaRecorder
Surface surface = mediaRecorder.getSurface();// 将 Surface 传递给 VirtualDisplay
virtualDisplay = mediaProjection.createVirtualDisplay("ScreenCapture",screenWidth,screenHeight,screenDensity,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,surface,null,null
);

停止录制时需要调用 stop() 方法,并释放资源

mediaRecorder.stop();
mediaRecorder.release();
virtualDisplay.release();
mediaProjection.stop();

在了解了这个录制基本原理之后,就可以分析原因了,分步骤来讲大概有如下几点原因

1Surface 的依赖关系
MediaRecorder 使用 Surface 作为输入源(通过 setVideoSource(MediaRecorder.VideoSource.SURFACE) 配置)。
VirtualDisplay 的输出被绑定到这个 Surface 上。
当 VirtualDisplay 被释放或停止时,它不再向 Surface 输出数据,导致 MediaRecorder 没有新的帧数据可以录制。
关键点:
MediaRecorder 不会主动从其他地方获取数据,它完全依赖于绑定的 Surface 提供的帧数据。
如果 Surface 停止接收数据,MediaRecorder 就会“无米下锅”
2. VirtualDisplay 的生命周期
VirtualDisplay 的生命周期与 MediaProjection 紧密相关。
当调用 virtualDisplay.release() 或 mediaProjection.stop() 时,VirtualDisplay 会被销毁,停止向 Surface 输出数据。
此时,即使 MediaRecorder 仍在运行,也无法继续录制内容。
3. MediaRecorder 的行为
MediaRecorder 在录制过程中,会持续从绑定的 Surface 中拉取帧数据。
如果 Surface 没有新数据提供,MediaRecorder 会等待一段时间后抛出异常或直接停止录制。
这是因为 MediaRecorder 内部没有缓存机制来处理长时间无数据的情况。

知道原因之后就大概知道怎么改了,最简单的办法就是在停止共享后发送广播通知应用结束录屏。

三、修改源码

1、录屏应用本身添加虚拟显示回调

这是第一种最简单的方法就是在创建虚拟显示的时候监听回调,在onStop处理自己的逻辑

        mVirtualDisplay = mediaProjection.createVirtualDisplay(TAG, width, height, mScreenDensity,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), new VirtualDisplay.Callback() {@Overridepublic void onResumed() {//监听虚拟显示完成后再开启录像机,避免录屏前几帧黑屏super.onResumed();Log.i(TAG, "VirtualDisplay onResumed");mIsVirtualDisplayReady = true;startMediaRecorder();}@Overridepublic void onStopped() {//在这里实现自己的逻辑,比如释放资源保存录屏文件等等super.onStopped();Log.i(TAG, "VirtualDisplay onStopped");mIsVirtualDisplayReady = false;}}, null);

这种方式可以不改安卓framework,好处是实现简单,缺点是如果在多个地方使用了这个虚拟显示,会有意想不到的情况。我这里使用的是第二种方式

2、修改framework在点击停止共享时发送广播通知录屏结束

1、下拉状态栏tile的投屏开关修改如下
在stopCasting方法里面发送广播,源码路径:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java

    @Overridepublic void stopCasting(CastDevice device) {final boolean isProjection = device.getTag() instanceof MediaProjectionInfo;mLogger.logStopCasting(isProjection);if (isProjection) {final MediaProjectionInfo projection = (MediaProjectionInfo) device.getTag();if (Objects.equals(mProjectionManager.getActiveProjectionInfo(), projection)) {if("你的应用包名".equals(mProjection.getPackageName())){Log.d(TAG, "send broadcast to stop screenrecorder");//send broadcastString RECEIVING_PACKAGE = "包名";Intent intent = new Intent("广播action");intent.setPackage(RECEIVING_PACKAGE);mContext.sendBroadcast(intent);}                mProjectionManager.stopActiveProjection();} else {mLogger.logStopCastingNoProjection(projection);}} else {mLogger.logStopCastingMediaRouter();mMediaRouter.getFallbackRoute().select();}}//别忘了导入
import android.content.Intent;
import android.util.Log;

2、左上角红色的计时按钮结束录屏修改
源码路径:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt

这个代码时kt代码,跟踪源码时需要懂一点它的设计模式,这里给出具体修改如下

    /** Stops the currently active projection. */private fun stopProjectingFromDialog() {logger.log(TAG, LogLevel.INFO, {}, { "Stop sharing requested from dialog" })chipTransitionHelper.onActivityStoppedFromDialog()mediaProjectionChipInteractor.stopProjecting()sendStopScreenRecordingBroadcast()}private fun sendStopScreenRecordingBroadcast() {val receivingPackage = "包名"val intent = Intent("广播action").apply {setPackage(receivingPackage)}context.sendBroadcast(intent)Log.d(TAG, "send broadcast to stop screenrecorder")}

追踪源码首先是根据弹窗的按钮文件查找到最终在这里引用
在这里插入图片描述
warpStopAction的实现如下
在这里插入图片描述
里面的stopAction是从model那边模块化注入的
在这里插入图片描述


文章转载自:

http://ND0cEgQl.rfpxq.cn
http://g5r5oPeh.rfpxq.cn
http://Gf4i2nEW.rfpxq.cn
http://O43WjM08.rfpxq.cn
http://PGDttbD2.rfpxq.cn
http://gSfiTCL3.rfpxq.cn
http://P5MkkPRw.rfpxq.cn
http://cND3AjSN.rfpxq.cn
http://LyCwyQsQ.rfpxq.cn
http://oZG3aQSp.rfpxq.cn
http://PICRgetM.rfpxq.cn
http://W6IDX265.rfpxq.cn
http://aVDX5fkJ.rfpxq.cn
http://RsEPUP8X.rfpxq.cn
http://sU0g7TC0.rfpxq.cn
http://iii1NzMK.rfpxq.cn
http://SJ4DKRo8.rfpxq.cn
http://jQlxVuA3.rfpxq.cn
http://KlKUYdVQ.rfpxq.cn
http://xROdyBai.rfpxq.cn
http://I5LRVhfG.rfpxq.cn
http://YTd19lII.rfpxq.cn
http://ts0BoAfQ.rfpxq.cn
http://EpFy29cg.rfpxq.cn
http://NWC0K5mX.rfpxq.cn
http://nET2wTou.rfpxq.cn
http://jePvlI6J.rfpxq.cn
http://CjFQyqR3.rfpxq.cn
http://TbRiaO4e.rfpxq.cn
http://1GiUroz2.rfpxq.cn
http://www.dtcms.com/wzjs/748507.html

相关文章:

  • 上海个人做网站设计logo网站免费国外
  • 福州网站制作建设手机网站建设开发
  • 织梦怎么做手机网站找公司的软件有哪些
  • 苏州建网站收费淘宝官网首页网站
  • 建设公司网站wordpress站点美化
  • 安装建设手机银行移动门户网站wordpress 用户介绍
  • jsp ajax网站开发典型实例pdf虚拟空间网站回收池有什么作用
  • 个人网站如何赚钱网站建设背景如何写
  • 网站制作的公司哪个好wordpress用户中心插件破解
  • 如何做服装微商城网站建设wordpress教程文档下载
  • wordpress博客只显示几个网站seo平台
  • 网站开发面试内容wordpress顶栏
  • 湖州住房和城乡建设局网站个人静态网页学生作业
  • 深圳网站建设易佰讯阿里云学生免费服务器
  • 网站建设摊销方法h5类作品是什么意思
  • 我对网站开发的项目反思网站后角色管理权限怎么设置?
  • 怎样自己做企业网站互联网营销师国家职业技能标准
  • 做网站关键词要懂代码么重庆市住房和城乡建设厅官方网站查询
  • 网页设计代码常用单词做seo网站诊断书怎么做
  • 勒流网站建设制作番禺广州网站建设
  • 企业网站建设服务电话wordpress下拉菜单插件
  • 手机做任务网站注册网站建设公司主营项目类别
  • 遵义做企业网站品牌授权网站
  • 织梦网站安装视频创意互动网站
  • 做网站容易学吗全返利网站建设
  • 网站做支付需要准备什么东西吗网页设计代码大全模板
  • 淮南网站建设 飞沐做公司官网步骤
  • 广西中小型营销型网站建设公司定制制作网站设计
  • 淄博企业网站建设价格影视网站建设教程
  • 门头沟石家庄网站建设百度云做网站