Rafael Lima
Rafael Lima

Reputation: 3535

Create an overlay window in android 19

I'm trying to create an overlay window in android (a which will float over any other app in the screen, even when my app is on background)

I followed several guides (some from SO) and here is the important code

this.sp = PreferenceManager.getDefaultSharedPreferences(context);
        this.wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

         
        this.main = (FrameLayout) LayoutInflater.from(c).inflate(R.layout.ui_floating_window, null);
        

        int type = WindowManager.LayoutParams.TYPE_TOAST;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
            type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

        Point p = new Point();
        wm.getDefaultDisplay().getSize(p);
        this.displayHeight = p.y;
        this.displayWidth = p.x;
        this.rationWH = this.displayWidth / (float) this.displayHeight;
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                sp.getInt(Constants.DefaultSharedPreferences.FLOATING_WINDOW_WIDTH, this.displayWidth / 2),
                sp.getInt(Constants.DefaultSharedPreferences.FLOATING_WINDOW_HEIGHT, this.displayHeight / 2),
                sp.getInt(Constants.DefaultSharedPreferences.FLOATING_WINDOW_X, this.displayWidth / 2),
                sp.getInt(Constants.DefaultSharedPreferences.FLOATING_WINDOW_Y, this.displayHeight / 2),
                type,
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.START | Gravity.TOP;
        params.horizontalMargin = 0;
        params.verticalMargin = 0;

        this.wm.addView(main, params);

i've tested on android 29 and works really fine
but on android 19 the window opens but as soon as the current app goes background the window goes either. i would like the window stayed on even after user switches the app.

This is how i get 19 asdasd

this is how it works in android 29 (correct way)
https://i.imgur.com/JjMugfG.mp4

am i doing anything wrong

Upvotes: 1

Views: 984

Answers (3)

Václav Hodek
Václav Hodek

Reputation: 668

For 7 years, I work on Floating Apps (https://floatingapps.net) which is basically a set of floating mini-apps, so I know something about it :-).

I first get it working on Android 2.3.5 and progress until today.

It's a complex problem if you want to do it right across all possible devices and Android versions.

I recently published a series of articles on this topic. Check it out: https://localazy.com/blog/floating-windows-on-android-1-jetpack-compose-and-room

It goes from the main app, background service, permissions, floating windows, moving them, keyboard input to the list of tips, trick and shortcomings I learned along the way.

It should learn you how to do it right.

Upvotes: 1

aminography
aminography

Reputation: 22832

The problem is that the WindowManager instance from Activity is different than the instance retrieved from the application-level Context.

Let's try a test:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Context context = this; // context of the activity

    WindowManager wm1 = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    WindowManager wm2 = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

    System.out.println("Are equal? " + wm1.equals(wm2));
}

The result is FALSE.

Actually, a WindowManager is responsible for managing a list of windows on the screen. In the case of Activities, when the Activity gets disappeared, all of the related windows such as your added floating view would be gone. While your app lives in the background after pressing the home button, for instance, its window manager (Application's window manager) keeps all of the managed windows. It means that your floating view has the chance of being shown until the app would be killed by the system.

So, by retrieving WindowManager instance from application-level Context and adding the view to it, the problem will be solved.

Upvotes: 2

Furkan Yurdakul
Furkan Yurdakul

Reputation: 3167

The window manager you are getting from an activity points out to Activity.getWindow() when adding a view, which naturally disappears if you click the back button or home button. That means you need another decor view to resolve your problem, which is calling the application context in your case, where it will let you manage the phone's window, as you want.

Check application context, and if it's not null, get the WindowManager instance, then try adding your view.

Also I'm not sure but using WindowManager.TYPE_SYSTEM_ALERT also might help.

Upvotes: -1

Related Questions