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?
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!? 😉
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:
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.
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.
Top comments (5)
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.
Very interesting article, NativeScript is powerful I would like to know more about the subject 😄
I think it is possible and you can watch an online TV channel at mobdro official website.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.