I'm trying to make a System Overlay window,which will appear over lockscreen too. I did manage to do so on version-6.0 but It's not working on version-7.0 AND 8.0. At first run,I was transferred to Overlay setting for my app (as expected from Android M & onwards) and I allowed it.But Now it's keep getting crashed as i tried to launch service from app. I tried all things which is related to this issue but nothing helps me to resolve it yet.I'm getting this error every time I tried to launch the service:-
FATAL EXCEPTION: main
Process: com.example.sumuix.lockdown, PID: 5128
java.lang.RuntimeException: Unable to create service com.example.sumuix.lockdown.MyService:android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@61b864 -- permission denied for window type 2010
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3414)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1683)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6540)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@61b864 -- permission denied for window type 2010
at android.view.ViewRootImpl.setView(ViewRootImpl.java:788)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:92)
at com.example.sumuix.lockdown.MyService.onCreate(MyService.java:64)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3404)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1683)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6540)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Here is my code:-(MyService.java)
@Override
public void onCreate() {
super.onCreate();
HeadView = LayoutInflater.from(this).inflate(R.layout.overlay_head,null);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.addView(HeadView, params); //I’m getting error here...(MyService.java:64)from error log
ImageView closeButton = (ImageView) HeadView.findViewById(R.id.close_btn);
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopSelf();
}
});
final ImageView chatHeadImage = (ImageView) HeadView.findViewById(R.id.head);
chatHeadImage.setOnTouchListener(new View.OnTouchListener() {
//Code for OnTouch.
}
});
}
My MainActivity , Where I'm calling the above service:- (MyActivity.java)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
back=(Button) findViewById(R.id.jump);
final Intent intentService=new Intent(MainActivity.this, MyService.class);
if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(MainActivity.this)) {
//If the draw over permission is not available open the settings screen
//to grant the permission.
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent,1234);
}else {
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(intentService);
finish();
}
});
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1234) {
//Check if the permission is granted or not.
if (Build.VERSION.SDK_INT >= 23 && Settings.canDrawOverlays(MainActivity.this)) {
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(new Intent(MainActivity.this, MyService.class));
finish();
}
});
} else { //Permission is not available
Toast.makeText(this,
"Draw over other app permission not available. Closing the application",
Toast.LENGTH_SHORT).show();
finish();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
In manifeast :-
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
MyService Layout XML:-
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/chat_head_root"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:background="@android:color/black"
android:orientation="vertical">
<ImageView
android:id="@+id/head"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="8dp"
android:background="@android:drawable/ic_menu_info_details"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/close_btn"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginLeft="40dp"
android:background="@android:drawable/ic_menu_close_clear_cancel"
tools:ignore="ContentDescription" />
</RelativeLayout>
I tried pretty much every thing that I find while searching on internet.I just started with Android so,if I'm doing any minor blunder then please let me know it.Thanks in advance.
For android 8.0, you MUST use WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
. The error overlay, phone overlay and similar are not working anymore.
See more here: https://developer.android.com/about/versions/oreo/android-8.0-changes.html#o-apps
Don't know why you have issues on android 7 though, never had them myself...
Sidenote
Don't use startService
anymore if your service is a foreground service, use startForegroundService
or the ContextCompat
version of it if your service is a foreground service to avoid possible issues if you want to start your overlay service after boot or anywhere else from the background...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With