tv助手项目阶段性总结

1. 模块,主要负责偏底层的模块:

(1)tvd模块的下载、更新、安装、开启;

(2)通过adb获取智能电视、盒子的ip,通过dlna获取智能电视、盒子的自定义名称(其中dlna模块使用的是开源项目)。

2. 设计

(1)设计一个单例模式的TVDManager类,通过http协议下载、更新tvd.apk文件到手机sdcard上,通过adb命令安装tvd.apk到智能电视或盒子上,并安装、开启tvd;

1个主类:TVDManager.java是单例模式,实现下载:通过http协议,下载过程中的成功失败状态通过Interface回调给上层界面,首先是像服务器拉取tvd.apk文件的下载地址url和版本号等参数,数据使用Gson解析,然后更具服务器返回的是否需要更新数据以及下载地址url,下载最新版本的tvd.apk文件到手机sdcard上;实现安装:通过adb命令push tvd.apk文件到tv上,这里还需要首先通过adb命令获取tv上的tvd的版本号,来判断是否需要安装新版本的tvd.apk。所以这里就需要在启动tv助手app的时候(启动TvassistantApplication),在Application中首先调用TVDManager下载目前服务器上最新版本的tvd.apk,并通过sp存储版本号和下载sdcard的路径,然后需要安装的时候直接从这个SDCard路径中安装到tv上即可。

客户端判断:已经安装,则判断是否更新;没安装则直接安装;

4个辅助class文件:ITVDManagerCallback提供给上层界面的接口,回调下载、更新、安装的状态;TVDPackageDownloadRequest请求最新版tvd.apk文件的下载地址url和版本号、是否需要升级等;TVDRequestParams请求参数;TVDResponseParams响应参数;

问题1:这里会出现一个多线程问题:假设有2台tv,手机连接上了tv1,并且下载tvd文件,下载到了50%,这个时候切换到tv2,并且开始下载,这个时候就会出现一个问题,tv2的中的线程会重复下载(并且会覆盖)同一个版本的tvd文件(因为这个tvd文件在安装到tv上之前,是先存放在手机sdcard文件系统中的),这个时候就要用ReentrantLock来锁定互斥区(下载的文件),来解决问题,又由于这个下载线程是异步事件,因此不能用synchronized,需要使用ReentrantLock来解决。

问题2:现象时,服务器、手机、tv上的tvd版本不一致;场景,当需要更新tvd文件时(从服务器上拉取tvd返回的标志标明需要更新tvd),这时候app启动的时候就会从服务器中下载文件,当下载文件没有完成时,这个时候点击连接tv(这个过程从tv本地获取tvd的版本号与手机本地存储的tvd版本号比较,如果一样则不更新tv上的tvd,如果不一样才更新),由于手机本次存储的tvd版本号还没有被服务器上的更新,所以手机上的tvd版本号是脏数据,导致这一次tv上的tvd没有得到更新;对于这个问题,我开始的设计是:使用ReentrantLock的Condition条件变量来实现,即,当启动App时,首先获取锁并持有条件变量,当拉取的服务器标志是要更新,则更新完并把版本号写入到手机本地后,再释放锁和通知释放条件变量,当点击连接tv,检查tv上tvd版本号与手机本地tvd版本号时,在这个条件变量上等待,直到接到通知;如果服务器返回的数据不需要更新tvd,则立马释放锁和通知条件变量。

但是,目前这个会影响连接tv的性能,因为无论如何都必须等待手机从服务器上拉取是否更新的标记和更新地址,这样才是真正的连接tv过程。。。。严重影响用户体验。。。暂时没用。

(2)adb Service和DLNA Service都是异步行为,因此,如果想让他们同时显示ip地址和电视名称是不可能的,同时又考虑到项目中的连接、安装功能都必须使用adb来实现,因此,我们以adb命令探测到的ip地址为主key,adb探测到的电视ip地址设计一个列表List<String> ipListAdb 用于存储ip;DLNA方式探测到的ip和name设计一个哈希表Map<String, String> ipNamemapDlna来存储ip和电视自定义名称,因为探测到的电视/盒子个数是以ipListAdb中数量为主,因此我们的ListView的数量也是以ipListAdb为数据源,更新数据源的时机处了是ipListAdb改变外,还有就是ipNameMapDlna的改变后,查询ipListAdb是否有对应ip,如果有更新,如果没有,放弃;在ListView的adapter中,我们的getItem是使用ipListAdb中查询到的ip地址作为key,返回ipNameMapDlna中的value。【这里验证了一个问题:ListView的数据源更新,并不一定必须是数据源个数的变化才notifyDataSetChanged,数据源的显示改变也可以用notifyDataSetChanged更新ListView】。

以上的设计用户体验方面很差劲儿,adb获取速度比dlna快的多,因此,dlna获取的名称很滞后,所以,改了设计:当启动App的时候(在Applicaton中执行)就启动DLNA Service,然后设置异步回调事件处理把获得的ip-name存入sp,等进入首页后,开启adb service扫描到tv或盒子的ip地址,然后在sp中查找对应的name,如果找到就显示name,找不到就显示默认名称,这种设计缺点是:存储在sp中的ip-name对与其他存储在sp中的值相混淆,使得公共sp很杂乱,而且用户体验方面也不好:用户第1次使用App时,sp中的ip-value对很可能没有建立,因为DLNA比adb慢,所以,一般情况下是先显示adb拉到的ip和默认名称,而且如果用户把盒子名称更改了,也不会及时得到更新;

针对以上2点缺点,重新设计为:使用java中的Properties类来把ip-name对存入文件(/data/data/package-name/files/xxxx.properties文件)中;使用interface回调给UI界面更新设备名称,当扫描到设备并获取设备名称后,这个解决第1次使用app时显示不出设备名称问题和用户更改设备名称得不到及时更新问题;

过程是:启动app时,从文件中获取ip-name对存入Map中,然后用adb扫描到的ip来查找Map中name,显示给UI,如果Map为空,则显示为默认设备名称(这个情况只会出现在第1次使用App时,这时Properties文件还没建立,所以Map一定为空,之后再次开启就直接从Properties文件中获取即可),并且设定DLNA扫描到设备的回调,一旦有新设备加入则回调给UI跟新设备名称,即使用户更新了设备名称,也能通过这个interface回调给UI更新设备名称。

----项目工作记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值