Reputation: 3535
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 it works in android 29 (correct way)
https://i.imgur.com/JjMugfG.mp4
am i doing anything wrong
Upvotes: 1
Views: 984
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
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
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