Android: permission denied for window type 2038 using TYPE_APPLICATION_OVERLAY
Asked Answered
I

6

24

I trying to create a view that is above other applications:

WindowManager.LayoutParams paramsDirectorView = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT);

I have looked in other responses and found the following things for "drawing over applications":

  • I have android.permission.SYSTEM_ALERT_WINDOW in the manifest
  • I am doing the Settings.canDrawOverlays(this) check which comes back true.
  • I have done everything located here permission denied for window type

I am still getting "-- permission denied for window type 2038" error. As of now I am using TYPE_PHONE and it works, but it is deprecated and says to use TYPE_APPLICATION_OVERLAY. Can some one follow up on this as the TYPE_PHONE answer is not truly a resolution but a "patch work" solution that is deprecated in Android O.

I am running on Android 7.1.2

android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@1f47e89 -- permission denied for window type 2038 at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3344) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@1f47e89 -- permission denied for window type 2038 at android.view.ViewRootImpl.setView(ViewRootImpl.java:703) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93) at HeadService.TwoViewManager.(TwoViewManager.java:99) at HeadService.UIHeadService.onStartCommand(UIHeadService.java:65) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3327) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

Impresa answered 14/9, 2017 at 0:55 Comment(4)
Just curious did you find an actual solution for TYPE_APPLICATION_OVERLAY? From what I understand, none of the answers below actually solve the issue. All of them were suggesting using another TYPE.Parlin
It's as the accepted answer describes you have to take into account before and after Oreo ie you will be using two types.Impresa
It can happen if user disable "Allow display over other apps"Violinist
@Impresa any other cause rather than permission and your accepted answer.Rugged
G
48

I had the exactly same issue. I guess you should differentiate the target (before and after Oreo)

int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
        LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}

params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        LAYOUT_FLAG,
        WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT);
Germander answered 3/11, 2017 at 18:53 Comment(8)
I was going to write the solution myself eventually but you nailed it!Impresa
If i use this, i cant interact with the overlayed layout,is there anyother wayMinny
TYPE_PHONE it's worked. But i can't gets install button when install .apk files. Any solutions?Siana
Life Saver solution thanks!!. After spending two days finally my App is working.Microreader
@Impresa @Microreader I am using same code structure still having crash in Fabric any relation with ` lock screen notification`.any help will be acceptedRugged
I am following same answer but still having crash in fabricRugged
hello this solution working for me in many apps but in my current app there is video recording in background but after this widow manager line app is not crash but my app is going hang and video recording also done in background properly. what is the issue?Hoch
@Rugged did you find any solution? I have the same issue. I am also following the same but still have crash log into firebase crashlyticsSomato
S
14
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

I had the exactly same issue in service class(before and after Marshmallow).

if (Build.VERSION.SDK_INT >= 23) {
    if (!Settings.canDrawOverlays(this)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
          Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, 1234);
    }
} else {
    startService(new Intent(SplashActivity.this,                     
    CheckServicesForApps.class));
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1234) {
            startService(new Intent(SplashActivity.this, 
            CheckServicesForApps.class));

    }
}

public class CheckServicesForApps extends Service {
    private Context context = null;

    @Override
    public void onCreate() {
        super.onCreate();

        ImageView imageView = new ImageView(context);
        imageView.setVisibility(View.GONE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            try {
                windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);

                //here is all the science of params
                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
                );

                windowManager.addView(imageView, params);
                hand=new Handler();

            } catch (Exception e) {
                hand=new Handler();
                e.printStackTrace();
            }
        }else{
            windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

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

            params.gravity = Gravity.TOP | Gravity.CENTER;
            params.x = ((getApplicationContext().getResources().getDisplayMetrics().widthPixels) / 2);
            params.y = ((getApplicationContext().getResources().getDisplayMetrics().heightPixels) / 2);
            windowManager.addView(imageView, params);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        /* We want this service to continue running until it is explicitly
        * stopped, so return sticky.
        */
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (imageView != null) {
            try {
                windowManager.removeView(imageView);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        /**** added to fix the bug of view not attached to window manager ****/
    }
}
Soper answered 11/12, 2017 at 9:17 Comment(1)
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />Soper
T
7

Did you request runtime permission by calling following intent?

private void requestOverlayPermission() {
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
        return;
    }

    Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
    myIntent.setData(Uri.parse("package:" + getPackageName()));
    startActivityForResult(myIntent, APP_PERMISSIONS);
}

Then in onActivityResult() check if Settings.canDrawOverlays(this) is true otherwise request permission again by calling above method.

Tater answered 24/9, 2017 at 12:39 Comment(1)
Fixed my issue, Thanks!Quintessa
E
1

Source SYSTEM_ALERT_WINDOW String SYSTEM_ALERT_WINDOW Allows an app to create windows using the type TYPE_APPLICATION_OVERLAY, shown on top of all other apps. Very few apps should use this permission; these windows are intended for system-level interaction with the user.

Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user's approval by sending an intent with action ACTION_MANAGE_OVERLAY_PERMISSION. The app can check whether it has this authorization by calling Settings.canDrawOverlays().

Enounce answered 30/9, 2017 at 19:52 Comment(0)
P
1
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
        layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    }else {
        layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
    }
Peaceable answered 22/11, 2019 at 7:8 Comment(0)
G
0

Try to change WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY to WindowManager.LayoutParams.TYPE_PHONE?

Gametangium answered 14/9, 2017 at 2:12 Comment(1)
Thanks for the reply! However, as I said in the post, I am already using this as a workaround but this TYPE_PHONE is deprecated in Android O and I want this to eventually work with Android O.Impresa

© 2022 - 2024 — McMap. All rights reserved.