How to disable status bar click and pull down in Android?

前端 未结 2 1062
礼貌的吻别
礼貌的吻别 2020-11-30 06:27

How can I disable a status bar click and pull down in Android? I have tried many things but this is not working.

2条回答
  •  难免孤独
    2020-11-30 06:53

    Disable Android StatusBar expand/pull-down

    Hello, all, boy oh boy, I'm glad! After spending quite a long time, I am back with a delicious answer once again!

    This solution is NOT out there! And this solution works! It is provided by Android and if you are building a System App, you can use this solution, for User Apps, sorry, I cannot help, but try and see if it works.

    And Yeah I used this before (You'll easily find on SO): public class BlockStatusBar { and lots of others, tried to modify AOSP itself, but was more complicated.

    But you know how BlockStatusBar works, what with the onWindowFocusChange and stuff! It lets the user pull it down and has delay. Now if you refer Android AOSP, you'll see that there is a public method public void disable(int what) provided by StatusBarManager which takes FLAGs. I tried to reflect it, but was in vain!

    The problem was the parameter type and getMethod(String methodName) usage, which failed, but instead when I used the correct parameter specification, I was able to pull it off.

    So here's a reference of Android AOSP 9.0r34 source android/frameworks/base/core/java/android/app/StatusBarManager.java

    ...
    ...
    ...
    public class StatusBarManager {
    
        public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;
        public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS;
        public static final int DISABLE_NOTIFICATION_ALERTS
                = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS;
        @Deprecated
        public static final int DISABLE_NOTIFICATION_TICKER
                = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
        public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO;
        public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME;
        public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;
        public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK;
        public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK;
        public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH;
    
        @Deprecated
        public static final int DISABLE_NAVIGATION = 
                View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT;
    
        public static final int DISABLE_NONE = 0x00000000;
    
        public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS
                | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER
                | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK
                | DISABLE_SEARCH;
    
    ...
    ...
    ...
    
        /**
         * Disable some features in the status bar.  Pass the bitwise-or of the DISABLE_* flags.
         * To re-enable everything, pass {@link #DISABLE_NONE}.
         */
        public void disable(int what) {
            try {
                final IStatusBarService svc = getService();
                if (svc != null) {
                    svc.disable(what, mToken, mContext.getPackageName());
                }
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    
    ...
    ...
    ...
    
    

    So what I am doing is getting the right method, and then invoking the disable FLAGs on it.

    Simply speaking anything like View.STATUS_BAR_DISABLE_EXPAND should have worked, but for some reason, even though in Android Studio I can see the code, and it is public inside View class, I cannot access it. However, I was able to use the actual HEX values. So finally, without much ado, Here's the solution:

    But first, review the View.java's FLAGS:

        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to make the status bar not expandable.  Unless you also
         * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
         */
        public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to hide notification icons and scrolling ticker text.
         */
        public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to disable incoming notification alerts.  This will not block
         * icons, but it will block sound, vibrating and other visual or aural notifications.
         */
        public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to hide only the scrolling ticker.  Note that
         * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
         * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
         */
        public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to hide the center system info area.
         */
        public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to hide only the home button.  Don't use this
         * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
         */
        public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to hide only the back button. Don't use this
         * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
         */
        public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to hide only the clock.  You might use this if your activity has
         * its own clock making the status bar's clock redundant.
         */
        public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to hide only the recent apps button. Don't use this
         * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
         */
        public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to disable the global search gesture. Don't use this
         * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
         */
        public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to specify that the status bar is displayed in transient mode.
         */
        public static final int STATUS_BAR_TRANSIENT = 0x04000000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to specify that the navigation bar is displayed in transient mode.
         */
        public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to specify that the hidden status bar would like to be shown.
         */
        public static final int STATUS_BAR_UNHIDE = 0x10000000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to specify that the hidden navigation bar would like to be shown.
         */
        public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to specify that the status bar is displayed in translucent mode.
         */
        public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
    
        /**
         * @hide
         *
         * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
         * out of the public fields to keep the undefined bits out of the developer's way.
         *
         * Flag to specify that the navigation bar is displayed in translucent mode.
         */
        public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
    
        /**
         * @hide
         *
         * Makes navigation bar transparent (but not the status bar).
         */
        public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
    
        /**
         * @hide
         *
         * Makes status bar transparent (but not the navigation bar).
         */
        public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
    

    NEXT, the actual solution: I used two flags, namely, public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND; & public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;, whose HEX you can find in View.java

        public static void disableStatusBar(Context context) {
            Log.d(Home.class.getCanonicalName(), "disableStatusBar: ");
            // Read from property or pass it in function, whatever works for you!
            boolean disable = SystemProperties.getBoolean(context, "supercool.status.bar.disable", true);
            Object statusBarService = context.getSystemService("statusbar");
    
            Class statusBarManager = null;
            try {
                statusBarManager = Class.forName("android.app.StatusBarManager");
                try {
                    final Method disable_statusBarFeatures = statusBarManager.getMethod("disable", int.class);
                    try {
                        disable_statusBarFeatures.setAccessible(true);
                        if (disable) {
                            disable_statusBarFeatures.invoke(statusBarService, 0x00010000 | 0x00040000);
                        } else {
                            disable_statusBarFeatures.invoke(statusBarService, 0x00000000);
                        }
                    } catch (Exception e) {
                        Log.e(Home.class.getCanonicalName(), "disableStatusBar: " + e.getMessage(), e);
                    }
    
                } catch (Exception e) {
                    Log.e(Home.class.getCanonicalName(), "disableStatusBar: " + e.getMessage(), e);
    
                }
            } catch (Exception e) {
                Log.e(Home.class.getCanonicalName(), "disableStatusBar: " + e.getMessage(), e);
    
            }
        }
    

    Lastly, you'll need , or else, it will Throw InvocationTargetException & SecurityException

    Now, the ultimate treat, I am using our Home App (Launcher) so, this is applied across the system, once and for all. Plus, I call this method in onResume() so, if I modify the property at runtime, I can Re-Enable the StatusBar back. Please like & share!

    Happy Coding!

提交回复
热议问题