返回博客首页
← 所有文章

使用 NativeScript 构建 Android TV 应用

2018年4月25日 — 作者:Rob Lauer

如果你在这里,我猜 NativeScript 是你开发原生跨平台应用的首选(或者很快就会成为!),它可以从一个代码库为 iOS 和 Android 构建应用。我想标题已经说明了一切,但你知道你也可以使用 NativeScript 为Android TV构建应用吗?

nativescript and android tv

虽然 Android TV 还没有风靡全球(至少现在还没有),而且我们也没有正式支持这种集成(至少现在还没有),但将其视为您杀手级应用开发技能的另一个渠道仍然是一项有趣的尝试。

那么什么是 Android TV?Android TV 是一种机顶盒(由 Android 提供支持),允许您将内容流式传输到您的电视📺。在许多方面,您可以将其与 Apple TV 进行比较,但没有 Apple 生态系统固有的硬件限制。Android TV 上最常见的应用侧重于媒体消费和游戏,但该平台正在等待其下一个杀手级应用。

也许是时候再次尝试 WebTV 了!?😉

webtv

简史

有一天,我们收到了一位NativeScript Sidekick用户的消息,他希望利用其 NativeScript 技能开发 Android TV 应用。

android tv request via intercom

这对我们来说是一个💡时刻,因为我们意识到该平台应该在 NativeScript 总部拥有一个非官方的归宿。于是我们请来了我们的老朋友Eddy "插件" Verbruggen

Eddy 马上就完成了概念验证,有效地将 Android TV 作为 NativeScript 应用的另一个构建目标。

你知道他做了什么吗?这令人惊讶地简单。为了实现与 Android TV 的原始兼容性,您只需在 AndroidManifest.xml 文件中添加一行代码即可。

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

但是,仅仅让应用在 Android TV 上构建和运行是一回事。那么如何利用该平台的独特功能呢?

请参阅此 GitHub 代码库,了解一个基本但功能齐全的 NativeScript Android TV 应用示例。

方向键控制

与允许您使用手指控制 UI 的 iOS 或 Android 设备不同,在 Android TV 上,您使用一个小遥控器(方向键或方向盘) 进行导航。因此,您确实需要能够

  • 使用方向键控制导航 UI,以及
  • 能够主动查看您在 UI 中的位置。

android tv ui example

这意味着对您的 NativeScript 应用进行一些小的 UI 调整。幸运的是,您有几个有效的选项。

选择器

您可以使用Android 选择器专门为您的 UI 元素设置视图状态。

<?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>

虽然这确实可以完美地工作,但这并不是真正的 NativeScript 方式。但是,它确实有效,并且连接选择器并不太麻烦。

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

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

按键事件

可以说,实现“焦点”状态的更合适方法是使用Android 按键事件

  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);
  }

…您可以使用以下方法将其连接到您的 UI 中:

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;
}

…使用 CSS 中实际上是focused伪类的功能。

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

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

以上示例是一个很好的机会来构建一个新的 NativeScript 插件,提示提示…

单独的 UI 视图

使用 NativeScript,您始终可以通过平台拥有单独的 UI 视图。通过一个巧妙的小技巧,您也可以拥有一个单独的 Android TV 视图。

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"});
}

请记住,您可以在此 GitHub 代码库中找到一个功能齐全的 NativeScript Android TV 应用。

总结

现在轮到你了!尝试获取一个简单的 NativeScript 应用并添加这些自定义项。将应用部署到 Android TV 模拟器(作为 Android SDK 的一部分提供)以进行测试。

最后,请在评论中告诉我们您的体验(或提交问题),以便我们可以继续为 Android TV 开发人员微调此解决方案。