What is WindowManager in android?
Asked Answered
C

3

71

I tried googling it and there is no direct and/or clear cut answer.

The developer website's definition is not clear either:

The interface that apps use to talk to the window manager. Use Context.getSystemService(Context.WINDOW_SERVICE) to get one of these.

Can someone with plain 6th grade English explain what it is?

And how can I use it to create a floating object that remains via several activties, even though I moved from one to the other?

Cartload answered 7/11, 2013 at 20:56 Comment(0)
J
158

The Android WindowManager is a system service, which is responsible for managing the z-ordered list of windows, which windows are visible, and how they are laid out on screen. Among other things, it automatically performs window transitions and animations when opening or closing an app or rotating the screen.

Every activity has a Window that is used to display its content on the screen. When you call setContentView on an activity, it attaches that view to the activity's default window. The default window fills the screen, so that your activity's window hides any other activities -- the WindowManager will display whichever window is on top. So normally you don't need to worry about windows - you just create an activity and Android will do the rest for you.

But you need to interact with the WindowManager if you want to do something unusual like create floating windows that don't fill the screen. If you want to create a floating window that is visible in front of other applications, you can't use an activity because your activity will stop when another app comes to the foreground, and its window will be hidden or destroyed. Instead you need to display a window from a background service. For example:

WindowManager.LayoutParams p = new WindowManager.LayoutParams(
    // Shrink the window to wrap the content rather than filling the screen 
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    // Display it on top of other application windows, but only for the current user
    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
    // Don't let it grab the input focus
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    // Make the underlying application window visible through any transparent parts
    PixelFormat.TRANSLUCENT);

// Define the position of the window within the screen
p.gravity = Gravity.TOP | Gravity.RIGHT;
p.x = 0;
p.y = 100;

WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
windowManager.addView(myView, p);

For this to work, you will need to add the following permission to your AndroidManifest.xml

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Joses answered 16/3, 2014 at 20:40 Comment(2)
@Joses I'm using two windomanager objects, but they seem to conflict with each other. I can't get the ontouch called properly of one of them until I remove the another. Do you know how to solve this?Chalcedony
Is the permission needed for all WindowManager.addView, or just the one that has TYPE_APPLICATION_OVERLAY flag set?Spandex
H
7

For android api version > 23, android.permission.SYSTEM_ALERT_WINDOW need to request runtime. Moreover, TYPE_SYSTEM_ERROR and some few type is deprecated in android api 26. Here is the way

public void showWindowManager() {
    if (requestPermission()) {
        return;
    }

    WindowManager.LayoutParams p =
            new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    Build.VERSION.SDK_INT > Build.VERSION_CODES.O
                            ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
                            : WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                    PixelFormat.TRANSLUCENT);


    final WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater layoutInflater =
            (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
    final View popupView = layoutInflater.inflate(R.layout.window_manager_layout, null);
    windowManager.addView(popupView, p);

    // dismiss windowManager after 3s
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            windowManager.removeView(popupView);
        }
    }, 3000);
}

@TargetApi(Build.VERSION_CODES.M)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
        if (Settings.canDrawOverlays(this)) {
            showWindowManager();
        }
    }
}

public boolean requestPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
            return true;
        }
    }
    return false;
}
Humbert answered 20/10, 2017 at 10:21 Comment(0)
K
2

Window manager organises the screen and processes what should go where and how they should be layered.

Here is a nice open source example of a floating object. Floating Object Example

Killick answered 7/11, 2013 at 21:34 Comment(5)
I want to achieve this only when my app is open (visible to user), is this possible via the above open source ?Cartload
Sure, in the OnPause method of your app just stop the service. Of course in the OnResume start the service again.Killick
I was able to accomplish this. Thanks a lot. The project was straight forward to use. However, is it possible to use a custom layout instead of the ball ? for example, show a text (that is different every time) with an image X ?Cartload
No worries. Not sure about a custom layout, I'm sure it's possible though. You could just set the resource as a TextView instead of an ImageView and work through the code.Killick
It works! But, when I am trying to remove a view from the WindowManager windowManager.removeView(), some flickering occurs duing the removal of the view. How to avoid that ?Allege

© 2022 - 2024 — McMap. All rights reserved.