Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type
Asked Answered
C

4

82

I have prefer this post for example but I got the error at adding viewgroup into the windowmanager object, I have used the same class for the Service as posted into the question with no change where I can mistake I didn't gettting it

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params); // here

when I add view to the WindowManger

here is my manifest file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.searce.testoverlay"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name="TestOverlayActivity"
                      android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        <service android:enabled="true" android:name=".HUD"></service>
    </application>
</manifest>

error

09-27 18:49:23.561: ERROR/AndroidRuntime(653): Uncaught handler: thread main exiting due to uncaught exception
09-27 18:49:23.571: ERROR/AndroidRuntime(653): java.lang.RuntimeException: Unable to create service com.searce.testoverlay.HUD: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2790)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.access$3200(ActivityThread.java:119)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1917)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.os.Looper.loop(Looper.java:123)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.main(ActivityThread.java:4363)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at java.lang.reflect.Method.invokeNative(Native Method)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at java.lang.reflect.Method.invoke(Method.java:521)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at dalvik.system.NativeStart.main(Native Method)
09-27 18:49:23.571: ERROR/AndroidRuntime(653): Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.view.ViewRoot.setView(ViewRoot.java:492)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at com.searce.testoverlay.HUD.onCreate(HUD.java:41)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2780)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     ... 10 more
Carlson answered 27/9, 2011 at 13:27 Comment(0)
M
154

Try using this permission in AndroidManifest.

android.permission.SYSTEM_ALERT_WINDOW

on API >= 23 see

Multiparous answered 27/9, 2011 at 13:36 Comment(3)
@ceph3us do you know how to achieve it for >=M? ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}, Perm.PERMISSIONS_REQUEST_SYSTEM_ALERT_WINDOW); Will not fire anything. Same with: ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}, Perm.PERMISSIONS_REQUEST_SYSTEM_ALERT_WINDOW);Afore
Additionally you may need to give permission explicitly, either programmatically or manually from settings on your phone. I was using Huawei Nexus 6p and in settings for my application I clicked "Yes" on drawing on other applications on the screen section.Anh
see this for a good solution: github.com/facebook/react-native/issues/…Past
T
147

"@ceph3us do you know how to achieve it for >=M? ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}..."

  1. SYSTEM_ALERT_WINDOW PERMISSION on API >= 23 (Draw over other apps etc):

    • no longer appears in App's Permissions screen.
    • it doesn't even appear in the strangely confusing new "All permissions" screen
  2. Calling Activity.requestPermissions() with this permission,

    • will not show any dialog for the user to Allow/Deny.
    • instead, the Activity.onRequestPermissionsResult() callback will be called immediately with a denied flag.

Solution:

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()

example code:

/** code to post/handler request for permission */
public final static int REQUEST_CODE = -1010101; *(see edit II)*

public void checkDrawOverlayPermission() {
    /** check if we already  have permission to draw over other apps */
    if (!Settings.canDrawOverlays(Context)) {
        /** if not construct intent to request permission */
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + getPackageName()));
        /** request permission via start activity for result */
        startActivityForResult(intent, REQUEST_CODE);
    }
}

@Override 
protected void onActivityResult(int requestCode, int resultCode,  Intent data) {
    /** check if received result code 
        is equal our requested code for draw permission  */
    if (requestCode == REQUEST_CODE) {
       / ** if so check once again if we have permission */
       if (Settings.canDrawOverlays(this)) {
           // continue here - permission was granted 
       }
    }
}

"And how can the user disable this permission ? It doesn't show in the permissions in settings->apps->"MyApp"->permissions. Also...any explanation as to why this permission is different from the others in the way we request for it? – Anonymous Feb 12 at 21:01"

There are a couple of permissions that don't behave like normal and dangerous permissions. SYSTEM_ALERT_WINDOW and WRITE_SETTINGS are particularly sensitive, so most apps should not use them. If an app needs one of these permissions, it must declare the permission in the manifest, and send an intent requesting the user's authorization. The system responds to the intent by showing a detailed management screen to the user.

Special Permissions

edit II:

I used this code in an Activity extending FragmentActivity and I got Exception java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode because request code used is not in the range of 0.. 65535. You might consider changing your request code to an appropriate value. – mtsahakis

as it sais:

request code must be in the range of 0.. 65535.

this is becaus:

  • integer in java is represented by 32 bits
  • you are allowed to use lower 16 bits for requestCode
  • other bits are used in request processing

so for example:

