【Android】TV端项目开发挖坑总结

最近完成了一个TV端的项目,大致包括影视、直播观看,手机投屏操控,内容分类推荐等功能,解决了一些坑,但同时也挖了好多(逃(●’◡’●),在此简单记录一下

1.foucus焦点问题:

简单基础的view通过android:focusable="true"、android:nextFocusLeft=""、设置selector背景等属性就可以搞定,但如果你要实现复杂布局(或者嵌套布局)的recyclerview或者listview,那就需要自己重写事件处理了。当然你和我一样懒得话,可以使用google的leanback库,不过这样可客制化的空间就变小了,个人也不是很推荐使用吧,有利有弊,具体怎样使用下面解释。

2.播放器IjkPlayer问题

主要就是so库蛋疼的编译问题。。。如果你是windows电脑的话基本可以不用自己编译了,可以在这做一回伸手党拿到so库,接下来就是自己把IjkPlayer封装成一个自定义的framelayout,根据需求处理其各种回调(缓冲、暂停、启动、重播、后台、出错、完成等等),开心的是TV端只要做一些最简单的播放操作就可以了,至于弹幕、旋转、音量、亮度等完全不需要考虑。
播放结束后记得relase播放器即可。

3.手机投屏、操控问题解决

采用了NSDManager+AsyncHttpServer开源库的方式起长连接完成。简单解释下就是:

———————Server(TV端)——————————————–
1.后台service起一个AsyncHttpServer
2.配置NsdServiceInfo的端口号、协议类型、协议名等信息,并注册NSDManager Service (等待client 来扫描连接)
———————Client(手机端)—————————————
3.注册NsdManager.DiscoveryListener(扫描),及NsdManager.ResolveListener(扫描条件满足后的连接listener)
4.连接socket
5.发送交互信息

连接完之后,我们就能自定义上层信息协议了(通过setStringCallback,解析不同string完成不同操作)。比如说用户token传递、投屏影片url传递,完全只需要加密过后以string的方式传递过来,server解析后跳转对应界面就行了。至于远程遥控功能,目前我是使用Instrumentation来发送虚拟按键,从而完成手机遥控。

4.界面展示与网络请求数据

由于TV端一般都是采用tab标签+fragment的形式,而且数据一般不会短时间内变化,所以最好不要频繁刷新数据与view,请求一次后如果没有触发刷新事件,你就可以一直用这次的response,fragment也只需要hide即可。

5.leanback相关使用问题

主要是针对VerticalGridFragment的定制,实现这样一个界面,并可以将focus移动到上方tab的位置。

【Android】TV端项目开发挖坑总结 - 阿里云
我的收藏.png

官方demo也比较清楚,要实现这样一个效果,只需要照着它的模板去实现一个PresenterSelector(如果只有一种viewtype,直接提供一个Presenter即可)和ArrayObjectAdapter即可,将网络请求的数据add进adapter就会自动去notify,主要是一些UI细节方面需要我们去改变。

加载数据前后loading界面:
getProgressBarManager().show();
getProgressBarManager().hide();

设置列数,行间距:
/**
* Created by lucky on 2017/7/17.
*/
public class CustomVerticalGridPresenter extends VerticalGridPresenter {
private VerticalGridView gridView;
public CustomVerticalGridPresenter(int focusZoomFactor) {
super(focusZoomFactor);
}
@Override
protected void initializeGridViewHolder(ViewHolder vh) {
super.initializeGridViewHolder(vh);
gridView= vh.getGridView();
int top= DensityUtil.dip2px(vh.getGridView().getContext(),25);//this is the new value for top padding
int bottom= gridView.getPaddingBottom();
int right= gridView.getPaddingRight();
int left= gridView.getPaddingLeft();
gridView.setPadding(left+top,top,right+top,bottom+top);
gridView.setHorizontalSpacing(top);
gridView.setVerticalSpacing(top);
}
}

接着在VerticalGridFragment中:

CustomVerticalGridPresenter gridPresenter = new
CustomVerticalGridPresenter(ZOOM_FACTOR);
gridPresenter.setNumberOfColumns(COLUMNS);
setGridPresenter(gridPresenter);

VerticalGridFragment顶层控件不能向上导航focus,如上图中焦点无法移动到我的收藏那一行item:

可以重写一个一模一样的lb_vertical_grid_fragment,自己写的布局会覆盖掉系统的布局,再将BrowseFrameLayout重写成我们自己的BrowseFrameLayout。

主要是因为VerticalGridFragment中的父布局拦截了事件,详细原因可以看这