无法添加窗口android.view.ViewRoot$W@44da9bc0 - 此窗口类型的权限被拒绝

Pra*_*tik 82 android overlay

我比较喜欢这篇文章但是我在将viewgroup添加到windowmanager对象时遇到了错误,我已经使用相同的服务类来发布到问题而没有任何变化,我可能会误认为我没有得到它

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params); // here
Run Code Online (Sandbox Code Playgroud)

当我向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>
Run Code Online (Sandbox Code Playgroud)

错误

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
Run Code Online (Sandbox Code Playgroud)

Lal*_*ani 154

请尝试使用此权限 AndroidManifest.

android.permission.SYSTEM_ALERT_WINDOW
Run Code Online (Sandbox Code Playgroud)

在API> = 23见


cep*_*3us 139

" @ ceph3us你知道如何为> = M实现它吗?ActivityCompat.requestPermissions(这个,新的String [] {Manifest.permission.SYSTEM_ALERT_WINDOW} ......"

  1. API上的SYSTEM_ALERT_WINDOW PERMISSION> = 23(借助其他应用程序等):

    • 不再出现在App的权限屏幕中.
    • 它甚至没有出现在奇怪混乱的新"所有权限"屏幕中
  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 
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

"用户如何禁用此权限?它不会显示在设置 - >应用程序 - >"MyApp" - >权限的权限中.另外...有关此权限与其他权限不同的任何解释我们要求它的方式? - 匿名2月12日21:01"

有一些权限不像正常和危险的权限.SYSTEM_ALERT_WINDOW和WRITE_SETTINGS特别敏感,因此大多数应用程序不应使用它们.如果应用程序需要其中一个权限,则必须在清单中声明权限,并发送请求用户授权的意图.系统通过向用户显示详细的管理屏幕来响应意图.

特别许可

编辑二:

我在Activity扩展FragmentActivity中使用了这段代码,我得到了异常java.lang.IllegalArgumentException:对于requestCode只能使用低16位,因为使用的请求代码不在0 .. 65535的范围内.您可以考虑将请求代码更改为适当的价值. - mtsahakis

因为它是:

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

这是因为:

  • java中的整数由32位表示
  • 您可以使用低16位的requestCode
  • 其他位用于请求处理

例如:

integer value:  5463             ///hi 16 bits //   |    // lo 16 bits //
as binary string will look like: 0000 0000 0000 0000 0001 0101 0101 0111 
Run Code Online (Sandbox Code Playgroud)

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

编辑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)
Run Code Online (Sandbox Code Playgroud)

  • 用户如何禁用此权限?它没有显示在settings-> apps - >"MyApp" - >权限的权限中.还有...为什么这个权限与我们要求的方式不同的任何解释? (2认同)