Android 소스(6.0 및 8.1) 차단 상태 막대 드롭다운 및 차단 탐색 막대 표시

34079 단어
전에 6.0의 내비게이션 표시줄 차단 분석 과정을 한 번 썼는데 안드로이드6.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는 실행할 수 없습니다. 코드는 간단해 보이지만, 사실은 슈퍼입니다.onTouch Event (이벤트) 는 Panel Bar를 호출합니다.java의 onTouchEvent ()
8.1 해결 방법(동상)
6.0과 8.1의 상태바 코드는 차이가 있지만 위의 방법을 통해 모두 수요 효과에 도달할 수 있다
6.0의 PhoneStatusBarView는 onTouchEvent () 를 호출하고, 최종적으로PanelBar의 onTouchEvent () 를 호출한다.
8.1의 Phone Status BarView는 onTouch Event () 를 호출하고 Panel Bar의 onTouch Event () 를 호출하며, 최종적으로Panel View의 onTouch Event () 를 호출한다.
근본적으로 사건의 전달을 막아서 차단하고 내리는 효과에 도달하다
보태다
동적 제어가 필요하면 상태 표시줄을 내릴 수 있는지 여부를 방송하고 전달하는 파라미터를 받아들여 영구적으로 저장할 수 있다(Shared Preference 또는 Settings.Global.xxx) 현재 상태 표시줄의 상태는 일반적으로 Settings를 사용하는 것을 권장한다.Global 저장
구체적 절차
4
  • frameworks\base\core\java\android\provider\Settings.java에서 Globel 내부 클래스에 변수 이름을 추가합니다. 예를 들어 OPENPANEL_ENABLED

  • 4
  • makeupdate-api 명령을 통해 다시 컴파일합니다.Settings에서 수정한 후에 컴파일해야 이 두 파일에 대응할 수 있기 때문에frameworks/base/api/system-current.txt、frameworks/base/api/current.txt

  • 4
  • 라디오에서 수신하는 곳에서Settings를 통과한다.Global.putInt(context.getContentResolver(), Settings.Global.OPEN_PANEL_ENABLED, 1) 값 저장(ps는 adb 명령adb shell settings put global open panel enabled 1을 통해 adb shell settings get global open panel enabled 시뮬레이션으로 쓰기 가능)
  • 4
  • 방금 리턴 false를 4
  • 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의 내비게이션 표시줄은 윈도 관리자의ddView를 통해 추가되고, 윈도 관리자의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();
                }
            }
        };
    

    좋은 웹페이지 즐겨찾기