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

Android TV端YoutubePlayer onError方法未触发问题求助

Android TV YoutubePlayer 网络错误监听失效的解决办法

YoutubePlayer自带的onError回调并不是万能的,尤其是在Android TV场景下,很多网络断开的情况不会触发这个回调——比如视频加载前就断网、播放中网络波动但播放器内部没抛出错误。下面给你几个实用的解决思路:

1. 主动监听系统网络状态变化

播放器自身的错误回调有局限性,必须主动监听系统网络状态才能覆盖所有断网场景:

  • 先在Manifest中添加权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
  • 使用ConnectivityManager.NetworkCallback实时监听网络连接,断网时直接触发弹窗:
private lateinit var networkCallback: ConnectivityManager.NetworkCallback

private fun registerNetworkListener() {
    val connectivityManager = requireContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onLost(network: Network) {
            super.onLost(network)
            requireActivity().runOnUiThread {
                showNetworkErrorDialog()
            }
        }

        override fun onAvailable(network: Network) {
            super.onAvailable(network)
            initializedYouTubePlayer?.let { player ->
                if (isEulaAccepted) {
                    player.loadVideo(
                        glance.peek.videoPeek.video.youtubeVideo.videoId,
                        videoStartTime.toFloat()
                    )
                }
            }
        }
    }

    val networkRequest = NetworkRequest.Builder()
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .build()

    connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
}

// 在Fragment销毁时注销监听,避免内存泄漏
override fun onDestroyView() {
    super.onDestroyView()
    val connectivityManager = requireContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    connectivityManager.unregisterNetworkCallback(networkCallback)
}

private fun showNetworkErrorDialog() {
    AlertDialog.Builder(requireContext())
        .setTitle("网络错误")
        .setMessage("当前网络不可用,请检查网络连接")
        .setPositiveButton("确定") { dialog, _ -> dialog.dismiss() }
        .show()
}

2. 结合播放器缓冲状态判断网络异常

播放中突然断网可能只会触发BUFFERING状态而不会抛出错误,这时候可以通过缓冲时长结合网络状态判断:

private var bufferingStartTime: Long = 0
private val bufferingHandler = Handler(Looper.getMainLooper())

override fun onStateChange(youTubePlayer: YouTubePlayer, state: PlayerConstants.PlayerState) {
    handleVideoStateChange(state)
    when (state) {
        PlayerConstants.PlayerState.BUFFERING -> {
            bufferingStartTime = System.currentTimeMillis()
            bufferingHandler.postDelayed({
                val isBufferingTimeout = System.currentTimeMillis() - bufferingStartTime > 5000
                if (isBufferingTimeout && !isNetworkAvailable(requireContext())) {
                    showNetworkErrorDialog()
                }
            }, 5000)
        }
        else -> {
            bufferingHandler.removeCallbacksAndMessages(null)
        }
    }
}

// 辅助方法:检查当前网络是否可用
private fun isNetworkAvailable(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val network = connectivityManager.activeNetwork ?: return false
    val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
    return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
            capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}

3. 完善播放器错误回调的处理

确认播放器版本是否支持全量错误回调,同时细化onError的分支处理:

override fun onError(youTubePlayer: YouTubePlayer, error: PlayerConstants.PlayerError) {
    super.onError(youTubePlayer, error)
    Timber.i("Youtube错误类型: ${error.name}")
    when(error) {
        PlayerConstants.PlayerError.NETWORK_ERROR,
        PlayerConstants.PlayerError.NO_CONNECTION -> {
            showNetworkErrorDialog()
        }
        else -> {
            setErrorCodes("Youtube error:${error.name}")
        }
    }
}

把以上三种方式结合使用,就能覆盖绝大多数网络异常场景了。

内容的提问来源于stack exchange,提问作者Parag Rane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:15:42