-
-
Save bjoernQ/6975256 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="de.mobilej.overlay" | |
android:versionCode="1" | |
android:versionName="1.0" > | |
<uses-sdk android:minSdkVersion="14" /> | |
<application android:label="SystemOverlay" > | |
<activity | |
android:name="de.mobilej.overlay.Main" | |
android:exported="true" > | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
</activity> | |
<service | |
android:name="de.mobilej.overlay.OverlayShowingService" | |
android:exported="false" /> | |
</application> | |
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> | |
</manifest> |
package de.mobilej.overlay; | |
import android.app.Activity; | |
import android.content.Intent; | |
import android.os.Bundle; | |
public class Main extends Activity { | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
Intent svc = new Intent(this, OverlayShowingService.class); | |
startService(svc); | |
finish(); | |
} | |
} | |
package de.mobilej.overlay; | |
import android.app.Service; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.graphics.PixelFormat; | |
import android.os.IBinder; | |
import android.view.Gravity; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.view.View.OnClickListener; | |
import android.view.View.OnTouchListener; | |
import android.view.WindowManager; | |
import android.view.WindowManager.LayoutParams; | |
import android.widget.Button; | |
import android.widget.Toast; | |
public class OverlayShowingService extends Service implements OnTouchListener, OnClickListener { | |
private View topLeftView; | |
private Button overlayedButton; | |
private float offsetX; | |
private float offsetY; | |
private int originalXPos; | |
private int originalYPos; | |
private boolean moving; | |
private WindowManager wm; | |
@Override | |
public IBinder onBind(Intent intent) { | |
return null; | |
} | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); | |
overlayedButton = new Button(this); | |
overlayedButton.setText("Overlay button"); | |
overlayedButton.setOnTouchListener(this); | |
overlayedButton.setAlpha(0.0f); | |
overlayedButton.setBackgroundColor(0x55fe4444); | |
overlayedButton.setOnClickListener(this); | |
WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT); | |
params.gravity = Gravity.LEFT | Gravity.TOP; | |
params.x = 0; | |
params.y = 0; | |
wm.addView(overlayedButton, params); | |
topLeftView = new View(this); | |
WindowManager.LayoutParams topLeftParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT); | |
topLeftParams.gravity = Gravity.LEFT | Gravity.TOP; | |
topLeftParams.x = 0; | |
topLeftParams.y = 0; | |
topLeftParams.width = 0; | |
topLeftParams.height = 0; | |
wm.addView(topLeftView, topLeftParams); | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
if (overlayedButton != null) { | |
wm.removeView(overlayedButton); | |
wm.removeView(topLeftView); | |
overlayedButton = null; | |
topLeftView = null; | |
} | |
} | |
@Override | |
public boolean onTouch(View v, MotionEvent event) { | |
if (event.getAction() == MotionEvent.ACTION_DOWN) { | |
float x = event.getRawX(); | |
float y = event.getRawY(); | |
moving = false; | |
int[] location = new int[2]; | |
overlayedButton.getLocationOnScreen(location); | |
originalXPos = location[0]; | |
originalYPos = location[1]; | |
offsetX = originalXPos - x; | |
offsetY = originalYPos - y; | |
} else if (event.getAction() == MotionEvent.ACTION_MOVE) { | |
int[] topLeftLocationOnScreen = new int[2]; | |
topLeftView.getLocationOnScreen(topLeftLocationOnScreen); | |
System.out.println("topLeftY="+topLeftLocationOnScreen[1]); | |
System.out.println("originalY="+originalYPos); | |
float x = event.getRawX(); | |
float y = event.getRawY(); | |
WindowManager.LayoutParams params = (LayoutParams) overlayedButton.getLayoutParams(); | |
int newX = (int) (offsetX + x); | |
int newY = (int) (offsetY + y); | |
if (Math.abs(newX - originalXPos) < 1 && Math.abs(newY - originalYPos) < 1 && !moving) { | |
return false; | |
} | |
params.x = newX - (topLeftLocationOnScreen[0]); | |
params.y = newY - (topLeftLocationOnScreen[1]); | |
wm.updateViewLayout(overlayedButton, params); | |
moving = true; | |
} else if (event.getAction() == MotionEvent.ACTION_UP) { | |
if (moving) { | |
return true; | |
} | |
} | |
return false; | |
} | |
@Override | |
public void onClick(View v) { | |
Toast.makeText(this, "Overlay button click event", Toast.LENGTH_SHORT).show(); | |
} | |
} |
I get an error on line 52 (OverlayShowingService) when I use it, target device 8.1 oreo, but project SDK 15. "FATAL EXCEPTION".
at de.mobilej.overlay.OverlayShowingService.onCreate(OverlayShowingService.java:52)
The line
wm.addView(overlayedButton, params);
Why is that?
[Edit]
Seems like you have to replace both
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
with LAYOUT_FLAG
as elich11 said in order to work.
Thanks everyone
crashes on Pie with permission denied
Thanks.
thanks
I want to make a Overlay (Always on Top over all Apps) in Android 6.0. Your code doesn't work in my android studio.
Could you please help make system?
If you get "permission denied for window type 2003 at", here is my fix.
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
is deprecated from SDK 26.
In OverlayShowingService
, just replace it with WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
.
I get this error
java.lang.RuntimeException: Unable to create service de.mobilej.overlay.OverlayShowingService: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@4929b7e -- permission denied for window type 2003
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3493)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1776)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6753)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@4929b7e -- permission denied for window type 2003
at android.view.ViewRootImpl.setView(ViewRootImpl.java:949)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at de.mobilej.overlay.OverlayShowingService.onCreate(OverlayShowingService.java:52)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3483)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1776)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6753)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Any way to fix this?
For "permission denied for window type 2003
at". Please look at my comment and come back.
Thanks, that solved the first error, though I now get 'permission denied for window type 2038' instead
Ok for 'permission denied for window type 2038' you just need to allow drawing over other apps in settings on phone.
I am trying to use this to create an app to hide rounded screen corners by adding a black bar across top and bottom of screen.
At the moment these black bars appear below the status bar and above the navigation bar, as show in the image
(https://user-images.githubusercontent.com/77055803/104008998-3aeb8f00-51a2-11eb-90e6-43fa2704ce0d.jpg)
Anyone know how to make the overlays position to the absolute top and bottom of screen?
Also the overlay gets rotated with any app that goes to landscape mode, as shown here
(https://user-images.githubusercontent.com/77055803/104009159-7a19e000-51a2-11eb-89d7-7b4ad5d22660.jpg)
How can I make it always appear at the top and bottom edges of the screen, regardless of app rotation?
use this code it will solve your problem
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
wmParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_TOAST);
} else {
wmParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
}
This is an old thread, but here's my thoughts:
The color/alpha settings as-is worked for me on kitkat, but not on lollipop.
So I updated them similar to another commenter.
Changed to
overlayedButton.setBackgroundColor(Color.BLUE);
overlayedButton.setTextColor(Color.WHITE);
overlayedButton.getBackground().setAlpha(Math.round(0.33f*255));
(white on transparent light blue: 33% transparency).
All the topleft stuff didn't make sense to me at all. So I commented out all the topLeft / topLeftView code and it made very little difference.
I changed:
to:
I'd be glad to hear an explanation of the topLeft code. I suspect that if it is doing something, it could be done a lot more efficiently, and doesn't have to be a view object of it's own. (Or please tell me otherwise).