Android P 拦截虚拟按键事件

    最近有一个奇怪的需求,当储存空间不足时,需要一个提醒框.此提醒框出现时只能点击提供的button才能跳转到释放文件空间的地方.触发其他地方要求无响应(包括虚拟按键).
     此做法有两种,一种是使用悬浮框. 一种是对话框.不管是那种做法,都需要屏蔽虚拟按键的响应.

   一.寻找解决方案.
        (1)使用SDK自带工具hierarchyviewer 查看虚拟按键的布局,发现Back/Home/Recents 三个按钮都使用KeyButtonView. 并查看到对应的view id ,分别是R.id.back/R.id.home/R.id.recent_apps.
        (2)根据(1)所带的线索,在全局代码中搜索发现是对应的代码在SystemUI中.
    二.分析代码逻辑.
         虚拟按键主要事件是点击,长按,以及触摸.
         对应的代码
         SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
            @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
       ...
        prepareNavigationBarView();//初始化预先设置
       ...

}

    private void prepareNavigationBarView() {
      ...
        // recents添加事件
        ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
        recentsButton.setOnClickListener(this::onRecentsClick);
        recentsButton.setOnTouchListener(this::onRecentsTouch);
        recentsButton.setLongClickable(true);
        recentsButton.setOnLongClickListener(this::onLongPressBackRecents);
       // back添加事件
        ButtonDispatcher backButton = mNavigationBarView.getBackButton();
        backButton.setLongClickable(true);
       // home添加事件
        ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
        homeButton.setOnTouchListener(this::onHomeTouch);
        homeButton.setOnLongClickListener(this::onHomeLongClick);
        // accessibility添加事件
        ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
        accessibilityButton.setOnClickListener(this::onAccessibilityClick);
        accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
        updateAccessibilityServicesState(mAccessibilityManager);

        ButtonDispatcher rotateSuggestionButton =      mNavigationBarView.getRotateSuggestionButton();
        rotateSuggestionButton.setOnClickListener(this::onRotateSuggestionClick);
        rotateSuggestionButton.setOnHoverListener(this::onRotateSuggestionHover);
        updateScreenPinningGestures();
    }
    代码中已经显示了对应事件,我们做一些宏开关进行拦截和放过就可以.
 
 三. 修改了NavigationBarFragment.java事件处理,但是,发现home键位和back键,还不能捕捉.
      查看源码,发现KeyButtonView.java重写了onTouchEvent方法,自身对touch事件进行了拦截.
      在KeyButtonView.java中onTouchEvent方法进行宏变量进行拦截,测试OK.

四.总结:

      拦截虚拟按键事件只要在KeyButtonView.java和NavigationBarFragment.java中拦截对应的方法即可.

你可能感兴趣的:(systemui,android)