DEV Community

loading...
Progress

Building an Android TV App with NativeScript

rdlauer profile image Rob Lauer Originally published at nativescript.org ・4 min read

If you're here, I'm guessing NativeScript is your first choice (or will be soon!) when it comes to developing native cross-platform apps from one codebase, for both iOS and Android. I suppose the title gives it away, but did you know you can also build NativeScript apps for Android TV?

nativescript and android tv

While Android TV isn't taking the world by storm (yet) and we're not officially supporting this integration (yet), it's still an interesting exercise to consider as another channel for your killer app dev skills.

So what is Android TV? An Android TV is a set-top box (powered by Android) that lets you stream content to your TV 📺. In many ways, you can compare it to Apple TV, without the hardware restrictions inherent to Apple's ecosystem. The most common apps on Android TV focus on media consumption and gaming, but this platform is just waiting for its next killer app.

Maybe the time is ripe for another run at WebTV!? 😉

webtv

A Little History

One day we received a message from a NativeScript Sidekick user who wanted to leverage his NativeScript skills for an Android TV app:

android tv request via intercom

It was a bit of a 💡 moment for us, as we realized this platform deserved an unofficial home here at NativeScript HQ. Enter our old pal Eddy "the plugin" Verbruggen.

In no time at all, Eddy put together a POC to effectively offer Android TV as another build target for your NativeScript app. Watch the brief video here..

You know what he had to do? It's shockingly simple. In order to achieve raw compatibility with Android TV, you just need to add one line to your AndroidManifest.xml file:

<category android:name="android.intent.category.LEANBACK_LAUNCHER" />

But just getting an app to build and run on Android TV is one thing. What about embracing the unique capabilities of the platform?

Consult this GitHub repository for a basic, but fully-functional, NativeScript Android TV app example.

The D-Pad Controls

Unlike an iOS or Android device that allows you to use your fingers to control a UI, with Android TV you are navigating with a little remote control (the D-pad or directional pad). Therefore you really need the ability to:

  • Navigate the UI with a D-pad control, and
  • Be able to actively see where you are in the UI.

android tv ui example

This means making some minor UI adjustments to your NativeScript app. Luckily you have a couple of valid options:

Selectors

You can use Android Selectors to specifically set view states for your UI elements:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:state_pressed="true" android:drawable="@drawable/bluebutton_focused"/> <!-- pressed -->
      <item android:state_focused="true" android:drawable="@drawable/bluebutton_focused"/> <!-- focused -->
      <item android:state_hovered="true" android:drawable="@drawable/bluebutton_focused"/> <!-- hovered -->
      <item android:drawable="@drawable/bluebutton"/> <!-- default -->
    </selector>

While this does work perfectly fine, it's not really the NativeScript way. However, it works and wiring a selector is not too painful:

    export function elementLoaded(args: observable.EventData): void {
      const view = <ViewBase>args.object;

      // use a resource that specifies a 'focused' state:
      view.android.setBackgroundResource(identifier);
    }

KeyEvents

Arguably a more proper way to implement a "focused" state is with Android KeyEvents:

      public dispatchKeyEvent(event: android.view.KeyEvent): boolean {
        // you can respond to specific keycodes by fi. registering a listener and invoking it when appropriate
        console.log("D-Pad center button pressed? " + (event.getKeyCode() === android.view.KeyEvent.KEYCODE_DPAD_CENTER));

        // let's highlight the element that currently has the focus
        const tnsButton = <ViewBase>this.getCurrentFocus()["jsview"];
        if (tnsButton && tnsButton !== this.highlightedElement) {
          tnsButton.addPseudoClass("focused");
          if (this.highlightedElement) {
            this.highlightedElement.deletePseudoClass("focused");
          }
          this.highlightedElement = tnsButton;
        }
        return super.dispatchKeyEvent(event);
      }

...which you can wire up in your UI with:

    export function elementLoaded(args: observable.EventData): void {
      const view = <ViewBase>args.object;

      // set a backreference so 'dispatchKeyEvent' in app.ts can swap CSS classes
      view.android["jsview"] = args.object;
    }

...with what is effectively a focused pseudo-class in your CSS:

    .nav button {
      background-color: #87cefa;
    }

    .nav button:focused {
      background-color: #65aafa;
    }

The above example is a good opportunity to build a new NativeScript plugin, hint hint...

Separate UI Views

With NativeScript, you've always been able to have separate UI views by platform. With a clever little hack, you can also have a separate Android TV view:

    import * as utils from "tns-core-modules/utils/utils";

    if (utils.ad) {
      // Android: Load either the TV or phone UI
      const uiModeManager = utils.ad.getApplicationContext().getSystemService(android.content.Context.UI_MODE_SERVICE);
      if (uiModeManager.getCurrentModeType() === android.content.res.Configuration.UI_MODE_TYPE_TELEVISION) {
        console.log("Running on a TV");
        application.start({moduleName: "main-page-tv"});
      } else {
        console.log("Running on a Phone / Tablet");
        application.start({moduleName: "main-page"});
      }
    } else {
      // iOS
      application.start({moduleName: "main-page"});
    }

Remember, you can find a fully-functional NativeScript Android TV app in this GitHub repository.

Wrapping Up

Now it's your turn! Try taking a simple NativeScript app and add these customizations. Deploy the app to an Android TV emulator (available as part of the Android SDK) to test it out.

Finally, let us know about your experience in the comments (or submit an issue) so we can continue to fine-tune this solution for Android TV developers.

Discussion

pic
Editor guide
Collapse
apkbuilds profile image
APKBuilds

It would be great to start a project on the media player because playing the latest movies and shows online is pretty useful. Showbox official website (showboxupdates.com/) may be the iconic brand to stream media from different sources.

Collapse
bytet profile image
Bytet

I found a browser shell app I got from appsgeyser could be side loaded to my FireTV but there's no cursor as it's intended to be used with an Android touch interface. I used js-spacial-navigation from GitHub and had great success. Anyone here play with this? I have one small pesky problem when moving backwards from page to page. Previous last focused elements are gone when returning to the page and the system is intialized. You can used the directional arrow keys and enter key to mimic the d-pad controls at loopzine.tv/firetv.htm first the listed issue link is active and all videos at that issue are active in this limited demo.

Collapse
uptofast profile image
UptoFast

If you want to find an app to watch TV online, I suggest you an app. It's JioTV. JioTV is an online TV watching software, which allows users to watch Live TV channels and programs broadcast within 7 days on any Android devices at all times. You can download JioTV app at uptofast.com

Collapse
andreslopezrm profile image
ALR

Very interesting article, NativeScript is powerful I would like to know more about the subject 😄

Collapse
mobdro8 profile image
Mobdro

I think it is possible and you can watch an online TV channel at mobdro official website.

Collapse
tomlucy704 profile image
tomlucy704

Very interesting article, NativeScript is powerful I would like to know more about the subject 😄 Gacha Life 2