Android TV框架TIF_安卓tv开发用什么框架-程序员宅基地

技术标签: TIF  TV Input  Android TV  

Android TIF(Android TV input Framework)是Google向电视制造商提供了一套标准的API,用于创建Input模块来控制Android电视。这套API的底层实现的原理是aidl和provider,从而进行了跨进程通信。系统或第三方的应用可以通过TIF获得所有输入(input)的信源(输入的模块包括:搜台模块,MDMI模块,网络模块等),然后通过AIDL切台输出到屏幕上。

电视相关知识

在介绍这套框架之前,先复习一下电视相关的专业术语

  • HDMI:高清晰度多媒体接口(英文:High Definition Multimedia Interface,HDMI)是一种数字化视频/音频接口技术,是适合影像传输的专用型数字化接口

  • IPTV:网络电视,也叫VOD电视,三方比如说某某视频公司提供的视频资源在电视上播放

  • DTV:数字电视

  • ATV:模拟电视

TIF的组成部分

在这里插入图片描述

  • TV Provider (com.android.providers.tv.TvProvider):一个包含频道、节目和相关权限的数据库

  • TV App (com.android.tv.TvActivity):一个和用户交互的系统应用

  • TV Input Manager (android.media.tv.TvInputManager):一个中间接口层,能够让TV Inputs和TV App进行通讯

  • TV Input:可以看做是一个代表物理或者虚拟的电视接收器或者输入端口的应用。Input在TIF中可以看做是一个输入源

  • TV Input HAL (tv_input module):TV Input的硬件抽象层,可以让系统的TV inputs访问TV特有硬件

  • Parental Control:儿童锁,一种可以锁住某些频道和节目的技术

  • HDMI-CEC:一种可以通过HDMI在多种设备上进行远程控制的技术

  • CEC(Consumer Electronics Control):消费电子控制

TIF的整理使用流程

在这里插入图片描述
如上图所示,LiveTV App通过turning调用TV Input Manager获得一个session,session里面放的是一路信源的状态。TvInput将获得的Channel和Programs信息写入到/data/data/com.android.providers.tv/databases/tv.db数据库中。LiveTV App通过session以aidl的方式调用TVinputService获得相关的频道和具体的节目信息进行播放。

启动流程

SystemServer -> TvInputManagerService <-> TvInputHardwareManager <-> TvInputHal->JNI <-> HAL
在这里插入图片描述

接口介绍

TvView

负责显示播放的内容。它是一个ViewGroup的子类,它是切台的入口,内置surface用于显示视频播放的内容和通过控制session可以控制音量的大小等

TvInputService

这是一个重要的类,继承它并实现一些规范就可以实现一路Input信源供其它应用使用。

在该Service中要实现onCreatSession()方法,该方法会返回一个TvInputService.Session对象。

这里的Service在Manifest中定义时要注意要添加permission和action,添加完之后,系统的TvInputManager可以检测到该Service是一个TvInputService,也就是一路信源。

<uses-permission android:name=“android.permission.TV_INPUT_HARDWARE” />
在这里插入图片描述

TvInputService.Sssion

该session类TvView通过Tune方法会指定相应的inputId(往往是该service对应的“包名/.类名”)和uri,uri中包含对应的节目id,该tune方法会调用Session的Onturn方法中,在这个方法中解析传过来的id,根据id利用TvProvider去查询数据库的数据,设置给player,这里使用onSetSurface()方法将TvView创建的surface设置给player,然后player就在该surface上显示内容。

TvContract

介于TvProvider和TvApp之间的一层封装,它里面封装了一些uri。有两个内部类是两个JavaBean,他们分别是TvContract.channels(频道表),TvContract.Programs(频道里面的节目单)。

TvInputManager

这个是TIF的核心类,它是系统的类,可以监测到在系统的Service中注册android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMSaction的类,并将其设为一路信源。它来管理一些回调,比如video是否可用,video的大小尺寸是否变换。

通过下面的代码可以获得一个TvInputManager:

TvInputManager tvInputManager =(TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);

得到TvInputManager后我们可以遍历拿到系统当前有多少个service是TV信源:

List<TvInputInfo> list = tvInputManager.getTvInputList();
  for(TvInputInfo info:list){
    
  Log.i(TAG, "id:" + info.getId());
}

我们可以拿到inputId,在TvView的tune方法中设置。这里的信源就是注册了服务并没有开启,在TvView的tune方法调用的时候会开启服务。

TvInputInfo

TvInput的信息,包括频道类型,图标,名称等。

TvInputCallback

这里是TvView的一个内部类,TvInputCallBack可以反馈给TvView一些信息比如连接Service是否成功,Video是否可用等:

