3

I want to overlay android status bar. In my case it is on top. I do not want to overlay or hide navigation bar.

Note: Solution must work on android 4.2.2+. I prefer answers for non-rooted device.

I have searched many SO questions and answers, but none works on 4.2.2.

Below is my code, but it does not consume touch events. That's why status bar opens its panel. And I do not want this.

@Override 
public void onCreate() {
    super.onCreate();

    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    int statusBarHeight = (int) Math.ceil(25 * getResources().getDisplayMetrics().density);

    overlay = new Button(this);
    overlay.setBackgroundColor(Color.GREEN);
    overlay.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.i("StatusBar", "touched");
            return false;
        }
    });

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.FILL_PARENT,
            statusBarHeight,
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|
            WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH|
            WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
            PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.TOP | Gravity.RIGHT;

    windowManager.addView(overlay, params);

}

@Override
public void onDestroy() {
    super.onDestroy();
    if (overlay != null) windowManager.removeView(overlay);
}

In main activity I start service:

startService(new Intent(this, StatusBarService.class));

And permission is added in AndroidManifest.xml:

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

And now proof it can be done and it works on 4.2.2: Play Google - MobiLock

How?

Screenshots: enter image description here enter image description here

Solata
  • 1,444
  • 3
  • 28
  • 42
  • Kindly provide some screenshots/pictures of what you want to achieve – Jimmar Sep 15 '14 at 12:44
  • @JiMMaR: The best way to visualize it, is if you install&run MobiLock launcher. Keep an eye on their custom status bar. It stays the same even when you run one of allowed apps in launcher. – Solata Sep 15 '14 at 13:02
  • @JiMMaR screenshots added – Solata Sep 18 '14 at 09:51

3 Answers3

6

After try&repeat, this did it for me:

int statusBarHeight = (int) Math.ceil(25 * getResources().getDisplayMetrics().density);

WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.FILL_PARENT,
            statusBarHeight,
            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|
            WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
            PixelFormat.TRANSLUCENT);

It works on 4.2.2 and 4.4.2

Solata
  • 1,444
  • 3
  • 28
  • 42
  • Hi @Solata, I don't have personal anything against you. Thanks for clarification. I will vote up your answer as well. The answer has good explanation as well. Generally Stackoverflow contains a lot of users just to make a profiles like that. Regarding my reputation, I don't care. I am not here to have good reputation, and I generally don't read only the posts by users who has 40K or more. There are a lot of people who has a lot of knowledge and gives good answers, but doesn't have good reputation here. – X-HuMan Dec 01 '14 at 10:32
  • @AzatMartirosyan: I like that you care about this, but your approach is not ok. Stackoverflow has very good QA rating process to avoid this kind of non constructive commenting .. – Solata Dec 01 '14 at 13:26
  • What value should I use at statusBarHeight? – Machado Apr 28 '15 at 14:20
2

We could not prevent the status appearing in full screen mode in kitkat devices, so made a hack which still suits the requirement ie block the status bar from expanding.

For that to work, the app was not made full screen. We put a overlay over status bar and consumed all input events. It prevented the status from expanding.

note:

  • customViewGroup is custom class which extends any layout(frame,relative layout etc) and consumes touch event.
  • to consume touch event override the onInterceptTouchEvent method of the view group and return true

Updated

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

customViewGroup implementation Code :

WindowManager manager = ((WindowManager) getApplicationContext()
            .getSystemService(Context.WINDOW_SERVICE));

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;
    localLayoutParams.height = (int) (50 * getResources()
            .getDisplayMetrics().scaledDensity);
    localLayoutParams.format = PixelFormat.TRANSPARENT;

    customViewGroup view = new customViewGroup(this);

    manager.addView(view, localLayoutParams);

Note not rooting required

Abhimaan
  • 1,893
  • 2
  • 19
  • 26
0

Can't you put your app in a notitlebar theme [shouldn't remove the navigation bar] and implement your own view on top that mimics the notification bar look as a container and the rest of the contents would be fragments ?

Jimmar
  • 4,194
  • 2
  • 28
  • 43
  • This works when main form of launcher is on top. But if another application is started, status bar shows again. I managed to hide status bar with StatusBarService.class. But touch events are forwarded to status bar in background. So user can swipe down status panel. – Solata Sep 15 '14 at 13:44