Android源码(6.0和8.1) 屏蔽状态栏下拉和屏蔽导航栏显示

简介: Android源码(6.0和8.1) 屏蔽状态栏下拉和屏蔽导航栏显示

之前写过一遍6.0的导航栏屏蔽分析过程,可参考Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP)/动态显示和隐藏NavigationBar


屏蔽状态栏下拉


6.0解决办法


源码位置 SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBarView.java


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean barConsumedEvent = mBar.interceptTouchEvent(event);
        if (DEBUG_GESTURES) {
            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
                EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH,
                        event.getActionMasked(), (int) event.getX(), (int) event.getY(),
                        barConsumedEvent ? 1 : 0);
            }
        }
        // return barConsumedEvent || super.onTouchEvent(event);
    return false;
    }

直接返回false,action_move不会执行,代码看似简单,实则super.onTouchEvent(event)调用的是PanelBar.java中的onTouchEvent()


8.1解决办法(同上)


6.0和8.1的状态栏代码是有差异的,但是通过上面的方法都能达到需求效果


6.0的PhoneStatusBarView调用onTouchEvent(),最终调用PanelBar的onTouchEvent()


8.1的PhoneStatusBarView调用onTouchEvent(),接着调用PanelBar的onTouchEvent(),最终调用PanelView的onTouchEvent()


从根本上阻止事件的传递来达到屏蔽下拉的效果


补充


如果需要动态的控制是否允许下拉状态栏,可以通过广播通知,接受传递的参数,持久化保存(可通过SharedPreference或者Settings.Global.xxxx)当前状态栏的状态,一般建议采用Settings.Global保存。


具体步骤


  1. 在frameworks\base\core\java\android\provider\Settings.java中Globel内部类下添加变量名称,比如OPEN_PANEL_ENABLED
  2. 通过make update-api指令重新编译,因为在Settings中修改后需要编译才能对应到这两文件frameworks/base/api/system-current.txt、frameworks/base/api/current.txt
  3. 在广播接收的地方通过Settings.Global.putInt(context.getContentResolver(), Settings.Global.OPEN_PANEL_ENABLED, 1) 保存值
  4. (ps 可通过adb命令 adb shell settings put global open_panel_enabled 1 模拟写入 adb shell settings get global open_panel_enabled 模拟查看)
  5. 将刚刚的return false改成
boolean flag=Settings.Global.getInt(getContext().getContentResolver(), Settings.Global.OPEN_PANEL_ENABLED,1)==1;
return flag ? barConsumedEvent || super.onTouchEvent(event) : flag;


屏蔽导航栏显示

6.0解决办法

源码位置SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBar.java

    @Override
    public void start() {
        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        updateDisplaySize();
        mScrimSrcModeEnabled = mContext.getResources().getBoolean(
                R.bool.config_status_bar_scrim_behind_use_src);
        super.start(); // calls createAndAddWindows()
        mMediaSessionManager
                = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
        // TODO: use MediaSessionManager.SessionListener to hook us up to future updates
        // in session state
         addNavigationBar();
     .....
    }


直接注释addNavigationBar()就能达到需求效果

8.1解决办法

源码位置SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java

    protected void makeStatusBarView() {
        final Context context = mContext;
        updateDisplaySize(); // populates mDisplayMetrics
        updateResources();
        updateTheme();
        ....
        try {
            boolean showNav = mWindowManagerService.hasNavigationBar();
            if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
            if (showNav) {
                createNavigationBar();
            }
        } catch (RemoteException ex) {
            // no window manager? good luck with that
        }
        ....
    }


直接注释createNavigationBar()或者将showNav=false就能达到需求效果


代码流程分析


6.0和8.1的导航栏都是通过WindowManager的addView来添加的,通过WindowManager的removeViewImmediate来移除


1、6.0的addNavigationBar实现,通过addView将mNavigationBarView添加,prepareNavigationBarView方法设置了点击、触摸、长按事件,无需关心

  private void addNavigationBar() {
        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
        if (mNavigationBarView == null) return;
        prepareNavigationBarView();
        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
        mNavigationShown=true;
    }


