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
相关产品推荐
相关产品推荐

