Continuity
React Native Fire TV & Android TV
Integration Guide
Setup

Setup

Build Setup

Add dependencies

Add Vizbee React Native Module Dependency

yarn add react-native-vizbee-receiver-sdk

Add Vizbee Native SDK dependency based on the required platforms.

Add the Vizbee repository to your Android TV / Fire TV receiver app’s root build.gradle.

allprojects {
  repositories {
     ...
 
     // Vizbee Code
     maven { url 'https://repo.claspws.tv/artifactory/libs'}
  }
}

2(a): Add Dependency in build.gradle (Fire TV Only).

dependencies {
 
   // Vizbee Fire TV SDK
   implementation 'tv.vizbee:firetv-receiver-sdk:4.3.1'
}
Step 2(b): Add Dependency in build.gradle (Android TV Only).
dependencies {
   // Vizbee Android TV SDK
   implementation 'tv.vizbee:androidtv-receiver-sdk:4.2.7'
}
 
Step 2(c): Add Dependencies in build.gradle (Fire TV and Android TV).
android {
  flavorDimensions "default"
  productFlavors {
    androidTV {
      dimension "default"
    }
    fireTV {
      dimension "default"
    }
  }
}
 
dependencies {
 
   ...
 
   // Vizbee - Android TV
   androidTVImplementation "tv.vizbee:androidtv-receiver-sdk:4.2.7"
 
   // Vizbee - Fire TV
   fireTVImplementation "tv.vizbee:firetv-receiver-sdk:4.3.1"
}

Install Dependencies

Install Vizbee React Native and Native dependencies

yarn install

Run

Run the project on Fire TV or Android TV

yarn android

Manifest Setup

ℹ️ Updates have to be made to the Fire TV and Android TV app’s respective manifest files to enable the TV apps to be launched from the mobile app.

Fire TV Manifest Setup

Step 1: Ensure that the primary/main activity has the DEFAULT category in the intent filter.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.myapp">
 
   <application
      android:name="com.myapp">
 
      // Vizbee: FireTV setup
      <meta-data android:name="whisperplay" android:resource="@xml/whisperplay"/>
 
      <activity
         <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
 
               // Vizbee: Needed
               <category android:name="android.intent.category.DEFAULT" />
         </intent-filter>
      </activity>
 
      ...
 
   </application>
</manifest>

Step 2: Set DIAL ID in res/xml/whisperplay.xml

Mobile app communicates with the FireTV using two mobile-to-TV protocols: DIAL and WHISPERPLAY. To enable these protocols, a dialid parameter needs to be set for the FireTV app. The dialid typically is selected by the app owner and is a reverse DNS name of the app. For example, com.google.youtube or com.netflix.

Step 2.1: Create whisperplay.xml with dialid.

Create a resource file called whisperplay.xml with the following content in your Fire TV app’s res/xml folder.

<whisperplay>
   <dial>
      <application>
         <!-- edit and replace com.myapp with a reverse dns name of your app -->
         <dialid>com.myapp</dialid>
         <startAction>android.intent.action.MAIN</startAction>
      </application>
   </dial>
</whisperplay>

NOTE: Please select a dialid for your app and edit the above file. Also, the exact same dialid needs to be configured in both your app and also in the Vizbee cloud configuration.

Step 2.2: Add a metadata item to your manifest file to link to whisperplay.xml file.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.myapp"
   android:installLocation="preferExternal">
 
   <application
      android:name="com.myapp">
 
      <meta-data android:name="whisperplay" android:resource="@xml/whisperplay"/>
 
      <activity
         <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
               <category android:name="android.intent.category.DEFAULT" />
         </intent-filter>
      </activity>
 
      ...
 
   </application>
</manifest>

Android TV Manifest Setup

Step 1: Ensure that the primary/main activity has the android:name="com.google.android.gms.cast.tv.action.LAUNCH with DEFAULT category in the intent filter.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.myapp"
   android:installLocation="preferExternal">
 
   <application
      android:name="com.myapp">
 
      <meta-data
         android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
         android:value="com.example.mysimpleatvapplication.MyAppReceiverOptionsProvider" />
 
      <activity android:name="com.myapp.MainActivity">
 
         <!-- To launch the app -->
         <intent-filter>
               <action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
               <category android:name="android.intent.category.DEFAULT" />
         </intent-filter>
 
         <!-- To start the video -->
         <intent-filter>
               <action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
               <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
 
      </activity>
 
      ...
 
   </application>
</manifest>

Step 2: Create and implement the ReceiverOptionsProvider to provide CastReceiverOptions. The ReceiverOptionsProvider is used to provide the CastReceiverOptions when CastReceiverContext is initialized.

 
import android.content.Context
import com.google.android.gms.cast.tv.CastReceiverOptions
import com.google.android.gms.cast.tv.ReceiverOptionsProvider
import java.util.*
 
class MyAppReceiverOptionsProvider : ReceiverOptionsProvider {
 
