Media Projection横竖屏切换时VirtualDisplay销毁,能否避免重启录屏?
关于MediaProjection API横竖屏切换时VirtualDisplay的更新问题
你的想法其实并非不切实际,但受限于Android MediaProjection API和VirtualDisplay的底层设计,目前没办法直接更新已创建的VirtualDisplay对象——不过我们可以通过优化重建流程,达到近似“无缝更新”的效果,同时保证录屏仅在你主动点击停止按钮时终止。
为什么VirtualDisplay会被销毁?
当屏幕横竖屏切换时,系统的显示配置(包括屏幕宽高、密度)会发生变化,而VirtualDisplay是基于创建时传入的尺寸和密度参数初始化的,这些参数在创建后是不可修改的:MediaProjection API并没有提供任何方法来更新现有VirtualDisplay的尺寸、密度等核心属性。
更关键的是,系统在检测到显示配置变更时,会自动销毁尺寸不匹配的VirtualDisplay,这是系统层面的保护机制,开发者无法阻止这个行为。
替代方案:无缝重建VirtualDisplay
虽然不能避免销毁重建,但我们可以优化这个过程,让用户完全感知不到录屏的“中断”:
- 保留MediaProjection实例:不要在横竖屏切换时释放MediaProjection,这样就不需要重新请求屏幕捕获权限,省去了用户授权的步骤。
- 监听配置变更:在Activity的Manifest声明中添加
android:configChanges="orientation|screenSize|smallestScreenSize",避免Activity重启,减少状态丢失。 - 快速重建VirtualDisplay:在配置变更回调中,销毁旧的VirtualDisplay,立即用新的屏幕参数创建新的VirtualDisplay。
- 优化过渡体验:可以用最后一帧捕获画面做临时填充,避免界面出现黑屏或闪烁。
举个简单的实现示例:
@Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); // 获取新的屏幕参数 DisplayMetrics metrics = getResources().getDisplayMetrics(); int newWidth = metrics.widthPixels; int newHeight = metrics.heightPixels; int newDensity = metrics.densityDpi; // 销毁旧的VirtualDisplay if (mVirtualDisplay != null) { mVirtualDisplay.release(); mVirtualDisplay = null; } // 确保MediaProjection和Surface仍可用,重建VirtualDisplay if (mMediaProjection != null && mSurfaceView.getHolder().getSurface().isValid()) { mVirtualDisplay = mMediaProjection.createVirtualDisplay( "ScreenCapture", newWidth, newHeight, newDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mSurfaceView.getHolder().getSurface(), null, null ); } }
核心需求的实现
你的核心目标是“让录屏仅在点击停止按钮时终止”,这个是完全可以实现的:只要你不主动调用mMediaProjection.stop(),MediaProjection实例就会保持有效,横竖屏时的VirtualDisplay重建只是替换了底层的显示镜像对象,录屏的数据流会持续从新的VirtualDisplay输出,整个录屏过程不会被中断。
简单来说,虽然VirtualDisplay会被销毁重建,但录屏的“会话”是持续的,用户完全感觉不到差异,最终只有你点击停止按钮时,才会真正终止录屏。
内容的提问来源于stack exchange,提问作者mmbrian
相关产品推荐
相关产品推荐

