源码修改之遥控器快捷通道添加
获取遥控快捷通道按键的keycode
logcat下遥控器按键值和源码keycode值,对应如下:
public static final int KEYCODE_PROG_RED = 183; public static final int KEYCODE_PROG_GREEN = 184; public static final int KEYCODE_PROG_YELLOW = 185; public static final int KEYCODE_PROG_BLUE = 186;
需求如下:
KEYCODE_PROG_RED AV[1,2] KEYCODE_PROG_GREEN HDMI[1,2,3] KEYCODE_PROG_YELLOW DTV KEYCODE_PROG_BLUE ATV
查找电视通道切换代码位置及方式
设备切换到电视界面,不断地切换通道,记录当前activity情况(dumpsys activity)
得到信息归纳集中如下:
所有电视通道下的主界面activity均为RootActivity.java
路径如下::device/mstar/common/apps/MTvPlayer/src/com/mstar/tv/tvplayer/ui/RootActivity.java
各通道信息代码使用int值表示,具体信息如下:
INPUT_SOURCE_ATV = 1; INPUT_SOURCE_CVBS = 2; INPUT_SOURCE_CVBS2 = 3; INPUT_SOURCE_HDMI = 23; INPUT_SOURCE_HDMI2 = 24; INPUT_SOURCE_HDMI3 = 25; INPUT_SOURCE_DTV = 28;
切换电视通道后,直接启动电视的apk软件,即可进入相应的通道
//初始化intent Intent shortcutIntent = new Intent(); shortcutIntent.setComponent(new ComponentName("com.mstar.tv.tvplayer.ui", "com.mstar.tv.tvplayer.ui.RootActivity")); // 此处设置电视通道即可 // ... shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(shortcutIntent);
获取及设置电视通道
// 获取通道信息 int currentTvInputSource = TvCommonManager.getInstance().getCurrentTvInputSource(); // 设置通道信息 TvCommonManager.getInstance().setInputSource(1);
- 添加代码
我们知道系统按键的分发过程中肯定会走PhoneWindowManager中的interceptKeyBeforeDispatching方法,如果按键没有下层处理,这里会收到两次事件,我们这里添加我们的遥控按键处理流程
// new code by allies begin else if (keyCode == KeyEvent.KEYCODE_PROG_RED || keyCode == KeyEvent.KEYCODE_PROG_GREEN || keyCode == KeyEvent.KEYCODE_PROG_YELLOW || keyCode == KeyEvent.KEYCODE_PROG_BLUE) { if (down) { launchShortcut(keyCode); // do interceptKeyEvent return -1; } } // new code by allies end // new code by allies begin private static int av = 2; private static int hdmi = 23; private static int mAntennaType = 0; private void launchShortcut(int keycode) { final int currentTvInputSource = TvCommonManager.getInstance().getCurrentTvInputSource(); final boolean withinTV = getTopActivity(); if (TvCommonManager.getInstance().getCurrentTvSystem() == TvCommonManager.TV_SYSTEM_ISDB) { mAntennaType = (keycode == 185 ? 2 : 1); } Intent shortcutIntent1 = new Intent("com.mstar.android.intent.action.START_TV_PLAYER"); shortcutIntent1.putExtra("inputAntennaType", mAntennaType); shortcutIntent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); shortcutIntent1.addFlags(8192); Intent shortcutIntent2 = new Intent("mstar.tvsetting.ui.intent.action.RootActivity"); switch (keycode) { case KeyEvent.KEYCODE_PROG_RED: //keycode(183) AV[CVBS1-8] inputsource(2-9) if (withinTV && currentTvInputSource == 2 || currentTvInputSource ==3) { av++; if (av >= 4) { av = 2; } } TvCommonManager.getInstance().setInputSource(av); shortcutIntent1.putExtra("inputSrc", av); break; case KeyEvent.KEYCODE_PROG_GREEN: //(184) HDMI(23) HDMI1(24) HDMI2(25) HDMI3(26) if (withinTV && currentTvInputSource == 23 || currentTvInputSource == 24 || currentTvInputSource == 25) { hdmi++; if (hdmi >= 26) { hdmi = 23; } } TvCommonManager.getInstance().setInputSource(hdmi); shortcutIntent1.putExtra("inputSrc", hdmi); break; case KeyEvent.KEYCODE_PROG_YELLOW: //(185) ATV(1) inputAntennaType 2 if (withinTV && currentTvInputSource == 1) { return; } TvCommonManager.getInstance().setInputSource(1); shortcutIntent1.putExtra("inputSrc", 1); break; case KeyEvent.KEYCODE_PROG_BLUE: //(186) DTV(28) inputAntennaType 1 if (withinTV && currentTvInputSource == 28) { return; } TvCommonManager.getInstance().setInputSource(28); shortcutIntent1.putExtra("inputSrc", 28); break; } mContext.startActivity(shortcutIntent1); if (withinTV) { shortcutIntent2.putExtra("task_tag", "input_source_changed"); }else{ shortcutIntent2.putExtra("no_change_source", true); } shortcutIntent2.putExtra("inputAntennaType", mAntennaType); mContext.startActivity(shortcutIntent2); } // new code by allies end
为了提高用户体验,例如在hdmi通道下,连续点按HDMI快捷键,是在各个HDMI通道下进行切换,如果当前界面不是在电视apk下,用户点击HDMI快捷键,直接进入上次的通道(HDMI通道不做切换)
处于tv应用内,且当前通道位于HDMI下,HDMI通道自动切换 if (withinTV && currentTvInputSource == 2 || currentTvInputSource ==3){ // ... }
实现这个功能,需要获取当前resume的activity进行判断,无奈在安卓6.0中相应获取正在运行的api已经不能正常使用,这里测试一下通过如下代码可以获取到最近的进程名
private boolean getTopActivity() { ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = manager.getRunningAppProcesses(); Iterator<ActivityManager.RunningAppProcessInfo> iterator = runningAppProcesses.iterator(); //get top-activity ActivityManager.RunningAppProcessInfo processInfo = iterator.next(); String processName = processInfo.processName; //within tv-apk if (processName.equals("com.mstar.tv.tvplayer.ui") || // processName.equals("com.jrm.localmm") || processName.equals("com.mstar.tvsetting")) { return true; }else { return false; } }
经测试发现,在PhoneWindowManager下调用可以准确获取运行的进程名
编译生成测试
mm -B 编译当前代码路径
cd .. 后 cproj 跳到当前文件mk路径 mm -B 编译当前文件
同步步骤2,编译发现生成service.jar,替换系统中相应文件测试即可