web-dev-qa-db-de.com

Fenster kann nicht hinzugefügt werden [email protected] - Berechtigung für diesen Fenstertyp verweigert

Ich habe es zum Beispiel vorgezogen, this zu posten, aber ich habe den Fehler beim Hinzufügen von viewgroup zum windowmanager-Objekt erhalten. Ich habe die gleiche Klasse für den Dienst verwendet, die in der Frage angegeben wurde, ohne zu ändern, wo ich Fehler machen kann, die ich nicht gemacht habe nicht bekommen

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

wenn ich Ansicht zum WindowManger hinzufüge

hier ist meine Manifest-Datei

<?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 [email protected] -- 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 [email protected] -- 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
81
Pratik

Versuchen Sie, diese Berechtigung in AndroidManifest. Zu verwenden.

Android.permission.SYSTEM_ALERT_WINDOW

auf API> = 23 siehe

154
Lalit Poptani

" @ ceph3us wissen Sie, wie Sie es für> = M erreichen? ActivityCompat.requestPermissions (dies ist der neue String [] {Manifest.permission.SYSTEM_ALERT_WINDOW} ..."

  1. SYSTEM_ALERT_WINDOW PERMISSION auf API> = 23 (Über andere Apps usw. ziehen):

    • wird nicht mehr im Bildschirm "Berechtigungen" der App angezeigt.
    • es erscheint nicht einmal auf dem seltsam verwirrenden neuen Bildschirm "Alle Berechtigungen"
  2. Aufruf von Activity.requestPermissions () mit dieser Berechtigung,

    • zeigt dem Benutzer kein Dialogfeld zum Zulassen/Verweigern an.
    • stattdessen wird der Activity.onRequestPermissionsResult () - Rückruf sofort mit einem Ablehnungsflag aufgerufen.

Lösung:

Wenn die App auf API-Ebene 23 oder höher ausgerichtet ist, muss der App-Benutzer der App diese Berechtigung über einen Berechtigungsverwaltungsbildschirm explizit erteilen. Die App fordert die Zustimmung des Benutzers an, indem sie eine Absicht mit der Aktion ACTION_MANAGE_OVERLAY_PERMISSION sendet. Die App kann überprüfen, ob sie über diese Berechtigung verfügt, indem sie Settings.canDrawOverlays () aufruft.

beispielcode:

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

"Und wie kann der Benutzer diese Berechtigung deaktivieren? Es wird nicht in den Berechtigungen in Einstellungen-> Apps ->" MyApp "-> Berechtigungen angezeigt. Außerdem ... jede Erklärung, warum diese Berechtigung anders ist als die anderen in der Art, wie wir es verlangen? - Anonymous 12. Februar um 21:01 "

Es gibt einige Berechtigungen, die sich nicht wie normale und gefährliche Berechtigungen verhalten. SYSTEM_ALERT_WINDOW und WRITE_SETTINGS sind besonders sensibel, daher sollten die meisten Apps sie nicht verwenden. Wenn eine App eine dieser Berechtigungen benötigt, muss sie die Berechtigung im Manifest deklarieren und eine Absicht senden, in der die Autorisierung des Benutzers angefordert wird. Das System reagiert auf die Absicht, indem es dem Benutzer einen detaillierten Verwaltungsbildschirm anzeigt.

Sondergenehmigungen

edit II:

Ich habe diesen Code in einer Aktivität verwendet, die FragmentActivity erweitert, und ich habe die Ausnahme Java.lang.IllegalArgumentException erhalten: Kann nur niedrigere 16 Bits für requestCode verwenden, da der verwendete Anforderungscode nicht im Bereich von 0 ... 65535 liegt. Möglicherweise sollten Sie Änderungen in Betracht ziehen Ihren Anforderungscode auf einen geeigneten Wert. - Mtsahakis

wie es heißt:

Der Anforderungscode muss im Bereich von 0 .. 65535 liegen.

das ist weil:

  • ganzzahl in Java wird durch 32 Bit dargestellt
  • sie dürfen niedrigere 16-Bit-Werte für requestCode verwenden
  • andere Bits werden bei der Anforderungsverarbeitung verwendet

so zum beispiel:

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

Einfacher Code im angegebenen Bereich verwenden

edit III:

für Apps mit AOSP API 26 (Android oreo/8+)

Apps, die die Berechtigung SYSTEM_ALERT_WINDOW verwenden, können die folgenden Fenstertypen nicht mehr zum Anzeigen von Warnfenstern über anderen Apps und Systemfenstern verwenden:

TYPE_PHONE TYPE_PRIORITY_PHONE TYPE_SYSTEM_ALERT TYPE_SYSTEM_OVERLAY TYPE_SYSTEM_ERROR

Stattdessen müssen Apps einen neuen Fenstertyp mit dem Namen TYPE_APPLICATION_OVERLAY verwenden.

TYPE_APPLICATION_OVERLAY

Fenstertyp: Anwendungs-Overlay-Fenster werden über allen Aktivitätsfenstern (Typen zwischen FIRST_APPLICATION_WINDOW und LAST_APPLICATION_WINDOW), aber unter kritischen Systemfenstern wie der Statusleiste oder IME angezeigt.

Das System kann die Position, Größe oder Sichtbarkeit dieser Fenster jederzeit ändern, um die visuelle Unordnung für den Benutzer zu verringern und Ressourcen zu verwalten.

Erfordert die Berechtigung SYSTEM_ALERT_WINDOW.

Das System passt die Wichtigkeit von Prozessen mit diesem Fenstertyp an, um die Wahrscheinlichkeit zu verringern, dass der Low-Memory-Killer sie tötet. In Mehrbenutzersystemen wird nur auf dem Bildschirm des Besitzers angezeigt.

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

Window.setAttributes(WindowManager.LayoutParams)
137
ceph3us

Nachdem Sie ceph3us geantwortet haben, um einen Warnungsdialog hinzuzufügen, hat dies problemlos funktioniert

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

Die Verwendung von TYPE_SYSTEM_ALERT kann jedoch dazu führen, dass Google Apps mit gefährlichen Berechtigungen deaktiviert. Stellen Sie sicher, dass Sie eine gültige Begründung haben, falls Google dies erfordert.

3