查找到在makeStatusBarView()中,mNavigationBarView初始化,加载navigation_bar布局文件

     protected PhoneStatusBarView makeStatusBarView() {
        final Context context = mContext;
        Resources res = context.getResources();
        updateDisplaySize(); // populates mDisplayMetrics
        updateResources();
    ...
    mNavigationBarView = (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
        mNavigationBarView.setDisabledFlags(mDisabled1);
        mNavigationBarView.setBar(this);
        mNavigationBarView.setOnVerticalChangedListener(
                new NavigationBarView.OnVerticalChangedListener() {
            @Override
            public void onVerticalChanged(boolean isVertical) {
                if (mAssistManager != null) {
                    mAssistManager.onConfigurationChanged();
                }
                mNotificationPanel.setQsScrimEnabled(!isVertical);
            }
        });
        mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                checkUserAutohide(v, event);
                return false;
            }});
  }


2、8.1的createNavigationBar实现,发现是通过NavigationBarFragment来实例化mNavigationBarView

    protected void createNavigationBar() {
        mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> {
            mNavigationBar = (NavigationBarFragment) fragment;
            if (mLightBarController != null) {
                mNavigationBar.setLightBarController(mLightBarController);
            }
            mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility);
        });
    }


NavigationBarFragment的crate方法通过addView将mNavigationBarView添加,加载navigation_bar_window布局

    public static View create(Context context, FragmentListener listener) {
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
                PixelFormat.TRANSLUCENT);
        lp.token = new Binder();
        lp.setTitle("NavigationBar");
        lp.windowAnimations = 0;
        View navigationBarView = LayoutInflater.from(context).inflate(
                R.layout.navigation_bar_window, null);
        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
        if (navigationBarView == null) return null;
        context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
        FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
        NavigationBarFragment fragment = new NavigationBarFragment();
        fragmentHost.getFragmentManager().beginTransaction()
                .replace(R.id.navigation_bar_frame, fragment, TAG)
                .commit();
        fragmentHost.addTagListener(TAG, listener);
        return navigationBarView;
    }


补充

依旧是通过广播来动态控制导航栏的显示和隐藏

6.0已在开头文章中写过,这里就只补充8.1的显示和隐藏

源码位置SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java

    private static final String SHOW_NAVIGATION = "cc.intent.systemui.shownavigation";
    private static final String HIDE_NAVIGATION = "cc.intent.systemui.hidenavigation";
   private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e(TAG, "onReceive: " + intent);
            String action = intent.getAction();
            if (HIDE_NAVIGATION.equals(action)) {
                if (mNavigationBarView == null) return;
                mWindowManager.removeViewImmediate(mNavigationBarView);
                mNavigationBarView = null;
            }else if (SHOW_NAVIGATION.equals(action)) {
                if (mNavigationBarView != null) return;
                createNavigationBar();
            }
        }
    };


目录
相关文章
|
5月前
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
278 2
|
6月前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
8月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
466 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
Ubuntu 开发工具 Android开发
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
本文介绍了在基于Ubuntu 22.04的环境下配置Python 3.9、安装repo工具、下载和同步AOSP源码包以及处理repo同步错误的详细步骤。
1002 0
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
489 1
|
Android开发 Docker 容器
docker中编译android aosp源码,出现Build sandboxing disabled due to nsjail error
在使用Docker编译Android AOSP源码时,如果遇到"Build sandboxing disabled due to nsjail error"的错误,可以通过在docker run命令中添加`--privileged`参数来解决权限不足的问题。
2240 1
|
开发工具 uml git
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
本文分享了下载AOSP源码的方法,包括如何使用repo工具和处理常见的repo sync错误,以及配置Python环境以确保顺利同步特定版本的AOSP代码。
1978 0
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
976 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
|
Android开发
我的Android 进阶修炼(1): AOSP源码根目录结构
本文介绍了AOSP源码的根目录结构,提供了基于MTK9269 Android 9.0源码的目录说明,帮助读者了解AOSP源码的组织方式和各目录的功能。
850 0
我的Android 进阶修炼(1): AOSP源码根目录结构
|
开发工具 Android开发 git
全志H713 Android 11 :给AOSP源码,新增一个Product
本文介绍了在全志H713 Android 11平台上新增名为myboard的产品的步骤,包括创建新的device目录、编辑配置文件、新增内核配置、记录差异列表以及编译kernel和Android系统的详细过程。
945 0

热门文章

最新文章

  • 1
    Android实战经验之Kotlin中快速实现MVI架构
    344
  • 2
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    211
  • 3
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    553
  • 4
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    854
  • 5
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    313
  • 6
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    230
  • 7
    Android历史版本与APK文件结构
    739
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    245
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    259
  • 10
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    491