关于使用MediaRouter检测投屏(镜像)功能的有效性确认及优化建议
使用MediaRouter检测投屏(镜像)功能的有效性确认及优化建议
你的这段代码在大多数日常场景下是完全可靠的,思路方向也非常正确——通过筛选非默认路由且播放类型为远程的路由,确实能覆盖绝大多数投屏/屏幕镜像的连接情况,两台测试设备的验证结果也能说明这一点。
为什么你的代码能工作?
PLAYBACK_TYPE_REMOTE这个标记本身就是用来标识内容输出到本地设备以外的远程终端(比如电视、投影仪、无线投屏接收器)的路由类型,排除默认路由(也就是设备自身的屏幕输出)的逻辑,刚好命中了投屏镜像的核心特征,所以常规情况下不会出错。
可能存在的误判场景
不过有几个边界情况需要留意,可能会导致你的函数误判为“已投屏”:
- 单独投放音频的场景:比如把手机音频投到蓝牙音箱,此时对应的路由也会被标记为
PLAYBACK_TYPE_REMOTE,但这并不是屏幕镜像。如果你的需求是仅检测屏幕镜像,那这个判断就不够精准了。 - 部分厂商定制系统的特殊路由:少数品牌的定制ROM可能对MediaRouter的路由信息有自定义处理,比如某些私有投屏协议的路由标记可能和标准有差异,但这种情况非常少见。
优化建议
如果想要更精准地识别屏幕镜像,或者实现更实时的状态检测,可以参考下面的优化方案:
1. 补充屏幕镜像专属的判断条件
在原有逻辑基础上,增加对设备显示类型的筛选,同时可以通过路由名称过滤掉音频类设备:
fun Activity.isScreenMirroringActive(): Boolean { val mediaRouter = MediaRouter.getInstance(this) return mediaRouter.routes.any { route -> !route.isDefault && route.playbackType == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE && // 筛选常见的屏幕镜像设备类型 (route.displayType == MediaRouter.RouteInfo.DISPLAY_TYPE_HDMI || route.displayType == MediaRouter.RouteInfo.DISPLAY_TYPE_WIRELESS) && // 可选:过滤掉蓝牙音频设备这类非镜像路由 !route.name.toString().contains("蓝牙", ignoreCase = true) } }
2. 采用实时监听替代单次检测
单次调用函数的方式只能获取当前瞬间的状态,不如监听路由变化回调更实时。可以注册MediaRouter的回调来动态捕捉投屏状态的变化:
fun setupMirroringStateListener(activity: Activity, onStateChanged: (Boolean) -> Unit) { val mediaRouter = MediaRouter.getInstance(activity) val callback = object : MediaRouter.Callback() { override fun onRouteAdded(router: MediaRouter, route: MediaRouter.RouteInfo) { updateMirroringState(activity, onStateChanged) } override fun onRouteRemoved(router: MediaRouter, route: MediaRouter.RouteInfo) { updateMirroringState(activity, onStateChanged) } override fun onRouteChanged(router: MediaRouter, route: MediaRouter.RouteInfo) { updateMirroringState(activity, onStateChanged) } } // 注册回调,监听音视频类型的路由变化 mediaRouter.addCallback( MediaRouter.ROUTE_TYPE_LIVE_AUDIO or MediaRouter.ROUTE_TYPE_LIVE_VIDEO, callback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN ) // 绑定生命周期,避免内存泄漏 activity.lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { mediaRouter.removeCallback(callback) } }) // 初始化状态 updateMirroringState(activity, onStateChanged) } private fun updateMirroringState(activity: Activity, callback: (Boolean) -> Unit) { callback.invoke(activity.isScreenMirroringActive()) }
总结
你最初的代码在基础投屏检测场景下是完全可用的,如果只是简单判断“是否有外部显示设备连接”,不需要做额外修改;但如果需要精准区分屏幕镜像和其他远程媒体播放,或者需要实时更新状态,上面的优化方案会更合适。
备注:内容来源于stack exchange,提问作者iknow
相关产品推荐
相关产品推荐

