Learn how to build a video streaming app for Fire TV using the react-native-video library. This step-by-step guide will take you through the basics of using react-native-video to boost your Fire TV app development, making sure your app stands out in the Amazon ecosystem
Fire OS is Amazon's customized Android-based operating system that powers Fire TV, bringing tons of streaming options to millions of users. With react-native-video, React Native developers can create rich, interactive video apps that fit perfectly into the Fire OS ecosystem. This guide will take you through the basics of using react-native-video to boost your Fire TV app development, making sure your app stands out in the Amazon ecosystem. If you run into any issues while working on your app, feel free to join our Discord for support.
Installation
npx react-native-tvos@latest init AppName
How it works on Apple TV?
After executing the command, we can see in our `package.json` file an additional script to run our app on the Apple TV simulator:
Before we run this script, we need to remember to download the simulator inside the Xcode app.
How it works on Fire TV?
If we want to run the app on a physical Fire TV Stick device, we should make the following steps:
Enable Developer Options on Fire TV Stick - On your Fire TV Stick, go to Settings > My Fire TV > About - Click several times on the button with your TV Stick device name. You should see a notification saying "You are now a developer!"
Enable ADB Debugging - Go to Settings > My Fire TV > Developer Options - Turn on ADB Debugging - If you see the option Apps from Unknown Sources, turn it on
Connect Fire TV Stick to Your Computer - Make sure your Fire TV Stick and your computer are connected to the same Wi-Fi network - Find the IP address of your Fire TV Stick. Go to Settings > My Fire TV > About > Network and note the IP address. - On your computer, open a terminal and run the following command to connect to your Fire TV Stick:
adb connect <your-fire-tv-ip-address>:5555
e.g.
adb connect 192.168.0.101:5555
A prompt may appear on your Fire TV Stick asking if you allow the connection. Confirm the prompt and run the command again.
To run your app on this device run the following:
adb -s <device name> reverse tcp:8081 tcp:8081
you can find device name with `adb devices` command
and later
yarn android
after running the command above, the app will run on the device
Ensuring Good Performance on Both Fire TV and Apple TV
When developing a TV app using React Native, it's important to ensure that the app works well on both Fire TV and Apple TV. While button focusing on Fire TV ans Android TV generally works well out of the box (though sometimes it requires minor adjustments with properties like `nextFocusUp`, `nextFocusRight`, etc.), it doesn't always work correctly on iOS. This can lead to a poor user experience on Apple TV. Fortunately, there are ways to address this issue and improve button focusing on Apple TV. According to the React Native documentation, `Touchable` components are auto-focused. And yes, that's true, but on Apple devices only when these elements are arranged next to each other along the x or y axis. For example, if we have a situation like this:
When button 1.3 is focused, after clicking the "down" button on the remote, the element will focus on 3.3, not 2.2. To fix this issue, we can use the `TVFocusGuideView` component, which provides support for Apple’s UIFocusGuide API.
When we wrap our boxes with the TVFocusGuideView component and set the autoFocus flag, everything looks great.
TVFocusGuideView acts as an extension of the view, allowing it to be aligned with other elements along an axis and to be focusable.
Next example is much more important, because when we see the situation like this, we won't be able to focus on the button 2.1 from the button 1.2 because the button 2.1 is not aligned with the button 1.2 or 3.1 along the x or y axis.
The best idea is to wrap all sections with the TVFocusGuideView component and set the autoFocus property. This way, we can navigate between all buttons seamlessly. TVFocusGuide also works on Android TV and Fire TV because it remembers the last selected item in a for example FlatList, and after navigating away and returning, this last selected item is focused. Look here.
Encountering issues while building Fire TV or Apple TV apps in React Native?
If you need assistance, let’s talk. As core contributors to React Native Video, we can provide you with a free ballpark quote for building your app.
Let's start coding
After creating the app, we should dive into how to build a streaming application on tvOS. We will use the `react-native-video` library, which enables us to create a seamless video playback. It provide playback control, support for various video formats or sources and much more! First, we will outline our app. We want to create a functional tool for browsing videos. We will separate the views into two screens, the first with a list of movies and the second with a preview of the selected one. To do this, we will use the `@react-navigation` library.
We will make our application play the video in a preview at the top of the screen when hovering over a thumbnail. There will also be a "play" button that will start the movie and, upon clicking, will take the user to a separate screen with that movie. However, let's start by adding a list of movies.
And let's add the "play" button. Remember how focusing works on Apple TV, we need to wrap the "play" button component and our list of movies with the TVFocusGuideView component. To avoid errors on Fire TV and AndroidTV we should also set nextFocusUp at FlatList to make sure, that "play" button is focused after click "up" on the remote.
// ...
const playButtonRef = useRef<View>(null);
const [playButtonNativeID, setPlayButtonNativeID] = useState<number | null>(
null,
);
useEffect(() => {
if (playButtonRef.current) {
// findNodeHandle imported from 'react native', it gives us a native id of this button
setPlayButtonNativeID(findNodeHandle(playButtonRef.current));
}
}, []);
// ...
const renderItem = ({item}) => (
<TouchableOpacity
nextFocusUp={playButtonNativeID ?? undefined}
>
{/*...*/}
</TouchableOpacity>
);
// ...
<View>
<Video
{/* ... */}
/>
<View>
{/* To make sure TVFocusGuideView works correctly, we can add a width property at styles */}
<TVFocusGuideView autoFocus style={{width: DEVICE_WIDTH}}>
<Pressable
ref={playButtonRef}
// Add the hasTVPreferredFocus property to ensure this element is focused by default. Remember to use this only once per screen
hasTVPreferredFocus={true}
>
<Text>Play</Text>
</Pressable>
</TVFocusGuideView>
</View>
</View>
<Text>Last Added</Text>
<TVFocusGuideView autoFocus>
<FlatList
{/* ... */}
/>
</TVFocusGuideView>
// ...
Let's now add the ability to navigate between screens.
Now we have saved in the state whether the controls should be visible, so we can easily add 'play/pause', 'go back', 'progress bar' and 'movie time' controls
To complete the implementation, we should also add event listeners for remote control buttons to show and hide the controls and automatically detect right/left button presses to seek the video.
const handleLongPress = (direction: 'left' | 'right') => {
const seekAmount = direction === 'left' ? -longSeekTime : longSeekTime;
if (Platform.OS === 'ios') {
// IOS: long press is triggered on start and finish pressing
if (!keyPressed) {
setKeyPressed(true);
// Need to remember to pause the video because then we update preview time there and on video progress
setPaused(true);
longPressTimeoutRef.current = setInterval(() => {
setPreviewTime(prevPreviewTime => prevPreviewTime + seekAmount);
controlsOpenTimer();
}, 200);
} else {
setKeyPressed(false);
setPaused(false);
clearInterval(longPressTimeoutRef.current || undefined);
seek(previewTime);
}
} else {
// ANDROID: long press is triggered from time to time while pressing
const newPreviewTime = previewTime + seekAmount;
setKeyPressed(true);
setPaused(true);
setPreviewTime(newPreviewTime);
clearInterval(longPressTimeoutRef.current ?? undefined);
longPressTimeoutRef.current = setTimeout(() => {
setKeyPressed(false);
setPaused(false);
seek(newPreviewTime);
}, 600);
}
};
const myTVEventHandler = (evt: HWEvent) => {
const {eventType} = evt;
if (eventType === 'playPause') {
setPaused(prev => !prev);
}
if (
[
'playPause',
'select',
'up',
'down',
'left',
'right',
'longLeft',
'longRight',
].includes(eventType)
) {
controlsOpenTimer();
}
switch (eventType) {
case 'select':
togglePausePlay();
break;
case 'left':
seekBackward();
break;
case 'right':
seekForward();
break;
case 'longLeft':
handleLongPress('left');
break;
case 'longRight':
handleLongPress('right');
break;
default:
break;
}
};
useTVEventHandler(myTVEventHandler);
Final player should look like this
Summary
In this article, we showed how to create a streaming app for TV using react-native-tvos and react-native-video. We configured the environment for Fire TV, Android TV, and Apple TV. You can find the full code on GitHub. If you have any questions, feel free to join our Discord!
Share our work
React Native
React Native Video
tvOS
Fire TV
Written By
Kamil Moskała
See related posts
No items found.
Do you need help with developing react solutions?
Leave your contact info and we’ll be in touch with you shortly
By clicking “Accept all”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.