tvView.setCallback(new TvView.TvInputCallback() {
    
@Override
 public void onConnectionFailed(String inputId) {
    
super.onConnectionFailed(inputId);
LogUtil.i(this,"MainActivity.onConnectionFailed:"+inputId);
}
@Override
public void onDisconnected(String inputId) {
    
super.onDisconnected(inputId);
LogUtil.i(this,"MainActivity.onDisconnected.");
}
@Override
public void onVideoSizeChanged(String inputId, int width, int height) {
    
super.onVideoSizeChanged(inputId, width, height);
LogUtil.i(this,"MainActivity.onVideoSizeChanged.");
}
@Override
public void onVideoAvailable(String inputId) {
    
super.onVideoAvailable(inputId);
LogUtil.i(this,"MainActivity.onVideoAvailable.inputId:"+inputId);
}
@Override
public void onVideoUnavailable(String inputId, int reason) {
    
super.onVideoUnavailable(inputId, reason);
LogUtil.i(this,"MainActivity.onVideoUnavailable.");
}
......
});

使用注意事项

通过uri解析id

Long channelId = ContentUris.parseId(channelUri);

状态的回传

在TvView中我们如果想要获取一些播放器的状态,比如buffer状态,在开始播放之前有一个loading的状态,获取节目的size的变换,以及自定义的一些状态。下面依次说明:

loading状态的回传

在tune方法的时候使用mSimpleSession.notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING); 通知Video不可用,原因是tuning其他对应的状态还有:

TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN:未知原因
TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL:信号弱
TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING:缓冲
TvInputManager.VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY:仅仅是音频

在视频播放的时候即在onPrepared时调用mSimpleSession.notifyVideoAvailable()

buffer状态的回传

在MediaPlayer中Buffer的两种状态,开始缓冲和结束缓冲对应的是701和702两个状态。在MediaPlayer的onInfo方法中收到了701开始调用mSimpleSession.notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING);

自定义的状态

这个使用make的方式编代码的时候才能引用,因为这个方法用@system api注解了。
可以传一个bundle对象:notifySessionEvent(@NonNull final String eventType, final Bundle eventArgs)

Program表清空问题修复

在使用TvProvider提供的Program表的时候,我这里遇到了一个问题,发现表的数据会被不定期的清空,测试那边给的也是偶现的,通过断网,切台,重启系统发现programs表总是被清空。

对于开发来说找到bug的复现步骤是最好不过的事情了。通过阅读TvProvider的源码可以看到有一个类专门负责清空Programs的数据,在EpgDataCleanupService
中会去清除当前时间以前的节目信息,在这个字段对应的时间信息COLUMN_END_TIME_UTC_MILLIS,而这个时间是以毫秒为单位的,我们服务器给的数据是以秒为单位的,所以会被清空,修改一下就可以了:

 /**
  * Clear program info that ended before {@code maxEndTimeMillis}.
  */
 @VisibleForTesting
void clearOldPrograms(long maxEndTimeMillis) {
    
    int deleteCount = getContentResolver().delete(
             Programs.CONTENT_URI,
             Programs.COLUMN_END_TIME_UTC_MILLIS + "<?",
             new String[] {
     String.valueOf(maxEndTimeMillis) });
    if (DEBUG && deleteCount > 0) {
    
        Log.d(TAG, "Deleted " + deleteCount + " programs"
              + " (reason: ended before "
               + DateUtils.getRelativeTimeSpanString(this, maxEndTimeMillis) + ")");
    }
 }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/johnWcheung/article/details/102753200

智能推荐

复位那些事儿_复位信号下降沿-程序员宅基地

文章浏览阅读649次,点赞3次,收藏6次。复位那些事儿欢迎关注公众号【TechDiary】,专注原创技术分享当我们进行IC/FPGA设计时,不可避免地会遇到复位信号的设计。复位信号是一个数字系统中基础又重要的设计,设计失误轻则bug频出,重则系统宕机。本文将从以下几个方面讨论复位设计相关的内容:同步复位介绍异步复位介绍异步触发同步释放复位及Verilog设计同步复位介绍顾名思义,“同步”即与时钟同步,也就是说,复位信号与时钟有特殊的相位关系。这样的复位信号将建立在满足系统的建立时间、保持时间的基础上,我们不需要担心它会引起电路中的_复位信号下降沿

第8周【项目1 - 猴子选大王(数组版)】-程序员宅基地

文章浏览阅读276次。/* *Copyright(c)2017,烟台大学计算机学院 *All right reserved. *文件名称:20171116.cpp *作者:李小同 *完成日期;2017年11月16日 *版本号;v1.1 * *问题描述:如下 *输入描述:功能需求 *程序输出:所需功能的实现 */ 一群猴子,编号是1,2,3 …m,这群猴子(m个)按照1-m的顺序

比较JDBC和Mybatis进行批处理时的性能比较-程序员宅基地

文章浏览阅读1.8w次,点赞5次,收藏11次。执行批量操作时,做了个比较Mybatis和JDBC执行时间的记录,JDBC还是强大太多了!jdbc.properties文件jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8&amp;allowMultiQueries=true&amp;rewriteBatchedSt..._比较jdbc和mybatis进行批处理时的性能比较

KubeSchedulerConfiguration解析-程序员宅基地

