在ATV SDK中,TV APP也是一个比较重要的apk,他负责显示各种输入源,比如HDMI IN输入,AV IN输入,因为要显示不同的源,具体硬件平台又步一样,所以一定会涉及到相关定义。每一个不同的芯片,其TV APK都需要定制。本系列文章基于amlogic ATV SDK,分析amlogic 平台上是如何实现显示切换的。
一、概述
代码位置:packages\apps\TV
参考Android TV系列 TV APP分析(一),显示输入源一般需要一个TvInputManager 类,一个
TvView 类负责显示,下面看看TV APP 中一些文件的具体作用
tv\MainActivity.java --主Activity
tv\util\TvInputManagerHelper.java--TvInputManager管理类
ui\AppLayerTvView.java-TvView的子类
ui\TunableTvView.java-AppLayerTvView的子类
TV的layout主要的控件就是TunableTvView,下面是activity_tv.xml的布局
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@android:color/transparent"
android:keepScreenOn="true">
<com.android.tv.ui.TunableTvView android:id="@+id/main_tunable_tv_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start|center_vertical" />
<FrameLayout
android:id="@+id/scene_container"
android:layout_height="match_parent"
android:layout_width="match_parent" />
<include layout="@layout/menu" />
<include layout="@layout/option_container" />
<include layout="@layout/program_guide" />
<FrameLayout android:id="@+id/fragment_container"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</FrameLayout>
因为是基于Amlogic 平台分析,amlogic 还增加的部分平台部分内容,这部分的核心类
QuickKeyInfo.java。
二、TV app 启动
TV app 在 AndroidManifest.xml定义一个隐式的action,android.media.tv.action.SETUP_INPUTS
<activity
android:name="com.android.tv.MainActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|smallestScreenSize|screenLayout|orientation"
android:launchMode="singleTask"
android:resizeableActivity="true"
android:screenOrientation="landscape"
android:supportsPictureInPicture="true"
android:theme="@style/Theme.TV.MainActivity" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/channel" />
<data android:mimeType="vnd.android.cursor.dir/channel" />
<data android:mimeType="vnd.android.cursor.item/program" />
<data android:mimeType="vnd.android.cursor.dir/program" />
</intent-filter>
<intent-filter>
<action android:name="android.media.tv.action.SETUP_INPUTS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
TV APP的启动通发送上述隐式的action启动,这个隐式的action为:TvInputManager.ACTION_SETUP_INPUTS:(ction,android.media.tv.action.SETUP_INPUTS)
例如希望TV显示HDMI IN1 源信号,需要如下启动
Intent mIntent = new Intent(TvInputManager.ACTION_SETUP_INPUTS);
//下面的都是amlogic自定义的
//amlogic会根据下面实现tune
mIntent.putExtra("from_tv_source", true);
mIntent.putExtra(TvInputInfo.EXTRA_INPUT_ID, "com.droidlogic.tvinput/.services.Hdmi1InputService/HW5");
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
上述代码最终会调用TV的MainActivity.java,并进入OnCreate。OnCreate的关键作用就是要调用TvView的tune函数,实现显示源的切换。
三、OnCreate
OnCreate关键是创建了TvInputManagerHelper,TvView,amlogic 定制类QuickKeyInfo
@Override
protected void onCreate(Bundle savedInstanceState) {
//TvInputManager管理类
mTvInputManagerHelper = tvApplication.getTvInputManagerHelper();
//TvView显示类
mTvView = (TunableTvView) findViewById(R.id.main_tunable_tv_view);
mTvView.initialize(mProgramDataManager, mTvInputManagerHelper);
//amlogic的定制类
mQuickKeyInfo = new QuickKeyInfo(MainActivity.this, mTvInputManagerHelper, mChannelTuner);
mQuickKeyInfo.registerCommandReceiver();
mTvViewUiManager.restoreDisplayMode(false);
//进一步处理Intent内容
if (!handleIntent(getIntent())) {
finish();
return;
}
handleIntent处理启动时传递的信息,这个信息主要时tune信息,handleIntent是原生函数,再该函数内,amlogic进行了拦截处理
// It should be called before onResume.
private boolean handleIntent(Intent intent) {
// Reset the closed caption settings when the activity is 1)created or 2) restarted.
// And do not reset while TvView is playing.
if (!mTvView.isPlaying()) {
mCaptionSettings = new CaptionSettings(this);
}
mShouldTuneToTunerChannel = intent.getBooleanExtra(Utils.EXTRA_KEY_FROM_LAUNCHER, false);
mInitChannelUri = null;
String extraAction = intent.getStringExtra(Utils.EXTRA_KEY_ACTION);
if (!TextUtils.isEmpty(extraAction)) {
if (DEBUG) Log.d(TAG, "Got an extra action: " + extraAction);
if (Utils.EXTRA_ACTION_SHOW_TV_INPUT.equals(extraAction)) {
String lastWatchedChannelUri = Utils.getLastWatchedChannelUri(this);
if (lastWatchedChannelUri != null) {
mInitChannelUri = Uri.parse(lastWatchedChannelUri);
}
mShowSelectInputView = true;
}
}
if (TvInputManager.ACTION_SETUP_INPUTS.equals(intent.getAction())) {
//当action为ACTION_SETUP_INPUTS时,由mQuickKeyInfo来处理
if (mQuickKeyInfo.handleUiCommand(intent)) {
return true;
}