You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 15:28:13