17

Usually, Android calls onPause on your Activity when it starts being obscured or hidden, followed by onStop when it's no longer shown at all. In my game, I pause the game in onPause, so the user doesn't lose the game while looking elsewhere.

However, when the user drags down the notification bar, it covers my Activity, but neither onPause nor onStop are called. This doesn't seem to be mentioned in the documentation. The game ticks away in the background with nobody looking at it. Is there some other way to tell my Activity has been obscured when this happens, so I can pause the game before the user loses? I can't find anything at all about this on the Android Developers site.

Zain
  • 37,492
  • 7
  • 60
  • 84
Dan Hulme
  • 14,779
  • 3
  • 46
  • 95
  • This may be solved via this [this](https://stackoverflow.com/questions/11520465/android-listener-on-the-status-bar-notification/50662025#50662025) answer – Zain Jun 07 '18 at 03:22
  • @M.Zain Isn't that answer for detecting the user making the notification bar appear after the application hid it? – Dan Hulme Jun 07 '18 at 14:32
  • Check this for a working solution: https://stackoverflow.com/questions/53509108/how-to-detect-when-the-notification-system-bar-is-opened/53509109#53509109 – The Hungry Androider Nov 28 '18 at 15:44

3 Answers3

24

The onWindowFocusChanged(boolean hasFocus) of Activity should serve the required purpose. It is called with false when the notification area is dragged down, and with true once the area is dragged back up. The corresponding Android documentation states that this method "is the best indicator of whether this activity is visible to the user". It also explicitly states that the callback is triggered when the "status bar notification panel" is shown.

It is important to note that this method is also called in other situations. A good example is the display of an AlertDialog. onWindowFocusChanged is even called when the activity itself shows an AlertDialog. This might require consideration, depending on if your game uses AlertDialogs or something else which causes a focus change.

In a scenario similar to the one described in this question, we've used the onWindowFocusChanged method successfully, e.g. on a Nexus 5 with Android 4.4, or a Sony Xperia Tablet with Android 4.1.

Basant Singh
  • 5,736
  • 2
  • 28
  • 49
Stephan Palmer
  • 835
  • 7
  • 18
5

Since the StatusBarManager isn't part of the official API, I find it unlikely that there is a way to detect it. Even using reflection, none of the statusbar-classes seem to have a hook for listeners.

If it is feasible, you could deactivate the statusbar. Otherwise, I think you are out of luck :(

Community
  • 1
  • 1
pgsandstrom
  • 14,361
  • 13
  • 70
  • 104
3

Interacting with the status bar has 2 cases:

  • Case 1: If your activity is already hiding the status bar, and the user pulls down the status bar area without showing the notification: this can be handled by registering OnSystemUiVisibilityChangeListener listener to get notified of system UI visibility changes
    boolean mStatusBarShown;
    View decorView = getWindow().getDecorView();
    decorView.setOnSystemUiVisibilityChangeListener
            (new View.OnSystemUiVisibilityChangeListener() {
                @Override
                public void onSystemUiVisibilityChange(int visibility) {
                    // Note that system bars will only be "visible" if none of the
                    // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
                    if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                        // TODO: The system bars are visible. Make any desired
                        // adjustments to your UI, such as showing the action bar or
                        // other navigational controls.
                        mStatusBarShown = true;

                    } else {
                        // TODO: The system bars are NOT visible. Make any desired
                        // adjustments to your UI, such as hiding the action bar or
                        // other navigational controls.
                        mStatusBarShown = false;

                    }
                }
            });
  • Case 2: If the status bar is already shown to the user, and the user pulls it down to show the notification area; to detect that, you need to override onWindowFocusChanged(boolean hasFocus) in the activity, where hasFocus parameter value will be 'false' in case the user pulls the status bar down, and when the user pushes the status bar up again; then the onWindowFocusChanged will be invoked again but this time hasFocus will be true
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        // handle when the user pull down the notification bar where
        // (hasFocus will ='false') & if the user pushed the
        // notification bar back to the top, then (hasFocus will ='true')
        if (!hasFocus) {
            Log.i("Tag", "Notification bar is pulled down");
        } else {
            Log.i("Tag", "Notification bar is pushed up");
        }
        super.onWindowFocusChanged(hasFocus);
    
    }

Check this link for more info.

Zain
  • 37,492
  • 7
  • 60
  • 84