项目中 由于用户投诉, 新增了一个需求, 用户在看tv的时候, 关机重启后 仍然希望是进入tv界面下,而我们现在是不管上次关机是在tv还是launcher下, 重启以后都是进入launcher下。 想想这个需求是很正常的, 用户买回电视主要还是看tv的, 每次重启后都是进入launcher, 每次都需要手动切换到tv下, 用户不投诉才怪。

解决办法也比较简单,

一,

在系统属性中增加了一个属性, persist.sys.bootfromui,  进入launcher的时候 将persist.sys.bootfromui 设为true, 进入tv的时候将persist.sys.bootfromui设为false。 在ActivitStack.java 增加的代码如下:

   final boolean resumeTopActivityLocked(ActivityRecord prev) {
1288         // Find the first activity that is not finishing.
1289         ActivityRecord next = topRunningActivityLocked(null);
1290
1291         // Remember how we'll process this pause/resume situation, and ensure
1292         // that the state is reset however we wind up proceeding.
1293         final boolean userLeaving = mUserLeaving;
1294         mUserLeaving = false;
1295
1296         if (next == null) {
1297             // There are no more activities!  Let's just start up the
1298             // Launcher...
1299             if (mMainStack) {
1300                 return mService.startHomeActivityLocked();
1301             }
1302         }
1303
1304         Slog.d(TAG,"resumeTopActivty");
1305         Slog.d(TAG, "------------liuwei-----------resumeTopActivty");
1306         if(next.packageName.equals("com.tcl.tv") || next.packageName.equals("com.tcl.common.bootsetwizard")){
1307             Slog.d(TAG, "set persist.sys.bootformui false ");
1308             SystemProperties.set("persist.sys.bootfromui","false");
1309         }else{
1310             Slog.d(TAG, "set persist.sys.bootformui true ");
1311             SystemProperties.set("persist.sys.bootfromui","true");
1312         }二,每次在开机启动的时候根据 这个属性来判断是进入launcher 还是 TV,  在ActivityManagerService.java改动的代码如下Slog.d(TAG, "----------liuwei------------startHomeActivityLocked");boolean isStartUi = "true".equals(SystemProperties.get("persist.sys.bootfromui","false"));if(isStartUi)</span>{Slog.d(TAG, "----------zhuxiaolin------------isStartUi is true");Intent intent = new Intent(mTopAction,mTopData != null ? Uri.parse(mTopData) : null);intent.setComponent(mTopComponent);if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {intent.addCategory(Intent.CATEGORY_HOME);}ActivityInfo aInfo =intent.resolveActivityInfo(mContext.getPackageManager(),STOCK_PM_FLAGS);if (aInfo != null) {intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));// Don't do this if the home app is currently being// instrumented.ProcessRecord app = getProcessRecordLocked(aInfo.processName,aInfo.applicationInfo.uid);if (app == null || app.instrumentationClass == null) {intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,null, null, 0, 0, 0, false, false, null);}}}else{Slog.d(TAG, "----------liuwei------------isStartUi is false");Intent mIntent = new Intent();//mIntent.setClassName("com.tcl.cyberui","com.tcl.cyberui.MainActivity");mIntent.setClassName("com.tcl.tv","com.tcl.tv.TVActivity");mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);Slog.d(TAG, "----------zhuxiaolin------------ mContext.startActivity(mIntent)");mContext.startActivity(mIntent);}三 引起的信源不一致问题

开机记忆TV的问题解决了。但是后来测试却发现一个更严重的问题, 有时候开机前TV的信源是DTV, 开机后的信源却是ATV或其他。经过多次测试总结出了规律, 如果第一次关机前是在launcher 状态下, 第二次关机前是tv状态下,就会出现信源就会出现不一致的情况。也就是说只要连续两次关机前的状态不一致(一次是launcher, 一次是TV)就必定会出现这个问题。如果两次关机前都是在luancher下 或都是在TV下那么就不会出现信源不一致的问题。

有了这个规律,那么就大胆猜测是由于luancher启动的时候读取信源的位置和 tv启动读取信源的位置不一致。

关键就在与这个位置不知道保存在哪里, 因为底层代码是厂商的我们看不到,很可能是保存在某个数据库里的。

后来不停的测试,加打印log, 发现不管是launcher先启动,还是TV先启动, 都会调用TVCommonNative.getDefault的getService来获取TVCommonService,

 static public ITVCommon getDefault(Context context) {155         if (mContext == null && context !=null) {156             mContext = context.getApplicationContext();157         }158 159         if (gDefault != null) {160             return gDefault;161         }162        IBinder b = getService(TVCOMMON);                                                                                                        163         if (b == null) {164             b = new TVCommonService();165             TVLog(TVCOMMON166                     + "service is not exit in ServiceManager, try to add it to ServiceManager");167             addService(TVCOMMON, b);</span>168         }

看到没, 第一次肯定都是走的红色代码,因为第一次都是空,先创建TVCommonService,在addService到ServiceManager。

再看看TVCommonService的构造函数:

  88     TVCommonService() {89 90         super();91         tvMgr = TVManager.getInstance(getContext());92         rawChSrv = (ChannelService) tvMgr93                 .getService(ChannelService.ChannelServiceName);94         cfgSrv = (ConfigService)tvMgr95                 .getService(ConfigService.ConfigServiceName);96         inputSrv = (InputService) tvMgr97                 .getService(InputService.InputServiceName);98         brdcstSrv = (BroadcastService) tvMgr99                 .getService(BroadcastService.BrdcstServiceName);100 101         mLooper = Looper.getMainLooper();102         mQueue = Looper.myQueue();103 104         mQueue.addIdleHandler(this);105         handler = new Handler(mLooper, this);106        <span style="color:#CC0000;"> storage = TVStorage.getInstance(getContext());</span>107         configurer = TVConfigurer.getInstance(getContext());

看到了,有个存储的东东叫TVStorage, 而且这个TVStorage是和context相关的!!!!!

也就是说, tv先启动的时候,这个TvStorage的context是tv 的, launcher先启动的时候context是launcher, 则也就导致了tv先启动和 luancher先启动 读取,存放信源的地方是不一致的。

我们来看看TVStorage的代码:

private TVStorage(Context context) {
               pref = context.getSharedPreferences(TVCM_TABLE, Context.MODE_PRIVATE);
               pref = tvContext.getSharedPreferences(TVCM_TABLE, Context.MODE_WORLD_WRITEABLE);
                editor = pref.edit();
        }

36
 37     public String getString(String key, String def) {
 38         return pref.getString(key, def);
 39     }
 40
 41     public void setString(String key, String val) {
 42         editor.putString(key, val);
 43         editor.commit();
 44
 45     }

看到了吗,是放到context 的preference下, 熟悉java上层应用的人都熟悉吧。

我就是不知道preference这个东西,所以卡到context那里 不知道往下怎么跟踪了。 追到这个地方是另外一个同事发现的。

四 。 知道了原因 代码修改如下

private TVStorage(Context context) {
 15         //改为指定用TV的context读写属性,所以要求第一个调用TV控制接口的应用有systemuid
 16         Context tvContext;
 17         try {
 18             tvContext = context.createPackageContext("com.tcl.tv", Context.CONTEXT_IGNORE_SECURITY);
 19         } catch (NameNotFoundException e) {
 20             // TODO Auto-generated catch block
 21             e.printStackTrace();
 22             tvContext = context;                                                                                                                  
 23         }
 24         pref = tvContext.getSharedPreferences(TVCM_TABLE, Context.MODE_WORLD_WRITEABLE);
 25         editor = pref.edit();
 26     }

把context写死到tv context下了,即不管是tv先启动,还是launcher先启动, storage都是读取,存储到tv的preference下了。

五  。其实我对这个该法是有意见的,在TVCommonService里我们可以看到, 不仅仅是TVstorage要用到context, 其他还有地方用到context, 我们只修改了storage的context, 那么其他地方的没有改,有很大的可能会出现问题。如果都修改, 那么对代码的改动太大了, 很可能造成更多的问题。  出现这个问题的本质 是因为TVCommonService是和context相关的, 只要每次开机add service的context不固定, 就会出先问题。 我比较推荐的方法 还是 永远都是launcher先启动,永远都用launcher的context去add TVCommonService, 启动luancher后,由launcher去判断 persist.sys.bootfromui, 由launcher去决定起TV或是不起。 毕竟以前一直都是先起launcher的,而这样也最稳定, 改动也很小。 可惜launcher不是我负责的, 做luancher的不想这么改,暂时修改Storage ,写死用tv的context。在我看来,这种写法实在不好, 除了刚才我提到的原因,底层的东西怎么能写死上层的package name呢?

android tv 信源不一致问题相关推荐

  1. android tv 不显示不出来,android tv 信源不一致问题

    项目中 由于用户投诉, 新增了一个需求, 用户在看tv的时候, 关机重启后 仍然希望是进入tv界面下,而我们现在是不管上次关机是在tv还是launcher下, 重启以后都是进入launcher下. 想 ...

  2. Android TV开发--HDMI播放器

    最近接到一个需求:做一个HDMI播放器的Demo,具体就是做一个Demo,安装在Android TV上,安卓TV接入安卓盒子,信号源是HDMI,打开播放器的Demo可以播放盒子里面的资源.网上这方面的 ...

  3. Android TV框架 TIF(Android TV Input Framework)入门实践

    Tamic/CSDN http://blog.csdn.net/sk719887916/article/details/53645615 做TV开发一段时间了,国内目前关于这方面的资料并不多,这里我来 ...

  4. Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑

    原文:Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必 ...

  5. 针对Android Tv的自定义RecyclerView2 0横竖向连动

    版权声明:本文为博主原创文章,转载请注明出处. 推荐: 欢迎关注我创建的Android TV 简书专题,会定期给大家分享一些AndroidTv相关的内容: www.jianshu.com/c/37ef ...

  6. 【Android TV 开发】焦点处理 ( 父容器与子组件焦点获取关系处理 | 不同电视设备上的兼容问题 | 触摸获取焦点 | 按键获取焦点 )

    Android TV 开发系列文章目录 [Android TV 开发]安卓电视调试 ( 开启网络远程调试 ) [Android TV 开发]焦点处理 ( 父容器与子组件焦点获取关系处理 | 不同电视设 ...

  7. 如何在Android TV上自定义推荐行

    When you fire up Android TV, the first thing you see is a list of movies and shows the system thinks ...

  8. android 设备名称_如何更改您的Android TV的设备名称

    android 设备名称 Android TV is Google's attempt at taking over the living room, and with some units bein ...

  9. Android插u盘自动执行,android tv box ---- 插入u盘直接播放指定文件夹中的视频

    android tv box ---- 插入u盘直接播放指定文件夹中的视频思路: 1.监听u盘插入广播 2.遍历指定目录下的所有文件,找到视频文件 3.将符合条件的文件加入播放集合中 4.循环播放 n ...

最新文章

  1. 请问:这里的空应怎么填呀?
  2. python binary lib on win/各种python库的二进制包
  3. java一个接口执行结束释放内存_java的灵魂--JVM虚拟机
  4. 听说你想去大厂看学妹,带你看看作业帮产品经理岗面经
  5. windbg调试cpu占用率高的进程
  6. VMware License Server使用经验
  7. python 验证码_4行Python代码生成图像验证码
  8. java 压缩gz_如何在Java中将.zip压缩为.gz?
  9. 我真out了,高端人士都这样玩儿?
  10. css3毛玻璃效果白边问题
  11. MapReduce之WordCount案例
  12. 你遇到过最有诗意的句子是什么?
  13. 第三部分:Android 应用程序接口指南---第一节:应用程序组件---第一章1-1.Fragment...
  14. DiskGenius屏蔽硬盘坏道方法
  15. 基于ROS使用Arduino控制水泵
  16. JS·经典·炫彩菜单(动画效果) for jquery
  17. win7系统,打开office出现错误代码0x8007007B的解决办法
  18. ES 7.0.1安装head和sql插件报错处理
  19. CS231n 02 Loss Functions and Optimization
  20. memcpy内存重叠问题

热门文章

  1. Matlab/simulink仿真,直驱永磁风机并网低电压穿越 直驱风力发电系统MATLAB仿真模型
  2. 惯导偏航角误差和GPS动态精度对导航的影响
  3. php dropdownlist,php 下拉列表多级联动dropDownList示例代码
  4. java 抖音开放平台 code token等
  5. c++ 计算某个日期是星期几,判断某年某月一号是星期几
  6. 【FPGA】数码管动态显示之电子时钟
  7. superset 最新版 地图数据展示问题
  8. 奥特曼系列ol光元在哪个服务器,奥特曼系列OL无限光元版
  9. 使用Arduino开发板和颜色传感器TCS230实现颜色感应
  10. RTSP/Onvif协议EasyNVR视频平台Linux版本云端录像下载异常的修复