integer value:  5463             ///hi 16 bits //   |    // lo 16 bits //
as binary string will look like: 0000 0000 0000 0000 0001 0101 0101 0111 

simple use code in given range

edit III:

for apps targeting AOSP API 26 (android oreo / 8+ )

Apps that use the SYSTEM_ALERT_WINDOW permission can no longer use the following window types to display alert windows above other apps and system windows:

TYPE_PHONE TYPE_PRIORITY_PHONE TYPE_SYSTEM_ALERT TYPE_SYSTEM_OVERLAY TYPE_SYSTEM_ERROR

Instead, apps must use a new window type called TYPE_APPLICATION_OVERLAY.

TYPE_APPLICATION_OVERLAY

Window type: Application overlay windows are displayed above all activity windows (types between FIRST_APPLICATION_WINDOW and LAST_APPLICATION_WINDOW) but below critical system windows like the status bar or IME.

The system may change the position, size, or visibility of these windows at anytime to reduce visual clutter to the user and also manage resources.

Requires SYSTEM_ALERT_WINDOW permission.

The system will adjust the importance of processes with this window type to reduce the chance of the low-memory-killer killing them. In multi-user systems shows only on the owning user’s screen.

WindowManager.LayoutParams wLp = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
      ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
      : WindowManager.LayoutParams.TYPE_PHONE;

Window.setAttributes(WindowManager.LayoutParams)
Theressa answered 3/12, 2015 at 8:53 Comment(11)
And how can the user disable this permission ? It doesn't show in the permissions in settings->apps->"MyApp"->permissions. Also...any explanation as to why this permission is different from the others in the way we request for it?Ranunculus
I used this code in an Activity extending FragmentActivity and I got Exception java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode because request code used is not in the range of 0.. 65535. You might consider changing your request code to an appropriate value.Smolensk
Use this request code ....... public final static int REQUEST_CODE = 5463&0xffffff00;Arndt
@MuhammadAdil what is the purpose of bitwise here ? u change the value to 5376Theressa
@Theressa here we get this error if we use that REQUEST_CODE..... java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode........ So I though it should be fixed.Arndt
@MuhammadAdil try something like "public final static int REQUEST_CODE = 9999;"Whiffet
This should be the only answer here. But here is the update that works for API > 25 @TargetApi(Build.VERSION_CODES.M) public void checkDrawOverlayPermission() { if (!Settings.canDrawOverlays(this.getApplicationContext())) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, REQUEST_CODE); } }Spectacled
In my case negative request code didn't work, so onActivityResult was never called. Changing request code to some positive value, solves the problem.Equalitarian
All solutions are no longer working for sdk versions >=27Sari
this one did the trick <3 -> WindowManager.LayoutParams wLp = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE;Ruberta
@RishavSingla doub le check you use a WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY flag maybe you put > instead >= or < instead <= in reverse ?Theressa
P
3

Following ceph3us answer to add an Alert Dialog, this worked fine

final AlertDialog dialog = dialogBuilder.create();
                final Window dialogWindow = dialog.getWindow();
                final WindowManager.LayoutParams dialogWindowAttributes = dialogWindow.getAttributes();

                // Set fixed width (280dp) and WRAP_CONTENT height
                final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
                lp.copyFrom(dialogWindowAttributes);
                lp.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 280, getResources().getDisplayMetrics());
                lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
                dialogWindow.setAttributes(lp);

                // Set to TYPE_SYSTEM_ALERT so that the Service can display it
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    dialogWindow.setType(WindowManager.LayoutParams.TYPE_TOAST);
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    dialogWindow.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
                }
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
                {
                    dialogWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                }
                dialog.show();

But using TYPE_SYSTEM_ALERT might trigger Google takedown policy of apps using dangerous permissions. Make sure you have a valid justification in case google requires it.

Palingenesis answered 10/1, 2018 at 6:6 Comment(1)
Not using the TYPE_APPLICATION_OVERLAY but some other type (TYPE_PHONE in my case) for phones with Android 7.1.1 or lower helped me to get rid of this pesky BadTokenException in my case. See #32224952Lipocaic
A
-8

You can change your target SDK to 22 or less, then it also works on API 23.

Change it in Gradle.Build.

Ayrshire answered 24/5, 2016 at 13:23 Comment(2)
@Hulk It's not the best solution maybe, but it's good to point it out.Levee
This will not fix the issue, it's a quick workaround you can use but you can never target api>23Abruzzi

© 2022 - 2024 — McMap. All rights reserved.