    override fun getOptions(context: Context): CastReceiverOptions {
        return CastReceiverOptions.Builder(context)
            .setCustomNamespaces(
                Arrays.asList("urn:x-cast:tv.vizbee.sync")
            )
            .build()
    }
 
}
 

Step 3: Specify the options provider in your Manifest file.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.myapp"
   android:installLocation="preferExternal">
 
   <application
      android:name="com.myapp">
 
      <meta-data
         android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
         android:value="com.example.mysimpleatvapplication.MyAppReceiverOptionsProvider" />
 
      <activity android:name="com.myapp.MainActivity">
 
         <!-- To launch the app -->
         <intent-filter>
               <action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
               <category android:name="android.intent.category.DEFAULT" />
         </intent-filter>
 
         <!-- To start the video -->
         <intent-filter>
               <action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
               <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
 
      </activity>
 
      ...
 
   </application>
</manifest>

Step 4: Handling the LOAD intent filter in your MainActivity

// In your activity, to handle these load requests, you need to handle the intents in your activity lifecycle callbacks:
 
class MyActivity : Activity() {
 
  override fun onStart() {
      super.onStart()
 
      val mediaManager = CastReceiverContext.getInstance().getMediaManager()
      // Pass the intent to the SDK. You can also do this in onCreate().
      if (mediaManager.onNewIntent(intent)) {
 
         // If the SDK recognizes the intent, you should early return.
         return
      }
 
      // If the SDK doesn't recognize the intent, you can handle the intent with
      // your own logic.
      ...
   }
 
   // For some cases, a new load intent triggers onNewIntent() instead of
   // onStart().
   override fun onNewIntent(intent: Intent) {
 
      val mediaManager = CastReceiverContext.getInstance().getMediaManager()
      // Pass the intent to the SDK. You can also do this in onCreate().
      if (mediaManager.onNewIntent(intent)) {
 
         // If the SDK recognizes the intent, you should early return.
         return
      }
 
      // If the SDK doesn't recognize the intent, you can handle the intent with
      // your own logic.
      ...
  }
}

Code Setup

Add Template Files

Integrating the Vizbee Fire TV & Android TV Continuity SDK is straightforward. We provide ready-to-use template files that you can easily copy into your project. These templates handle app lifecycle, deep linking, and video playback, giving you a solid foundation. We'll guide you through the process, clearly indicating which parts of the code you'll need to modify. You'll be able to customize these templates to fit your app's specific needs, ensuring a seamless integration with your existing codebase. Let's start by looking at the file structure and key components:

Copy the following template files provided by Vizbee into a vizbee folder in your react native code repo:

MyAppVizbeeAppDelegate.ts (opens in a new tab)

MyAppVizbeePlayerDelegate.ts (opens in a new tab)

Note: Rename the file names that start with MyApp with your app name. For example, if your app is named "Netflix", rename MyAppVizbeeAppDelegate.ts to NetflixVizbeeAppDelegate.ts.

Key Components
MyAppVizbeeAppDelegate

The MyAppVizbeeAppDelegate class inherits from the VizbeeAppDelegate provided by the react-native-vizbee-receiver-sdk. Upon receiving a StartVideo event from a mobile app, the Vizbee Receiver SDK within the TV app triggers the onStartVideo() method of the MyAppVizbeeAppDelegate, passing along the video metadata and streaming information received from the mobile device.

MyAppVizbeePlayerDelegate

The MyAppVizbeePlayerDelegate class inherits from the VizbeePlayerDelegate provided by the react-native-vizbee-receiver-sdk. It acts as a liaison between your app's player and the Vizbee SDK, facilitating the exchange of player commands and status updates.

ProGuard Rules

ProGuard Rules for Vizbee Integration in Release Builds

When building your app for release with R8 (Android's code shrinking and obfuscation tool) enabled, it's crucial to set up the correct ProGuard rules for Vizbee integration. This ensures that necessary classes and methods are preserved during the release build process.

Add the following rules to your proguard-rules.pro file for successful release builds:

-dontwarn tv.vizbee.config.api.ui.cards.DeviceStatusCardConfig
-dontwarn tv.vizbee.environment.Environment
-dontwarn tv.vizbee.environment.net.handler.factory.NetworkHandlerFactory
-dontwarn tv.vizbee.environment.net.handler.implementations.reachability.LocalReachabilityIpProvider
-dontwarn tv.vizbee.environment.net.info.NetworkInfo
-dontwarn tv.vizbee.environment.net.manager.INetworkManager$NetworkChangeCallback
-dontwarn tv.vizbee.environment.net.manager.INetworkManager

Handling Additional Vizbee Classes in Release Builds

If you encounter release build errors related to R8 and Vizbee, you may need to add more Vizbee classes to the ProGuard rules. Follow these steps:

  1. Identify the missing Vizbee classes from the release build error messages.
  2. Add -dontwarn rules for these classes to your proguard-rules.pro file.
  3. Rebuild your project in release mode to ensure the errors are resolved.

Note: These ProGuard rules are specifically for release builds. Debug builds typically don't require these rules.