PierfrancescoSoffritti / android-youtube-player

YouTube Player library for Android and Chromecast, stable and customizable.
https://pierfrancescosoffritti.github.io/android-youtube-player/
MIT License
3.41k stars 756 forks source link

Fatal Exception: android.net.ConnectivityManager$TooManyRequestsException #1024

Open rakeshrajput537 opened 1 year ago

rakeshrajput537 commented 1 year ago

Fatal Exception: android.net.ConnectivityManager$TooManyRequestsException: at android.net.ConnectivityManager.convertServiceException(ConnectivityManager.java:2887) at android.net.ConnectivityManager.sendRequestForNetwork(ConnectivityManager.java:3060) at android.net.ConnectivityManager.registerDefaultNetworkCallback(ConnectivityManager.java:3443) at android.net.ConnectivityManager.registerDefaultNetworkCallback(ConnectivityManager.java:3420) at com.pierfrancescosoffritti.androidyoutubeplayer.core.player.utils.NetworkObserver.doObserveNetwork(NetworkObserver.java:75) at com.pierfrancescosoffritti.androidyoutubeplayer.core.player.utils.NetworkObserver.observeNetwork(NetworkObserver.java:31) at com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.LegacyYouTubePlayerView.initialize(LegacyYouTubePlayerView.kt:102) at com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView.initialize(YouTubePlayerView.java:140)

PierfrancescoSoffritti commented 1 year ago

Hi, thanks. Maybe fixed by #996?

billdizl commented 1 year ago

Hi, thanks. Maybe fixed by #996?

not fix it

PierfrancescoSoffritti commented 1 year ago

What version of the library are you using?

billdizl commented 1 year ago

What version of the library are you using?

12.1.0

PierfrancescoSoffritti commented 1 year ago

Can you provide the stack trace and repro steps?

Repro steps should be either in the sample app or you can provide another project where it reproduces.

billdizl commented 1 year ago

您能提供堆栈跟踪和重现步骤吗?

重现步骤应该位于示例应用程序中,或者您可以提供重现它的另一个项目。

I cannot provide it because it comes from online and I did not find any error or crash during my own testing in the testing environment

Korrupshi commented 1 year ago

I had the same issue but solved it. For me, it was caused by my screen rendering every 100ms, due to accidently adding an update function in the onCurrentSecond (AbstractYouTubePlayerListener). This meant that the doObserveNetwork function in NetworkObserver.kt also calls connectivityManager.registerDefaultNetworkCallback(callback) every 100ms, which leads to the above crash.

So, once you fix whatever is causing your screen to render too often, the "Fatal Exception: android.net.ConnectivityManager$TooManyRequestsException:" won't be an issue.

However, before noticing that the frequent rendering was causing the issue, I solved it by creating an object for handling the connectivityManager callback registering. Before adding a new callback, the previous one was unregistered, which also prevents "TooManyRequestsException" error.

object ConnectionManager {
    private lateinit var connectivityManager: ConnectivityManager

    var networkCallback: ConnectivityManager.NetworkCallback? = null
        private set

    fun clearCallback() {
        networkCallback?.let { previousCallback ->
            try {
                connectivityManager.unregisterNetworkCallback(previousCallback)
            } catch (e: Exception) {
                Log.e(TAG, "updateCallback: ${e.message}")
            }
        }
    }

    @RequiresApi(Build.VERSION_CODES.N)
    fun updateCallback(newCallback: ConnectivityManager.NetworkCallback?) {
        clearCallback()
        newCallback?.let {
            connectivityManager.registerDefaultNetworkCallback(it)
        }
        networkCallback = newCallback
    }

    fun init(context: Context) {
        connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    }
}

The networkCallback related code in NetworkObserver.kt I replaced with the ConnectionManager to handle the callback registering and unregistering. For example:

  @RequiresApi(Build.VERSION_CODES.N)
  private fun doObserveNetwork(context: Context) {
    val callback = object : ConnectivityManager.NetworkCallback() {
      private val mainThreadHandler = Handler(Looper.getMainLooper())
      override fun onAvailable(network: Network) {
        // The callback is not on the main thread
        mainThreadHandler.post {
          listeners.forEach { it.onNetworkAvailable() }
        }
      }

      override fun onLost(network: Network) {
        // The callback is not on the main thread
        mainThreadHandler.post {
          listeners.forEach { it.onNetworkUnavailable() }
        }
      }
    }
//    networkCallback = callback
    ConnectionManager.updateCallback(callback)

//    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
//    connectivityManager.registerDefaultNetworkCallback(callback)
  }

I have no experience with ConnectivityManager in Android, so please let me know if using the above object ConnectionManager for handling callbacks is incorrect, or would lead to other issues.

bognargabor99 commented 11 months ago

HI, I had the same exception. In my case I had multiple YoutubePlayerViews in Jetpack Compose. After creating 3-4 YoutubePlayerViews programmatically (with AndroidView), my app crashed. What seems to have solved the issue is creating an xml file and inflating that, instead of calling the YouTubePlayerView constructor and setting "handleNetworkEvents" to false in an apply scope function, it did not matter because I was outside the constructor already and it already started observing the network connection.

Here is how I did it before:

AndroidView(
    factory = { context ->
        YouTubePlayerView(context = context).apply {
            this.enableAutomaticInitialization = false // Has no effect since it was true by default in the contructor
            initialize(object : AbstractYouTubePlayerListener() { ... })
        }
    }
)

So, I just created a layout file where I set both "handleNetworkEvents" and "enableAutomaticInitialization" to false and then I called initialize() manually. This way the properties were false in the constructor.

<com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:enableAutomaticInitialization="false"
    app:handleNetworkEvents="false"
    app:autoPlay="false" />

Then in Compose:

    AndroidView(
        factory = { context ->
            val inflatedView = LayoutInflater.from(context).inflate(R.layout.youtube_player_xml, null, false)
            val ytPlayer: YouTubePlayerView = inflatedView as YouTubePlayerView
            ytPlayer.initialize(/* TODO */)

And I stopped getting the exception since handleNetworkEvents was automatically false.

Hope this helps!