Невозможно добавить окно android.view.ViewRoot$W@44da9bc0 - разрешение отклонено для этого типа окна - PullRequest
80 голосов
/ 27 сентября 2011

Я предпочитаю эту публикацию, например, но я получил ошибку при добавлении viewgroup в объект 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

Ответы [ 4 ]

153 голосов
/ 27 сентября 2011

Попробуйте использовать это разрешение в AndroidManifest.

android.permission.SYSTEM_ALERT_WINDOW

по API> = 23 см.

136 голосов
/ 03 декабря 2015

" @ ceph3us вы знаете, как этого добиться для> = M? ActivityCompat.requestPermissions (this, new String [] {Manifest.permission.SYSTEM_ALERT_WINDOW} ..."

  1. РАЗРЕШЕНИЕ SYSTEM_ALERT_WINDOW на API> = 23 (рисовать поверх других приложений и т. Д.):

    • больше не отображается на экране разрешений приложения.
    • он даже не появляется на странно запутанном новом экране «Все разрешения»
  2. Вызов Activity.requestPermissions () с этим разрешением,

    • не будет отображать диалоговое окно для пользователя «Разрешить / Запретить».
    • Вместо этого обратный вызов Activity.onRequestPermissionsResult () будет немедленно вызван с флагом отказа.

Решение:

Если приложение предназначено для уровня API 23 или выше, пользователь приложения должен явно предоставить это разрешение приложению через экран управления разрешениями. Приложение запрашивает одобрение пользователя, отправляяi-е действие 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 
       }
    }
}

"И как пользователь может отключить это разрешение?Оно не отображается в разрешениях в настройках-> приложения-> «MyApp» -> разрешения. Кроме того, есть объяснение, почему это разрешение отличается от других тем, как мы его запрашиваем? - Аноним 12 февраляв 21:01 "

Есть несколько разрешений, которые не ведут себя как нормальные и опасные разрешения.SYSTEM_ALERT_WINDOW и WRITE_SETTINGS особенно чувствительны, поэтому большинство приложений не должны их использовать.Если приложению требуется одно из этих разрешений, оно должно объявить разрешение в манифесте и отправить намерение с запросом авторизации пользователя.Система отвечает на намерение, показывая пользователю подробный экран управления.

Специальные разрешения

edit II:

Я использовал этот код в Activity, расширяющей FragmentActivity, и получил исключение java.lang.IllegalArgumentException: можно использовать только младшие 16 битов для requestCode, поскольку используемый код запроса не находится в диапазоне 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 

простой код использования в заданном диапазоне

edit III:

для приложений, нацеленных на API AOSP 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)
3 голосов
/ 10 января 2018

После ceph3us ответа на добавление Alert Dialog, это работало нормально

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, использующую опасные разрешения. Убедитесь, что у вас есть действительное обоснование на тот случай, если это потребуется Google.

0 голосов
/ 24 мая 2016

Вы можете изменить целевой SDK на 22 или меньше, тогда он также работает на API 23.

Измените его в Gradle.Build.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...