Creating a System Overlay Window (Always on Top)

Creating a system overlay window (always on top)

This might be a stupid solution. But it works. If you can improve it, please let me know.

OnCreate of your Service: I have used WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag. This is the only change in service.

@Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}

Now, you will start getting each and every click event. So, you need to rectify in your event handler.

In your ViewGroup touch event

@Override
public boolean onTouchEvent(MotionEvent event) {

// ATTENTION: GET THE X,Y OF EVENT FROM THE PARAMETER
// THEN CHECK IF THAT IS INSIDE YOUR DESIRED AREA


Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}

Also you may need to add this permission to your manifest:

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

How to create an 'Always on top overlay' in Android

Alright. Heres a piece of code which does the job: (You can change the ImageView to any other thing and use it as an overlay.)

startPowerOverlay() function:

@SuppressLint("ClickableViewAccessibility")
private void startPowerOverlay(){
// Starts the button overlay.
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
overlayPowerBtn = new ImageView(this);
overlayPowerBtn.setImageResource(R.drawable.REPLACE_ME);

int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// APPLICATION_OVERLAY FOR ANDROID 26+ AS THE PREVIOUS VERSION RAISES ERRORS
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
// FOR PREVIOUS VERSIONS USE TYPE_PHONE AS THE NEW VERSION IS NOT SUPPORTED
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);

params.gravity = Gravity.TOP | Gravity.START;
params.x = 0;
params.y = 100;
params.height = 110;
params.width = 110;

windowManager.addView(overlayPowerBtn, params);

overlayPowerBtn.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
private long latestPressTime = 0;

@Override public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Save current x/y
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
// Check for double clicks.
if (latestPressTime == 0 || latestPressTime + 500 < System.currentTimeMillis()) {
latestPressTime = System.currentTimeMillis();
} else {
// Doubleclicked. Do any action you'd like
}
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(overlayPowerBtn, params);
return true;
}
return false;
}
});
}

on onCreate():

        // Check for overlay permission. If not enabled, request for it. If enabled, show the overlay
if(Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(context)){
CharSequence text = "Please grant the access to the application.";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.fromParts("package", getPackageName(), null)));
} else {
startPowerOverlay();
}

on onDestroy():

        if (overlayPowerBtn != null)
windowManager.removeView(overlayPowerBtn);

Hope it helps.

Creating System overlay window Like a normal activity

The following code shows how to add an overlay view by WindowManager. Unfortunately, these code doesn't work when it jumps to "Recent Task" Activity.

Add permission to AndroidManifest.xml

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

Then, write these code in Java.

WindowManager windowManager  = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
layoutParams.x = 0;
layoutParams.y = 0;
layoutParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
View window = LayoutInflater.from(this).inflate(R.layout.layout_window, null, false);
window.findViewById(R.id.left).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(FirstActivity.this, "Click Lock", Toast.LENGTH_SHORT).show();
}
});
windowManager.addView(window, layoutParams);

The Demo User Interface shows like this:

Sample Image

Processing, keep window on top/ overlay

If you're using Processing 3 (and you should be), then you should no longer use the frame variable- the other answer doesn't seem to do anything in Processing 3.

Instead, use the surface variable:

void setup(){
size(200, 200);
surface.setAlwaysOnTop(true);
}

void draw(){
background(0);
ellipse(mouseX, mouseY, 10, 10);
}

More info on the changes made in Processing 3 can be found here and here.

NodeWebkit always on top on top of fullscreen applications?

It's possible, but not as easy as you may think.
If you want to overlay games the problem is that the game engine "takes control" over the graphics card and renders ONLY the game.
that means that your application in the background is not rendered at all.

that means you need to "inject" yourself into that process.
you do this by talking to the OpenGL or DirectX directly

you can find more information on it
Here, Here, And Here

Clickable Screen overlay in C#

I think you want something like the window that appears when you right click an icon on the Windows taskbar. This is just a Windows Form without titlebar (here you can read how to hide titlebar: https://stackoverflow.com/a/7483026/14940782).

Then, you can add Opacity or BackColor to the form to make it semi transparent or with some color you want. BackColor allows Transparent, by the way.

how to make overlay window touchable

I finally found an answer.

windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

inflater = LayoutInflater.from(PlayAthkarService.this);

textView = new TextView(PlayAthkarService.this);
textView.setBackgroundResource(R.drawable.floating_window);
textView.setTextSize(20);
textView.setText(athkarString[completed]);
textView.setTextColor(getResources().getColor(R.color.colorPrimaryDark));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
params = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.OPAQUE);
}else {
params = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
, WindowManager.LayoutParams.TYPE_PRIORITY_PHONE,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.OPAQUE);
}

params.gravity = Gravity.TOP | Gravity.RIGHT ;
params.x = 0;
params.y = 50;

windowManager.addView(textView, params);


Related Topics



Leave a reply



Submit