【问题标题】:Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type无法添加窗口 android.view.ViewRoot$W@44da9bc0 -- 此窗口类型的权限被拒绝
【发布时间】:2011-09-27 13:27:16
【问题描述】:

例如,我更喜欢 this 帖子,但在将视图组添加到 windowmanager 对象时出现错误,我使用了与发布到问题中的服务相同的类,没有任何更改,我可能会误认为我没有明白了

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

当我向 WindowManger 添加视图时

这是我的清单文件

<?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>

错误

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

【问题讨论】:

    标签: android overlay


    【解决方案1】:

    尝试在AndroidManifest.中使用此权限

    android.permission.SYSTEM_ALERT_WINDOW
    

    on API >= 23 see

    【讨论】:

    • @ceph3us 你知道如何实现 >=M 吗? ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}, Perm.PERMISSIONS_REQUEST_SYSTEM_ALERT_WINDOW);不会发射任何东西。同:ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}, Perm.PERMISSIONS_REQUEST_SYSTEM_ALERT_WINDOW);
    • 此外,您可能需要以编程方式或通过手机设置手动明确授予权限。我使用的是华为 Nexus 6p,在我的应用程序设置中,我在屏幕部分的其他应用程序上绘图时单击了“是”。
    • 查看这个以获得好的解决方案:github.com/facebook/react-native/issues/…
    【解决方案2】:

    @ceph3us 你知道如何实现 >=M 吗?ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}...”

    1. SYSTEM_ALERT_WINDOW PERMISSION on API >= 23(在其他应用程序等上绘制):

      • 不再出现在应用程序的权限屏幕中。
      • 它甚至没有出现在令人困惑的新“所有权限”屏幕中
    2. 使用此权限调用 Activity.requestPermissions(),

      • 不会为用户显示允许/拒绝的任何对话框。
      • 相反,Activity.onRequestPermissionsResult() 回调将被立即调用并带有拒绝标志。

    解决方案:

    如果应用以 API 级别 23 或更高级别为目标,应用用户必须 通过权限显式将此权限授予应用程序 管理画面。应用通过发送一条请求用户的批准 意图采取行动 ACTION_MANAGE_OVERLAY_PERMISSION。该应用程序可以检查 通过调用是否有此权限 Settings.canDrawOverlays()

    示例代码:

    /** 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 
           }
        }
    }
    

    “用户如何禁用此权限?它不会显示在 settings->apps->“MyApp”->permissions 中的权限中。另外...关于为什么此权限的任何解释我们要求的方式与其他人不同?- 匿名 2 月 12 日 21:01"

    有一些权限的行为与正常情况不同,并且 危险的权限。 SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS 是 特别敏感,因此大多数应用程序不应使用它们。如果一个应用 需要这些权限之一,它必须在 manifest,并发送一个请求用户授权的意图。这 系统通过显示详细的管理屏幕来响应意图 给用户。

    Special Permissions

    编辑二:

    我在扩展 FragmentActivity 的 Activity 中使用了此代码,但出现异常 java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode,因为使用的请求代码不在 0.. 65535 的范围内。您可能考虑将您的请求代码更改为适当的值。 – mtsahakis

    正如它所说:

    请求代码必须在0..65535的范围内。

    这是因为:

    • java中的整数用32位表示
    • requestCode 允许使用低 16 位
    • 其他位用于请求处理

    例如:

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

    给定范围内的简单使用代码

    编辑 III:

    适用于面向 AOSP API 26 (android oreo / 8+) 的应用

    使用 SYSTEM_ALERT_WINDOW 权限的应用程序不能再使用以下窗口类型在其他应用程序和系统窗口上方显示警报窗口:

    TYPE_PHONE TYPE_PRIORITY_PHONE TYPE_SYSTEM_ALERT TYPE_SYSTEM_OVERLAY TYPE_SYSTEM_ERROR

    相反,应用必须使用一种称为 TYPE_APPLICATION_OVERLAY 的新窗口类型。

    TYPE_APPLICATION_OVERLAY

    窗口类型:应用程序覆盖窗口显示在所有活动窗口上方(类型介于 FIRST_APPLICATION_WINDOW 和 LAST_APPLICATION_WINDOW 之间),但在状态栏或 IME 等关键系统窗口下方。

    系统可以随时更改这些窗口的位置、大小或可见性,以减少用户的视觉混乱并管理资源。

    需要 SYSTEM_ALERT_WINDOW 权限。

    系统将调整具有此窗口类型的进程的重要性,以减少低内存杀手杀死它们的机会。 在多用户系统中,仅在拥有用户的屏幕上显示。

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

    【讨论】:

    • 用户如何禁用此权限?它没有显示在设置->应用程序->“我的应用程序”->权限中的权限中。另外...关于为什么此权限在我们请求的方式上与其他权限不同的任何解释?
    • 我在扩展 FragmentActivity 的 Activity 中使用了此代码,但出现异常 java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode,因为使用的请求代码不在 0.. 65535 的范围内。您可以考虑将请求代码更改为适当的值.
    • 使用这个请求代码....... public final static int REQUEST_CODE = 5463&0xffffff00;
    • @MuhammadAdil 这里按位的目的是什么? u 将值更改为 5376
    • @ceph3us 如果我们使用 REQUEST_CODE 会出现此错误..... java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode .... 所以我虽然它应该是固定的。
    【解决方案3】:

    按照ceph3us 回答添加警报对话框,效果很好

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

    但使用 TYPE_SYSTEM_ALERT 可能会触发 Google 移除使用危险权限的应用的政策。确保你有一个有效的理由,以防谷歌需要它。

    【讨论】:

    • 不使用 TYPE_APPLICATION_OVERLAY 而是使用其他类型(在我的情况下为 TYPE_PHONE)用于 Android 7.1.1 或更低版本的手机帮助我摆脱了这个讨厌的 BadTokenException。见stackoverflow.com/questions/32224452/…
    【解决方案4】:

    您可以将目标 SDK 更改为 22 或更低,然后它也适用于 API 23。

    在 Gradle.Build 中更改它。

    【讨论】:

    • @Hulk 这可能不是最好的解决方案,但指出这一点很好。
    • 这不会解决问题,这是一个快速的解决方法,您可以使用,但您永远不能定位 api>23
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    • 2019-02-03
    • 2018-02-22
    • 2023-02-09
    相关资源
    最近更新 更多