聊聊真实的 Android TV 开发技术栈

2020-03-09 22:11:39

参考地址 聊聊真实的 Android TV 开发技术栈

智能电视越来越普及了,华为说四月发布智能电视跳票了,一加也说今后要布局智能电视,在智能电视方向,小米已经算是先驱了。但是还有不少开发把智能电视简单的理解成手机屏幕的放大,其实这两者并不一样。

一、序

你慢慢会发现,身边所有的电视都变成了智能电视。这是很容易接受的事实,智能电视更便宜。

价格是不容忽视的敏感点,顾客会天然的选择物美价廉的智能电视。这看似不符合逻辑,为什么选择落后的技术,不允许联网的传统电视反而更贵呢?

厂商靠硬件的利润是固定的,当小米发布“年轻人的第一台电视”之后,通过搭建并自营广告、付费内容分发等服务手段,将用户数据紧握在自己手中并实现货币化。以服务的收入来补贴硬件的成本,极大的压低了智能电视的售价。

这很容易理解吧,之前都是单纯的制造商,卖出一台电视赚一台电视的钱,撇开需要提供的质保服务之外,这就是一锤子买卖。而当电视可以联网之后,就可以延伸出更多可能,你每一步操作都有广告的体验、推荐给你的电视 App、你在电视上看的付费视频,这些都是服务的费用,在你电视的使用寿命一直到终结,厂商都可以从你那里获得价值。

电视厂商已经开始从制造商转变成服务商了。智能电视是大势所趋,回头是不可能回头的,可能今后会有厂商继续生产小众的传统电视,但也只是小众。

再说回到技术上,对于智能电视的系统,得益于 Android 的开放,市面上占有率最大的就是 Android 系统,其它 Apple TV、Chromecast 都是比较小众的。另外三星之类的厂商,也从去年开始将新款电视的系统,选定为 Android。

在智能电视领域,Android 才是主流。

不少人对 Android TV 的技术印象,还停留在移动开发上,但其实它们并不一样。

二、技术与 Android TV

只要是个 Android 开发,就可以很容易的上手 Android TV 的项目,这一点毋庸置疑。

但是又不那么完全一样,不能简单的把 TV 开发理解成更大屏的手机去做,这其中还是有一些细节需要打磨的。

本文我就换一个角度,来分析 Android TV 开发所涉及到的一些技术点。

2.1 设计风格不同

电视最直观的感受就是大屏,但是不能仅仅把它当成放大版的手机,这是有根本区别的。

在做电视 UI 设计的时候,要考虑到这个设计在两三米开外,还能不能看见,电视和手机的视距是不一样的。

在做设计的时候,就讲究大块、留白、滚动、焦点效果等等,了解其中的差异即可。

2.2 API 的差异

都是 Android 系统,在手机上能用的那一套 API,在智能电视上都可以用到。智能电视用到的 API,算是移动开发的一个补充。

举个最简单的例子,在手机上操作,点击一个内容只有两态,普通态和按下态,而在电视上是有三态的,无焦点态、获取焦点态和按下态,这就需要在移动开发中根本不会用到的 android:focusableInTouchMode 属性来支持。

另外还有一些对焦点的处理,例如焦点动画、焦点记录、焦点寻址等,虽然 Android 是以就近原则来计算方向操作时,下一个获取焦点的控件,但是有时候还是需要我们通过代码去控制它的寻址效果。



电视开发还有很多 API 上的区别,这里就不一一举例了,其实很多效果都可以参照 Leanback 的实现,这个后文会介绍。

2.3 涉及的工具

在电视开发中,也有一些工具可以提高我们开发的效率。

虽说智能电视本质还是 Android 设备,但是大部分电视和智能盒子在出厂时,已经关闭了调试口,如果和厂商合作或者在论坛搜寻,有一些特定的设备,经过特殊的设置是允许开启 ADB 调试的。开启调试后,我们就可以通过 adb connect 进行连接,之后的调试就和普通的手机开发没有区别了。参考:《常用 ADB 命令

电视调试有时候确实很麻烦,如果不是和特定硬件强相关的需求,我们可以直接使用普通手机进行开发调试。

电视和手机的交互方式是不同的,手机通过触摸屏幕,而电视只能通过遥控器按键操控。那么为了在手机上模拟电视遥控器的操作,这里推荐一个 Chrome 插件:ChromeADB

只需要保证开发设备和调试设备,ADB 连接通畅,通过 ChromeADB,实现一些遥控器的简单上下左右的操作。

2.4 Google 的 Leanback 项目

Leanback 是 Google 真的 TV 开源的一款 UI 框架,可以使用 Leanback 快速实现 UI 效果,Leanback 主要都是围绕 Fragment 展开的。

在国内的 TV App 项目中,基本上都不会使用 Leanback 推荐的效果,就像 Google 的 Material Design 设计,所有设计都在转发文章,但是就是不用,不过这并不妨碍我们研究它的实现。

Leanback 内提供的 RecyclerView 把一些很头疼的焦点记忆、焦点项目放大、滚动时焦点块居中等问题都封装好了,简单到可以拿来即用。

Leanback 最大的问题是它是一个 v17 的项目,也就是 minSdkVersion 为 17,而在国内的环境下,TCL、联想都还在出厂 4.2 以下的电视和盒子。也就是说对于一个商业项目,你想完全依赖 Leanback 的官方指导来开发 App,将会有一部分设备的市场被放弃掉。

