如何在Android中禁用状态栏点击和下拉?

时间:2015-04-30 13:30:14

标签: android

如何禁用Android中的状态栏点击和下拉?我尝试了很多东西,但这不起作用。

3 个答案:

答案 0 :(得分:14)

在我看来,有两种选择:

选项1:您可以在状态栏上方放置一个窗口以禁用任何触摸或拉下。

选项2:您还可以覆盖OnWindowFocusChanged()方法,以便在显示后立即关闭通知面板。

如何:

选项1:在您的活动中定义以下方法(preventStatusBarExpansion)和类(CustomViewGroup)。

public static void preventStatusBarExpansion(Context context) {
    WindowManager manager = ((WindowManager) context.getApplicationContext()
        .getSystemService(Context.WINDOW_SERVICE));

    Activity activity = (Activity)context;
    WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
    localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
    localLayoutParams.gravity = Gravity.TOP;
    localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|

    // this is to enable the notification to recieve touch events
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |

    // Draws over status bar
    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

    localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
    int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
    int result = 0;
    if (resId > 0) {
        result = activity.getResources().getDimensionPixelSize(resId);
    }

    localLayoutParams.height = result;

    localLayoutParams.format = PixelFormat.TRANSPARENT;

    customViewGroup view = new customViewGroup(context);

    manager.addView(view, localLayoutParams);
}

public static class customViewGroup extends ViewGroup {

    public customViewGroup(Context context) {
        super(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v("customViewGroup", "**********Intercepted");
        return true;
    }
}

并在活动的onCreate方法中调用preventStatusBarExpansion方法。完成!

选项2:首先,将以下权限添加到Androidmanifest.xml文件中:

<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />

其次,在您的活动中定义以下类范围变量:

// To keep track of activity's window focus
boolean currentFocus;

// To keep track of activity's foreground/background status
boolean isPaused;

Handler collapseNotificationHandler;

第三,重写onWindowFocusChanged(boolean):

@Override
public void onWindowFocusChanged(boolean hasFocus) {

    currentFocus = hasFocus;

    if (!hasFocus) {

        // Method that handles loss of window focus
        collapseNow();
    }
}

Forth,定义collapseNow();方法:

public void collapseNow() {

    // Initialize 'collapseNotificationHandler'
    if (collapseNotificationHandler == null) {
        collapseNotificationHandler = new Handler();
    }

    // If window focus has been lost && activity is not in a paused state
    // Its a valid check because showing of notification panel
    // steals the focus from current activity's window, but does not 
    // 'pause' the activity
    if (!currentFocus && !isPaused) {

        // Post a Runnable with some delay - currently set to 300 ms
        collapseNotificationHandler.postDelayed(new Runnable() {

            @Override
            public void run() {

                // Use reflection to trigger a method from 'StatusBarManager'                

                Object statusBarService = getSystemService("statusbar");
                Class<?> statusBarManager = null;

                try {
                    statusBarManager = Class.forName("android.app.StatusBarManager");
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

                Method collapseStatusBar = null;

                try {

                    // Prior to API 17, the method to call is 'collapse()'
                    // API 17 onwards, the method to call is `collapsePanels()`

                    if (Build.VERSION.SDK_INT > 16) {
                        collapseStatusBar = statusBarManager .getMethod("collapsePanels");
                    } else {
                        collapseStatusBar = statusBarManager .getMethod("collapse");
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }

                collapseStatusBar.setAccessible(true);

                try {
                    collapseStatusBar.invoke(statusBarService);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

                // Check if the window focus has been returned
                // If it hasn't been returned, post this Runnable again
                // Currently, the delay is 100 ms. You can change this
                // value to suit your needs.
                if (!currentFocus && !isPaused) {
                    collapseNotificationHandler.postDelayed(this, 100L);
                }

            }
        }, 300L);
    }   
}

最后,重写onPause()和onResume方法:

@Override
protected void onPause() {
    super.onPause();

    // Activity's been paused      
    isPaused = true;
}

@Override
protected void onResume() {
    super.onResume();

    // Activity's been resumed
    isPaused = false;
}

完成!

注意:在将应用程序置于kiosk模式时,我使用了第一个选项,该模式根本不显示通知面板。 另一方面,第二个选项效果很好,但它允许通知面板显示一小段时间,用户可以快速单击通知面板顶部的设置图标以退出自助服务终端模式。

希望这会对你有所帮助。 干杯!

答案 1 :(得分:1)

禁用Android StatusBar展开/下拉

大家好,男孩,男孩,我很高兴!度过了很长一段时间后,我又回来了一个美味的答案!

此解决方案不存在!这个解决方案行得通!它由Android提供,如果您要构建系统应用程序,则可以使用此解决方案,对于用户应用程序,抱歉,我不能帮忙,但是请尝试看看是否可行。

是的,我以前使用过此方法(您会在SO上很容易找到):public class BlockStatusBar {和许多其他方法,试图修改AOSP本身,但是更加复杂。

但是您知道BlockStatusBar的工作原理,onWindowFocusChange和其他东西!它使用户将其拉下并具有延迟。现在,如果您引用Android AOSP,您将看到StatusBarManager提供了一个使用FLAG的公共方法public void disable(int what)。我试图反省,但徒劳!

问题出在参数类型和getMethod(String methodName)的使用上,但是失败了,但是当我使用正确的参数规范时,我能够将其删除。

因此,这里是Android AOSP 9.0r34android/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();
        }
    }

...
...
...

所以我在做的是找到正确的方法,然后调用禁用的FLAG。

简而言之,像View.STATUS_BAR_DISABLE_EXPAND之类的东西都应该起作用,但是由于某种原因,即使在Android Studio中我可以看到代码,并且该代码在View类中是公共的,但我无法访问它。但是,我可以使用实际的十六进制值。最后,不用多说,这是解决方案:

但是首先,请查看View.java的标志:

    /**
     * @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;

下一步,实际的解决方案:我使用了两个标志,分别是public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;,您可以在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);

        }
    }

最后,您需要<uses-permission android:name="android.permission.STATUS_BAR" />,否则将需要Throw InvocationTargetExceptionSecurityException

现在,最终的享受,我正在使用我们的家庭应用程序(Launcher),因此,这将永久地应用于整个系统。另外,我在onResume()中调用此方法,因此,如果在运行时修改属性,则可以重新启用StatusBar。请喜欢和分享!

快乐编码!

答案 2 :(得分:0)

我认为我的回答可能会迟到,但我也有类似的要求要禁用 android 中的 statusBar 而不是隐藏。

我已使用设备管理员权限完成此操作。一旦用户授予设备管理员权限。

我们可以在 devicePolicyManager 对象上调用这个特定的 API:-

mDevicePolicyManager.setStatusBarDisabled(mComponentName, true)

我在媒体文章中分享了我的经验:-

https://amitkumar-72131.medium.com/how-to-disable-status-bar-in-android-b6ad2e7dace5