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

项目中 由于用户投诉, 新增了一个需求, 用户在看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)

{

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(TVCOMMON

166 + "service is not exit in ServiceManager, try to add it to ServiceManager");

167 addService(TVCOMMON, b);

168 }

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

再看看TVCommonService的构造函数:

88 TVCommonService() {

89

90 super();

91 tvMgr = TVManager.getInstance(getContext());

92 rawChSrv = (ChannelService) tvMgr

93 .getService(ChannelService.ChannelServiceName);

94 cfgSrv = (ConfigService)tvMgr

95 .getService(ConfigService.ConfigServiceName);

96 inputSrv = (InputService) tvMgr

97 .getService(InputService.InputServiceName);

98 brdcstSrv = (BroadcastService) tvMgr

99 .getService(BroadcastService.BrdcstServiceName);

100

101 mLooper = Looper.getMainLooper();

102 mQueue = Looper.myQueue();

103

104 mQueue.addIdleHandler(this);

105 handler = new Handler(mLooper, this);

106 storage = TVStorage.getInstance(getContext());

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呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值