Custom Receiver Application Id does not work in React Native

Description

In our custom React Native app, we noticed that our app is not able to connect to our Custom Receiver. Our implementation on our dev website with Bitmovin works well with the custom receiver so the receiver itself appears to be fully functional.

To test this further I downloaded and bundled the example app, firstly with no changes. I was able to cast to my Chromecast with no issues - and the description “CAF Receiver v3 - Stable” appears.

After modifying the code, rebundling and deploying the app, and doing a reset of the Chromecast for good measure, the casted video still only can access the default Bitmovin receiver.

** Reproduction Steps **

  • Create a clean build of the example app (tested hash is 55c2f5bd0488843aee587c4ca89f25cd57e8eff5)

  • Update code at ./example/src/screens/Casting.tsx

** Change BitmovinCastManager.initialize(); toBitmovinCastManager.initialize({ applicationId: '910D2539' });

** Change title: 'Art of Motion', to title: 'Art of Motion - Custom Receiver 910D2539',

  • Run and deploy the app. Expected behavior is that the custom receiver plays the video, but the default Bitmovin receiver is instead shown.

** Repository Fork with changes **

https://github.com/vandevusse/bitmovin-player-react-native

Test Notes

Tested on Android 14 using the example app at bitmovin-player-react-native/example at development · bitmovin/bitmovin-player-react-native · GitHub

Hi @ben1,
looking into the lifecycle of the react native wrapper it appears to have an issue around the cast manager initialization timing - it might be too late to call it where it is currently being called.

Can your briefly try to call

BitmovinCastManager.initialize(/* applicationId = */ "910D2539",/* messageNamespace = */ "any")

in the MainApplication.kt native code and see if that works around the issue? Your may have to change the gradle dependency of the com.bitmovin.player:player to api in the bitmovin-player-react-native/android/build.gradle

Best,
Lukas

Hi Lukas,

Thanks for the quick reply. This is a bit beyond my current capabilities. I can’t resolve BitmovinCastManager in the kotlin code - it appears to be in the com.bitmovin.player.casting package but I can’t find any references to that, is there a particular import that I’m not seeing?

Given your feedback, it sounds like the initalize() method is timed poorly in the Casting.tsx sample file. I can see how if that method does not complete, the custom receiver cannot be used.

Theoretically, can’t this be solved by adding an await to the initialize() call? Sure, it will affect performance a little bit, but if it is needed for a custom receiver, I’m ok with that.

However, doing this as a test (and not changing anything else, the application crashes with the following error:

 ERROR  Error: Objects are not valid as a React child (found: object with keys {_h, _i, _j, _k}). If you meant to render a collection of children, use an array instead.

This error is located at:
    in Casting (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RCTView (created by View)
    in View (created by SceneView)
    in RNSScreen
    in Unknown (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)
    in RNSScreenStack (created by ScreenStack)
    in ScreenStack (created by NativeStackViewInner)
    in NativeStackViewInner (created by NativeStackView)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by SafeAreaInsetsContext)
    in SafeAreaProviderCompat (created by NativeStackView)
    in NativeStackView (created by NativeStackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator (created by App)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by App)
    in App
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in BitmovinPlayerReactNativeExample(RootComponent), js engine: hermes

What are your thoughts? Could this error potentially also be the reason why the async call isn’t working?

This seems like a relatively serious issue for anyone hoping to use a custom receiver from the React Native app.

Found a way to get around the issue above and test it out properly with awaits, feel free to check the commit out here Attempting awaits on casting · vandevusse/bitmovin-player-react-native@882d6ff · GitHub (all in React)

This, however, does not fix the issue. I still see the custom receiver being specified by the applicationId being ignored.

Hi @Lukas, any updates on this issue on your end? Are you able to reproduce?

Cheers,
Ben

Hi @ben1, sorry for the delayed response. I am able to reproduce the issue and we are tracking this as a bug internally.

In the mean time, please try the following patch as a workaround:

index 26a1cc6..9ac607f 100644
--- a/example/android/app/build.gradle
+++ b/example/android/app/build.gradle
@@ -122,6 +122,7 @@ dependencies {
     implementation "androidx.localbroadcastmanager:localbroadcastmanager:1.1.0"
 
     // only needed if the casting feature is used
+    implementation 'com.bitmovin.player:player:3.64.0+jason'
     implementation("com.google.android.gms:play-services-cast-framework:21.3.0")
     implementation("androidx.mediarouter:mediarouter:1.3.1")
 }
diff --git a/example/android/app/src/main/java/com/bitmovin/player/reactnative/example/MainApplication.kt b/example/android/app/src/main/java/com/bitmovin/player/reactnative/example/MainApplication.kt
index c29471c..8a6a7a5 100644
--- a/example/android/app/src/main/java/com/bitmovin/player/reactnative/example/MainApplication.kt
+++ b/example/android/app/src/main/java/com/bitmovin/player/reactnative/example/MainApplication.kt
@@ -1,6 +1,7 @@
 package com.bitmovin.player.reactnative.example
 
 import android.app.Application
+import com.bitmovin.player.casting.BitmovinCastManager
 import com.facebook.react.PackageList
 import com.facebook.react.ReactApplication
 import com.facebook.react.ReactHost
@@ -34,6 +35,7 @@ class MainApplication : Application(), ReactApplication {
 
   override fun onCreate() {
     super.onCreate()
+    BitmovinCastManager.initialize(/* applicationId = */ "910D2539",/* messageNamespace = */ "any")
     SoLoader.init(this, false)
     if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
       // If you opted-in for the New Architecture, we load the native entry point for this app.

Hi Lukas,

That’s great news, thank you for the update. I tested your workaround on the example app and it worked, which is great. I suspect you are already on top of the issue, but if it’s helpful I also conducted my own investigation looking at the debug logs and it appears that the Chromecast code already starts looking for the receiver with the default ID before reaching the React code which defines the initialization step with the custom receiver id.

I’ll go ahead and push this workaround into my real application and give it a shot. Please do feel free to reach out when the library has the bug fix applied.

Cheers,
Ben

1 Like