文章浏览阅读5.1k次。前言kube-scheduler如何配置调度框架和调度插件中提到的插件(比如使能或禁止哪些插件?)?如何配置调度队列的排序函数以及退避时间?本文将详细解析kube-scheduler的配置,在kube-scheduler中,配置也是一种API对象(其实在Kubernetes中都是这种设计,万物皆可API化),它被定义在k8s.io/kubernetes/pkg/scheduler/apis/config包中。本文引用源码为kubernetes的release-1.21分支。KubeSchedul_kubeschedulerconfiguration

JdbcTemplate and HibernateTemplate_getjdbctemplate() 与gethibe-程序员宅基地

文章浏览阅读285次。首先获取JdbcTemplate对象public static JdbcTemplate getJdbcTemplate(){ //创建dataSource DriverManagerDataSource dataSource=new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Dri..._getjdbctemplate() 与gethibe

【20210326期AI简报】用RISC-V微控制器开发难不难?行人搜索AI框架新突破~-程序员宅基地

文章浏览阅读430次。导读:本期为 AI 简报 20210326 期,将为您带来 9 条相关新闻,明日朝花节,有时候要冲,有时候也要出去走走~本文一共 字,通篇阅读结束需要 7~11 分钟1. 首个无需锚框(A..._riscv支持ros吗?

随便推点

数学2考点-程序员宅基地

文章浏览阅读114次。----考试形式和试卷结构一、试卷满分及考试时间试卷满分为150分,考试时间为180分钟。二、答题方式答题方式为闭卷、笔试。三、试卷内容结构高等教学约78%线性代数约22%四、试卷题型结构单项选择题8小题,每小题4分,共32分填空题6小题,每小题4分,共24分解答题(包括证明...

Chrome小恐龙游戏前端修改代码【含原理和代码】_小恐龙游戏网站代码-程序员宅基地

文章浏览阅读4.2w次,点赞26次,收藏64次。Chrome小恐龙前端修改代码分享Chrome小恐龙是什么?在Chrome(谷歌浏览器)断网之后访问在线页面,如a.com会出现以下界面,叫做Chrome小恐龙游戏.这是一个隐藏的彩蛋。除了断网以外,直接在Chrome里访问网站chrome://dino/也可以看到。这时按空格就可以开始游戏了。怎么控制游戏?按键中文名用途UpKey箭头上跳跃DownKe..._小恐龙游戏网站代码

python用于pmc排产可以吗_生产计划员每天都在抓狂,插单、排产问题到底该怎么解决?...-程序员宅基地

文章浏览阅读512次。紧急插单是指那些未安排在确定好的订单计划中,却由于某些原因必须优先交货的订单,这些订单会打乱原有的生产计划安排。在竞争日益激烈的市场环境中,通过及时响应紧急插单,迅速准确地完成订单交付,增加客户满意度和忠诚度,企业可以获得比竞争者更多的利润。大多数企业都处于紧急插单频发且生产计划流于形式的不良状态。在企业的工厂里面经常可以看到如下几个场景:PMC部说:“我计划排得好好的,但是业务部、甚至老..._python pmc算法

AltiumDesigner20画图不求人13 | 提高AD20启动速度方法九取消一些相关的元件选择 | 视频教程 | 你问我答_怎么提高ad流畅度-程序员宅基地

文章浏览阅读1.1k次。很多芯粉都遇到的问题就是AD20启动时间长,需要感觉N久的时间才能启动起来,今天为大家介绍可以提高AD20启动时间的方法八。取消一些相关的元件选择。视频教程AltiumDesigner画图不求人13| 提高AD20运行速度,取消一些元器件软件安装步骤打开Altium Designer,点击右上角小齿轮,进入Preferences。在Preferences属性窗口中,选择Data Management下的Parts Providers,将红框内的勾选全部去掉。大..._怎么提高ad流畅度

Qt实现截图之二 截图裁剪框实现方案1 窗口组合方式_qt实现裁剪选择框-程序员宅基地

文章浏览阅读1.2k次。截图相关介绍参考Qt实现截图之一整个截图分为两层,一层为截图显示区,一层为裁剪选着层,裁剪选择层蒙在截图显示区之上。本节介绍一种方案实现裁剪框。裁剪层分为5个区域,上下左右和中间,分别代表5个QWidget, 中间区域即为需要裁剪的区域-高亮区域,没有截图时此区域不存在。1.布局top, left,right, bottom 是个窗体均设置半透明颜色,mid是全透明效果就是裁剪区域void MaskFrameBase::setup(){ this->set._qt实现裁剪选择框

QT使用CDB远程调试_qt cdb-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏11次。1、开发环境:本地端:1)win 102)IDE Qt Creator 4.8.03) CDB 调试环境 ,因为我有装VS 2017 的环境以及前期安装过 Debugging Tools for Windows 所以这就不讲了,环境没搭好的朋友自行百度一下远程主机配置:win 7 32bit 注:如果要调试64位要把X86改X641)、创建文件夹在桌面创建了【Debug】文件夹方便调试和设置C:\Users\Administrator\Desktop\Debug2)、环境变量设_qt cdb

推荐文章

热门文章

相关标签