背景需求:
由于项目做升级切换,旧Android8.1上就有这个需求,但简单看过Android11这部分的逻辑,发现Recent功能流程有不小的变化,于是一边跟着网上的分析一边理源码,详细分析可以参考这篇文章:Android11 最近任务Recents功能分析,看过这部分就可以直接看来到导航实现部分。即下面的SystemUI。
SystemUI:statusbar
经过上面的分析,并通过查阅,可以知道这部分统一由SystemUI实现,具体在MTK平台代码路径如下:
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone
NavigationBar* NavigationBarInflaterView.java NavigationBarView.java NavigationBarFragment.java
另外可以在SystemUI/res/layout下面可以找到home,recent,back这些控件的xml描述,旧的Android版本,可以直接在xml设置systemui:keyRepeat为true来支持长按分发事件,Android11不再有这种方式,但在NavigationBarFragment.java内有针对每个按键提供长按事件进行处理。
解决:
NavigationBarView.java内对layout下各空间实现分发和控制
...
mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
mButtonDispatchers.put(R.id.accessibility_button, accessibilityButton);
mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
...
而NavigationBarFragment.java则在prepareNavigationBarView()内对触摸和长按设置监听
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
recentsButton.setOnClickListener(this::onRecentsClick);
recentsButton.setOnTouchListener(this::onRecentsTouch);
recentsButton.setLongClickable(true);
recentsButton.setOnLongClickListener(this::onLongPressBackRecents);
ButtonDispatcher backButton = mNavigationBarView.getBackButton();
backButton.setLongClickable(true);
ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
homeButton.setOnTouchListener(this::onHomeTouch);//home触摸事件
homeButton.setOnLongClickListener(this::onHomeLongClick);//长按
ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
accessibilityButton.setOnClickListener(this::onAccessibilityClick);
accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
updateAccessibilityServicesState(mAccessibilityManager);
updateScreenPinningGestures();
}
这个长按事件就是onHomeLongClick,接着我们来看:
boolean onHomeLongClick(View v) {
if (!mNavigationBarView.isRecentsButtonVisible()
&& ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
return onLongPressBackHome(v);
}
if (shouldDisableNavbarGestures()) {
return false;
}
mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS);
mUiEventLogger.log(NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS);
Bundle args = new Bundle();
args.putInt(
AssistManager.INVOCATION_TYPE_KEY, AssistManager.INVOCATION_HOME_BUTTON_LONG_PRESS);
mAssistManager.startAssist(args);
mStatusBarLazy.get().awakenDreams();
if (mNavigationBarView != null) {
mNavigationBarView.abortCurrentGesture();
}
return true;
}
通过添加Log,可以发现长按会进入这部分逻辑,且针对recentsButton是否存在有处理,一开始尝试过
修改onLongPressBackHome,但都没有得到想要的效果,这时候突然想起来mCommandQueue所带的方法,在frameworks内PhoneWindowManger内长按物理的home就有相关调用,于是想到在这里结束后加一句:
mAssistManager.startAssist(args);
mStatusBarLazy.get().awakenDreams();
mCommandQueue.toggleRecentApps();//add
if (mNavigationBarView != null) {
mNavigationBarView.abortCurrentGesture();
}
刷机后发现的确能打开多任务窗口,至此该功能实现。
END…