Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type
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 -- permiss开发者_JS百科ion 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
Try using this permission in AndroidManifest.
android.permission.SYSTEM_ALERT_WINDOW
on API >= 23 see
"@ceph3us do you know how to achieve it for >=M? ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}..."
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
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)
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.
You can change your target SDK to 22 or less, then it also works on API 23.
Change it in Gradle.Build.
精彩评论