但是这并不是无法解决的硬伤,我印象中只是某些数据刷新的 notifyDataXxx() 方法,对 API Level 有要求。所以只需要将这部分逻辑自己来实现,就可以将 Leanback 用在 V14 的设备上。

具体实现我就不放代码了,在 Github 上搜索 “V14 Leanback” 关键字,就能够有所收获。

Leanback-GoogleSample Github:github.com/googlesampl…

2.5 音视频

智能电视虽然可以安装一些 App,可最终还是要回归本质,看电视。大部分电视 App,都是围绕着音视频方向,做内容分发。

你能想到的主流视频 App,都存在电视版 App,做电视开发无可避免的会遇到音视频方向的问题。

有关音视频方向,简单点呢找个 Github 上的开源库封装一下也能用,但是不了解细节出了问题也很难排查。想要向这个方向研究,推荐一本前爱奇艺音视频方向专家何俊林的书《Android 音视频开发》。

如果让我针对智能电视的音视频,只提一个建议,那肯定是慎用硬解,慎用硬解,慎用硬解。

这很好理解,现在一台智能电视比很多手机都便宜,最大的成本占比在屏幕上,可想而知它的其他硬件,还不如小米几百块的手机。

当你使用硬解的时候,在一些低端设备上的表现就不可控了,会碰到非常恶心的黑屏、马赛克、花屏等问题。所以如果你的经验没那么丰富,推荐直接使用软解。

2.6 投屏协议

电视的真实需求,还是看电视,任何强操作的需求,在电视上都是伪需求。

智能电视联网后,我们就不必将看电视这个动作局限在直播中。要想将手机上的内容投到电视上播放,这就涉及到投屏的协议。

市面上存在很多投屏的协议,但凡对投屏有点想法的都会定制一套投屏的协议。主流的只有两个 Google 的 DLNA 和 Apple 的 AirPlay,这已经是属于现在智能电视出厂时的标配。

就像微信对手机的关系一样,某个手机要是微信退出到后台就收不到消息了,用户只会说这个手机有问题而不会说微信有问题。这两个协议对智能电视也是一样。

但是有归有,好不好用就是另外的说法了。所有的投屏协议,都是存在两端,客户端和接收端,智能电视在出厂时,集成的都是接收端的协议,如果遇上不好用的情况,可以尝试安装“乐播投屏 App”来解决。

大多数情况下,我们更多的是和协议的客户端在打交道,这里推荐一个开源项目 ConnectSDK,在其中对大部分协议做了支持。

ConnectSDK 是一个全平台的 SDK,接入也有明确的文档和示例,这里就不详细讲解了。

官网:connectsdk.com/

Github:github.com/connectsdk

投屏的功能,在大部分主流的视频 App,都是集成了投屏的功能。还有一些比较小众的 App,例如快点投屏,可以将一些视频网站上的内容,投到智能电视上观看。

投屏在智能电视的技术栈中,必定是需要点亮的。

2.7 本地服务

还是为了解决电视上操作困难的问题,例如最简单的一个需求,想要把下载好的蓝光高清的电影,Copy 到电视上观看,操作难度都都不小。

所以不少 App 都通过搭建本地服务的方式,方便用户在电视和其他设备之间传输文件。

在 Android 上,开启一个 HTTP 服务的方法,有很多开源项目可供选择。

这里推荐 nanohttpd,只需一个文件就可以在 Android 上实现一个本地的 HTTP 服务器。并且使用的人很多,上传文件、webserver 等已经被实现了,开箱即用。

Github:github.com/NanoHttpd/n…

三、小结时刻

我想看完本文,你对 Android 智能电视开发应该有了一个基本的了解,不会再将它了解成一个更大屏的手机了。

就像前文提到的,智能电视注定是会被普及的,我最近看到头条这样做短视频的公司,都已经开设了 Android TV 的产品岗位,我想今后 TV 开发相关的岗位会越来越多。


  • 2019-02-24 09:47:09

    解决Node.js的命令行输出中文乱码问题(也适用于Electron)

    ​一般我们的js文件都是试用utf8编码保存的,但是中文windows的命令行一般默认使用cp936编码(就是gbk),这样我们用js代码 console.log('中文');输出日志的时候,会发现输出的是乱码。 网上有提供一些解决方案,典型的就是用iconv或iconv-lite,把这些中文字符串先转成gbk再输出。 但是这个方案我试了多次,在win10的命令行下,utf8的字符串是成功转成了gbk字符串了(通过打印Buffer可以见到),但是输出还是乱码。

  • 2019-02-25 10:05:41

    Android Socket连接(模拟心跳包,断线重连,发送数据等)

    因为是要保证全局只能有一个连接,而且我们还需要在不同的Activity中发指令,因此肯定不能在需要发指令的界面中都去连接socket,这样一来不好管理,性能也不好,重复代码也会比较多,所以想了一下还是把socket放到service中比较好,发指令功能都放在service中即可。

  • 2019-02-28 15:54:24

    HTTP协议缓存策略深入详解之ETAG妙用

      HTTP协议规格说明定义ETag为“被请求变量的实体值” 。另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端。

  • 2019-02-28 16:46:26

    android获取视频、图片时添加防盗链

    使用HTTP协议时,可以利用头信息中的Referer做防盗链。 我们在一些网站的网页里访问图片的时候,在图片本站是可以正常看到的,但在外头就不能看到了,这是因为在http的header信息中的referer元素。

  • 2019-03-02 11:29:17

    MySQL学习之索引顺序

    这个问题比较简单,MySQL本身会对条件和索引进行判断,这样写可以用到索引,没有问题。