Today as some of you could have expected after our short movie with “Hello world” written in React Native running on Amazon Fire TV Stick (referred to AF later), Jakub Stasiak and I are going to describe our journey with an AF.

Our adventure with an AF has started from a request from a one of our client to build an app which would be responsible for displaying important information on TV displays in shops. Fire TV Stick is a small device (in the size of a bigger memory stick) which is probably the cheapest option to make non-smart TVs “smarter”. The most important thing for us is that it’s powered by Android.

When our AF arrived, we had to decide which technology stack we would like to choose. A final app would consist of 3–4 screens with input areas, list and details view.

How can we write an app for AF?

After some research we came up with the following options:

  • HTML5 app
  • native Android app
  • React Native app

The order of the list above is not a coincidence, the first option is probably the easiest and you can find relatively many docs about that solution. RN app is on the last position because we haven’t found anyone who had done this before. As it’s not too hard to spot the answer we wanted to try with RN on AF.

For the purpose of this article, we want to go through a process of creating an RSS reader in RN for AF.

How to enable adb?

The first step to become a React Native developer for Amazon Fire TV Stick is to enable adb on a device. On a Fire Stick, it’s even easier than on an Android phone. We just have to go to the device settings and find the adb switch. Next, we can verify whether the adb was enabled or not, we can do that from CLI (if our AF is connected to our computer) using command adb devices.

Will empty app work?

Now we can generate and start an empty RN app, we have to run the following two commands:

  • react-native init FirestickDemo && cd FirestickDemo
  • react-native run-android

As a result, we should see a standard RN app, be able to show developers the menu and navigate through options. 🎉

Can we navigate through buttons?

At this point, it seems like we can start developing what we planned. Let’s add some buttons to test if it works.

White rectangle should change background color.

What?! Why can’t we click on anything? 😦

We are clicking center button on remote control but nothing happens. It’s possible to navigate between touchable components and buttons but there is no possibility to call onPress method. We tried few different approaches. We even wrote native apps in Java and Native Script with few buttons (those apps works great). Turned out that Buttoncomponent doesn’t use native button underneath. That’s an unfortunate.

How AF’s remote works?

While writing our first app for AF we realized that remote control sends classic keyboard events. React Native doesn’t support those events by default but we found a library for that. Great, so there is still hope. It looks like we have everything we need — possibility to navigate between every touchable and possibility to listen to keyboard events. We could manually call onPress after user press center button on a remote control.

Yes, we could… but we can’t.

Another problem — there is no possibility to find out which touchable is focused. Ah, React Native, dear friend why you have to make everything harder. Now we must write something big and ugly that will become better touchable and keep in our state information about currently focused component.

How to live with that?

Our idea was to create two things:

  • SelectableContainer– a component which will store all information about selectable components in current view and react to keyboard events.
  • selectable– a Higher Order Component , something that can transform classic TouchableOpacityButtonView, etc. into a component that can be focused and selected using a keyboard or a remote control.

SelectableContainer should be a stateful component with a state in that shape:

So we can properly react on every up/down button click and change activeSelectable to one above/below. There is a list of coordinates in a component state so we can easily find out which selectable should we select. On every change of activeSelectable we will call onFocusonBluror onPress method. The code which is responsible for all of that:

How SelectableContainer has access to buttons inside?

The answer could frighten you — through context. Yes, we know… it’s an experimental API which will probably change but still, it’s the best solution for us. Of course, we don’t want to write context “magic“ every time we want to add simple button. It will be ugly and hard to maintain.

That’s why we created selectable HOC. It will register our component in SelectableContainer and make sure that we can use onPress prop on every component wrapped by it. It will also read position of our component so SelectableContainer will know the proper visual order of selectable components.

Okay, we can now easily create selectable Button or View. Let’s do that by modifying our first attempt to AF buttons:

Now we can select buttons!

Will inputs work?

The first part of our work is done! We are ready to create a list of RSS feeds with buttons. Now we only have to add some possibility to create custom RSS feed. And there is no surprise, classic TextInput doesn’t work well on AF. It’s impossible to navigate from another component to it. Fortunately, we created selectable before so we can us it here. Just simply wrap TextInput into selectable and call textInput.focus() inside onPress function prop. Just like this:

Now we truly have all pieces we need to build AF app!

RSS feed app

As you can see our app consists of 2 screens, for navigation we use exponent/ex-navigation which handle back button for us. The most interesting part of an app (of course besides problems described above) was fetching RSS news in an easy to read from javascript form. Not that long time ago we would use Google Feed API to translate xmlish RSSes to jsons, but sadly Google decided to shut down this service and we had to find an alternative solution. Finally, we came across YQL (Yahoo query language) which works exactly as we expected. For displaying RSS content which sometimes is HTML we use WebView component from RN.

Link to source code: https://github.com/souhe/react-native-firestick

Conclusion

Should you use React Native as a technology to build AF app?
If you are familiar with React Native definitely yes, it was a great adventure for us and we learned a lot of things. If not maybe stay with native stuff or write an app in HTML5 which is kind of a recommended solution for Fire TV Stick.