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

Android中MediaRouterDialog无法显示可用投屏设备问题求助

问题

使用MediaRouter API实现本地视频投屏到Android TV/智能电视,但MediaRouteChooserDialog无法发现投屏路由,同一局域网下YouTube等应用能正常识别设备。已配置官方文档要求的权限并确保在同一网络,推测是代码实现问题。

清单文件权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

Activity代码:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMain2Binding.inflate(layoutInflater)
    setContentView(binding.root)
    mediaRouter = MediaRouter.getInstance(applicationContext)

    mSelector = MediaRouteSelector.Builder()
        .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
        .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
        .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
        .build()
    mediaRouter?.addCallback(
        mSelector!!, mediaRouterCallback,
        MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN
    )
    binding.castButton.setOnClickListener {
        dialog = MediaRouteChooserDialog(this)
        dialog!!.routeSelector = mSelector as MediaRouteSelector
        dialog!!.show()
    }
}

回调逻辑:

private val mediaRouterCallback = object : MediaRouter.Callback() {

    override fun onRouteSelected(
        router: MediaRouter,
        route: MediaRouter.RouteInfo,
        reason: Int
    ) {
        super.onRouteSelected(router, route, reason)
        Log.d(TAG, "onRouteSelected: route=$route")
        val name = route.name
        Toast.makeText(this@MainActivity2, name, Toast.LENGTH_SHORT).show()
    }

    override fun onRouteRemoved(router: MediaRouter, route: MediaRouter.RouteInfo) {
        super.onRouteRemoved(router, route)
        Log.d(TAG, "onRouteRemoved: route=$route")
        val name = route.name
        Toast.makeText(this@MainActivity2, "$name\nRoute Removed", Toast.LENGTH_SHORT).show()

    }
    override fun onRouteUnselected(
        router: MediaRouter,
        route: MediaRouter.RouteInfo,
        reason: Int
    ) {
        Log.d(TAG, "onRouteUnselected: route=$route")
        if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {

        }
    }
}

解决方案

1. 补充必要权限

Android 10+及以上版本,局域网设备发现依赖位置权限,需添加并动态申请:

<!-- 清单文件新增 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Android 12+ 部分设备需要蓝牙扫描权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />

在Activity中动态申请权限:

private val REQUEST_PERM_CODE = 1001

private fun checkAndRequestPermissions() {
    val neededPermissions = arrayOf(
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.BLUETOOTH_SCAN
    )
    val ungranted = neededPermissions.filter {
        ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
    }
    if (ungranted.isNotEmpty()) {
        ActivityCompat.requestPermissions(this, ungranted.toTypedArray(), REQUEST_PERM_CODE)
    }
}

// 在onCreate中调用
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...其他初始化代码
    checkAndRequestPermissions()
}

2. 调整路由选择器配置

当前选择器的Category组合可能未覆盖设备支持的类型,针对Google Cast类设备补充专属Category:

import com.google.android.gms.cast.CastMediaControlIntent

// 重构选择器构建逻辑
mSelector = MediaRouteSelector.Builder()
    .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
    // 添加Google Cast设备支持的默认接收器Category
    .addControlCategory(CastMediaControlIntent.categoryForCast(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID))
    .build()

注意:使用Google Cast相关API需在build.gradle添加依赖:

implementation 'com.google.android.gms:play-services-cast:21.3.0'

3. 优化回调扫描Flag

调整扫描Flag组合,增强设备发现能力:

mediaRouter?.addCallback(
    mSelector!!, mediaRouterCallback,
    MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN or MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY
)

4. 替换手动Dialog为系统MediaRouteButton

系统自带的MediaRouteButton内置完整的路由发现逻辑,避免手动创建Dialog的配置遗漏:

<!-- 布局文件中替换自定义按钮 -->
<androidx.mediarouter.app.MediaRouteButton
    android:id="@+id/media_route_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
// Activity中绑定选择器
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMain2Binding.inflate(layoutInflater)
    setContentView(binding.root)
    // ...其他初始化代码
    binding.mediaRouteBtn.routeSelector = mSelector
}

5. 新增路由发现日志排查

在回调中添加onRouteAdded方法,确认设备是否被发现但未在Dialog中显示:

override fun onRouteAdded(router: MediaRouter, route: MediaRouter.RouteInfo) {
    super.onRouteAdded(router, route)
    Log.d(TAG, "发现路由: ${route.name},支持的Category: ${route.controlCategories}")
}

如果日志能输出设备信息但Dialog未显示,说明选择器Category与设备支持类型不匹配,需进一步调整Category配置。

内容的提问来源于stack exchange,提问作者Afnan Akber

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 14:17:44