Android: Fenster kann nicht hinzugefügt werden. Berechtigung für diesen Fenstertyp verweigert

83

Ich arbeite an einer App, in der ich ein Fenster mit einigen Informationen auf dem Sperrbildschirm (KeyGuard) anzeigen muss, ohne das Telefon zu entsperren. Ich dachte, ich könnte es wahrscheinlich mit WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG tun

Aber jedes Mal stürzt meine App mit folgendem Fehler ab:

android.view.WindowManager $ BadTokenException: Fenster android.view.ViewRootImpl$W@40ec8528 kann nicht hinzugefügt werden - Berechtigung für diesen Fenstertyp verweigert

Diese Beiträge ( hier , hier und hier ) geben alle die gleiche Antwort. So fügen Sie der Manifest-Datei die folgende Berechtigung hinzu

android.permission.SYSTEM_ALERT_WINDOW

Lösung, die ich implementiert habe, aber immer noch den gleichen Fehler erhalte. Irgendeine Idee, was ich falsch mache?

Hier sind die Berechtigungen in meiner Manifestdatei:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.droidpilot.keyguardwindow" >

<uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="21" />

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />

Und dies ist der Code, mit dem ich das Fenster zum Sperrbildschirm hinzufüge

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    mView = mInflater.inflate(R.layout.lock_screen_notif, null);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
            PixelFormat.TRANSLUCENT
    );

    wm.addView(mView, params);

Hat jemand eine Idee?

PS Ich teste auf einem HTC Desire 620 DS mit Android 4.4.2

DroidPilot
quelle

Antworten:

30

Aus ganz offensichtlichen Gründen dürfen normale Apps keine beliebigen Fenster über dem Sperrbildschirm erstellen . Was könnte ich tun, wenn ich ein Fenster auf Ihrem Sperrbildschirm erstellen würde, das den echten Sperrbildschirm perfekt imitieren könnte, sodass Sie den Unterschied nicht erkennen könnten?

Der technische Grund für Ihren Fehler ist die Verwendung des TYPE_KEYGUARD_DIALOGFlags - es android.permission.INTERNAL_SYSTEM_WINDOWist eine Berechtigung auf Signaturebene erforderlich . Dies bedeutet, dass nur Apps, die mit demselben Zertifikat wie der Ersteller der Berechtigung signiert sind, es verwenden können.

Der Schöpfer von android.permission.INTERNAL_SYSTEM_WINDOWist das Android-System selbst. Wenn Ihre App nicht Teil des Betriebssystems ist, haben Sie keine Chance.

Es gibt gut definierte und gut dokumentierte Möglichkeiten , den Benutzer über Informationen auf dem Sperrbildschirm zu informieren . Sie können benutzerdefinierte Benachrichtigungen erstellen, die auf dem Sperrbildschirm angezeigt werden, und der Benutzer kann mit ihnen interagieren.

Adelphus
quelle
2
Persönlich suchte ich nach so etwas wie den Sperrbildschirmbenachrichtigungen der Facebook-App. Ich wusste bereits über die neuen Benachrichtigungen auf dem Sperrbildschirm Bescheid, aber diese funktionieren derzeit nur in Android 22. Ich brauche eine Lösung, die auf Android 16 und höher funktioniert. Aber Ihre Antwort macht vollkommen Sinn und ich werde sie als solche akzeptieren. Ich habe es zwar geschafft, ein Fenster auf dem Sperrbildschirm anzuzeigen, aber es ist nicht das, was ich brauche. Ich werde die Lösung veröffentlichen, die ich unten gefunden habe.
DroidPilot
1
Wenn Apps diese Berechtigung benötigen, kann sie nach der Installation und dem Öffnen erteilt werden.
SkorpEN
Ich denke, dass dies seit Oreo die richtige Antwort ist stackoverflow.com/a/48481628/504179
ATom
107

Wenn Sie verwenden apiLevel >= 19, verwenden Sie nicht

WindowManager.LayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT 

welches den folgenden Fehler bekommt:

android.view.WindowManager $ BadTokenException: Fenster android.view.ViewRootImpl$W@40ec8528 kann nicht hinzugefügt werden - Berechtigung für diesen Fenstertyp verweigert

Verwenden Sie stattdessen Folgendes:

LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL
recotone2000
quelle
3
Ich habe TYPE_SYSTEM_ALERTgut auf Android 5.1 mit dem android.permission.SYSTEM_ALERT_WINDOWim Manifest gewährten funktioniert .
Sam
Ich habe zu verwenden , android.permission.SYSTEM_ALERT_WINDOWmit LayoutParams.TYPE_TOAST?
Bis zum
1
Ich habe LayoutParams.TYPE_TOAST ausprobiert. Es funktioniert für mich auf Lollipop und Marshmallow, beide API Level 6.0.1. Vorher habe ich WindowManager.LayoutParams.TYPE_SYSTEM_ALERT verwendet, das nur für Lollipop funktionierte.
Prashant
Leider verursacht es "Bildschirmüberlagerung erkannt", falls eine Anwendung einen Berechtigungsdialog anfordert (wenn Ihre Ansicht aktiv ist)
Siarhei
Dies würde nicht funktionieren, wenn Sie versuchen, das Fenster innerhalb eines Dienstes oder eines Rundfunkempfängers anzuzeigen
FindOutIslamNow
77

Ich denke, Sie sollten das Ziel unterscheiden (vor und nach Oreo)

int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}

params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    LAYOUT_FLAG,
    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    PixelFormat.TRANSLUCENT);
Cédric Dufouil
quelle
Ich versuche eine ähnliche Technik zu verwenden, aber Android Studio kann Build.VERSION_CODES.O& nicht erkennen WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY. Meine targetSdkVersion ist 26
Gabe O'Leary
Schätzen Sie Ihre Hilfe +1 von meiner Seite.
Saveen
@ GabeO'Leary Ich stehe vor dem gleichen Problem. Hast du eine Lösung dafür?
Sagar
49

Ich habe mein Bestes gegeben, um alle für diese Ausgabe verfügbaren Beispiele auszuprobieren. Endlich habe ich die Antwort darauf bekommen. Ich weiß nicht, wie zuverlässig es ist, aber meine App stürzt jetzt nicht ab.

windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
    //here is all the science of params
    final LayoutParams myParams = new LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            LayoutParams.TYPE_SYSTEM_ERROR,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
            PixelFormat.TRANSLUCENT
    );

Geben Sie in Ihrer Manifestdatei einfach die Erlaubnis ein

 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Zusätzlich können Sie auch nach der API-Ebene suchen, wenn sie dann> = 23 ist

 if(Build.VERSION.SDK_INT >= 23) {
    if (!Settings.canDrawOverlays(Activity.this)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, 1234);
    }
}
            else
{
    Intent intent = new Intent(Activity.this, Service.class);
    startService(intent);
}

Ich hoffe es hilft jemandem irgendwo. Vollständiges Beispiel https://anam-android-codes.blogspot.in/?m=1

Anam Ansari
quelle
13

Für Android API Level 8.0.0 sollten Sie verwenden

WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

anstatt

LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL

oder SYSTEM_ALERT.

Mingquan Liu
quelle
TYPE_APPLICATION_OVERLAY ist nicht in der Liste der Optionen enthalten, die in Android Studio angezeigt werden. Ich erhalte die Meldung "Symboltyp kann nicht aufgelöst werden". Was vermisse ich?
Philcruz
10

Versuchen Sie, dass dieser Code perfekt funktioniert

int layout_parms;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 

    {  
         layout_parms = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

    }

     else {

            layout_parms = WindowManager.LayoutParams.TYPE_PHONE;

    }

    yourparams = new WindowManager.LayoutParams(       
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            layout_parms,
            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);
Shakirullah Orakzai
quelle
Du hast mein Leben gerettet
Fo Nko
@BakaWaii, wo Sie Widget zeigen möchten, um diesen Code dort
einzufügen,
6

Suche

Zeichnen Sie über andere Apps

in Ihrer Einstellung und aktivieren Sie Ihre App. Versuchen Sie es für Android 8 Oreo

Einstellungen> Apps & Benachrichtigungen> App-Informationen> Über andere Apps anzeigen> Aktivieren

JeffNhan
quelle
1
Sie sind ein Lebensretter
Noor Hossain
5

Zunächst stellen Sie sicher, dass Sie über die Berechtigung zum Hinzufügen in der Manifestdatei verfügen.

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Überprüfen Sie, ob die Anwendung über die Berechtigung anderer Apps verfügt oder nicht. Diese Berechtigung ist standardmäßig für API <23 verfügbar. Für API> 23 müssen Sie jedoch zur Laufzeit nach der Berechtigung fragen.

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {

    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
            Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, 1);
} 

Verwenden Sie diesen Code:

public class ChatHeadService extends Service {

private WindowManager mWindowManager;
private View mChatHeadView;

WindowManager.LayoutParams params;

public ChatHeadService() {
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();

    Language language = new Language();
    //Inflate the chat head layout we created
    mChatHeadView = LayoutInflater.from(this).inflate(R.layout.dialog_incoming_call, null);


    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
        params.x = 0;
        params.y = 100;
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mChatHeadView, params);

    } else {
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                PixelFormat.TRANSLUCENT);


        params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
        params.x = 0;
        params.y = 100;
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mChatHeadView, params);
    }

    TextView tvTitle=mChatHeadView.findViewById(R.id.tvTitle);
    tvTitle.setText("Incoming Call");

    //Set the close button.
    Button btnReject = (Button) mChatHeadView.findViewById(R.id.btnReject);
    btnReject.setText(language.getText(R.string.reject));
    btnReject.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //close the service and remove the chat head from the window
            stopSelf();
        }
    });

    //Drag and move chat head using user's touch action.
    final Button btnAccept = (Button) mChatHeadView.findViewById(R.id.btnAccept);
    btnAccept.setText(language.getText(R.string.accept));


    LinearLayout linearLayoutMain=mChatHeadView.findViewById(R.id.linearLayoutMain);



    linearLayoutMain.setOnTouchListener(new View.OnTouchListener() {
        private int lastAction;
        private int initialX;
        private int initialY;
        private float initialTouchX;
        private float initialTouchY;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:

                    //remember the initial position.
                    initialX = params.x;
                    initialY = params.y;

                    //get the touch location
                    initialTouchX = event.getRawX();
                    initialTouchY = event.getRawY();

                    lastAction = event.getAction();
                    return true;
                case MotionEvent.ACTION_UP:
                    //As we implemented on touch listener with ACTION_MOVE,
                    //we have to check if the previous action was ACTION_DOWN
                    //to identify if the user clicked the view or not.
                    if (lastAction == MotionEvent.ACTION_DOWN) {
                        //Open the chat conversation click.
                        Intent intent = new Intent(ChatHeadService.this, HomeActivity.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);

                        //close the service and remove the chat heads
                        stopSelf();
                    }
                    lastAction = event.getAction();
                    return true;
                case MotionEvent.ACTION_MOVE:
                    //Calculate the X and Y coordinates of the view.
                    params.x = initialX + (int) (event.getRawX() - initialTouchX);
                    params.y = initialY + (int) (event.getRawY() - initialTouchY);

                    //Update the layout with new X & Y coordinate
                    mWindowManager.updateViewLayout(mChatHeadView, params);
                    lastAction = event.getAction();
                    return true;
            }
            return false;
        }
    });
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (mChatHeadView != null) mWindowManager.removeView(mChatHeadView);
}

}}

Abhijeet Sharma
quelle
Kannst du deinen XML-Code teilen und in Github anzeigen oder etwas anderes? Es wird für mich hilfreich sein.
Pavel
4

Ändern Sie Ihr Flag Windowmanger-Flag "TYPE_SYSTEM_OVERLAY" in Ihrem Projekt in "TYPE_APPLICATION_OVERLAY", um die Kompatibilität mit Android O zu gewährleisten

WindowManager.LayoutParams.TYPE_PHONE zu WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

Rakesh Kumar B Badiger
quelle
3

Ich habe es geschafft, endlich ein Fenster auf dem Sperrbildschirm mit der Verwendung von TYPE_SYSTEM_OVERLAYanstelle von anzuzeigen TYPE_KEYGUARD_DIALOG. Dies funktioniert wie erwartet und fügt das Fenster auf dem Sperrbildschirm hinzu.

Das Problem dabei ist, dass das Fenster über alles hinzugefügt wird, was es kann. Das heißt, bei sicheren Sperrbildschirmen wird das Fenster sogar über Ihrer Tastatur- / Mustersperre angezeigt. Bei einem ungesicherten Sperrbildschirm wird dieser über der Benachrichtigungsleiste angezeigt, wenn Sie ihn über den Sperrbildschirm öffnen.

Für mich ist das inakzeptabel. Ich hoffe, dass dies allen anderen helfen kann, die mit diesem Problem konfrontiert sind.

DroidPilot
quelle
Vielen Dank für die Lösung. Gibt es eine Möglichkeit, es zu verwerfen? Ich kann den Dialog nicht schließen, wenn ich ihn als hinzufüge TYPE_SYSTEM_OVERLAY. Mein setOnDismissListener in AlertDialog wird nicht aufgerufen.
Tom Taylor
3

Ich habe gerade eine einfache Ansicht WindowManagermit den folgenden Schritten hinzugefügt :

  1. Erstellen Sie eine anzuzeigende Layoutdatei (in meinem Fall dummy_layout)
  2. Berechtigung im Manifest und dynamisch hinzufügen.
// 1. Show view
private void showCustomPopupMenu()
{
    windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
    // LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    // View view = layoutInflater.inflate(R.layout.dummy_layout, null);
    ViewGroup valetModeWindow = (ViewGroup) View.inflate(this, R.layout.dummy_layout, null);
    int LAYOUT_FLAG;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    } else {
        LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
    }
    WindowManager.LayoutParams params=new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        LAYOUT_FLAG,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT);

    params.gravity= Gravity.CENTER|Gravity.CENTER;
    params.x=0;
    params.y=0;
    windowManager.addView(valetModeWindow, params);
}

// 2. Get permissions by asking
if (!Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, 1234);
}

Damit können Sie WM eine Ansicht hinzufügen.

Getestet in Pie.

Radha Krishna
quelle
2

LayoutParams.TYPE_PHONE ist veraltet. Ich habe meinen Code wie folgt aktualisiert.

parameters = if (Build.VERSION.SDK_INT > 25) {
        LayoutParams(
                minHW * 2 / 3, minHW * 2 / 3,
                LayoutParams.TYPE_APPLICATION_OVERLAY,
                LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT)
    }else {
        LayoutParams(
                minHW * 2 / 3, minHW * 2 / 3,
                LayoutParams.TYPE_PHONE,
                LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT)
    }

LayoutParams.TYPE_APPLICATION_OVERLAY erfordert API-Level 26 oder höher.

Ashiqul Islam
quelle
0

Der Hauptgrund für die Verweigerung der Berechtigung ist, dass wir keine Berechtigung zum Zeichnen über andere Apps haben. Wir müssen die Berechtigung zum Zeichnen über andere Apps bereitstellen, die mit dem folgenden Code ausgeführt werden kann

Code für die Erlaubnis anfordern

    public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;

Fügen Sie dies in Ihre MainActivity ein


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
            askPermission();
}

private void askPermission() {
        Intent intent= new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
        startActivityForResult(intent,ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}

Fügen Sie dies auch hinzu

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE){
            if(!Settings.canDrawOverlays(this)){
                askPermission();
            }
        }
    }
Sai Pavan Kumar
quelle
0

Ich hatte Mühe, die funktionierende Lösung mit ApplicationContextund zu finden, TYPE_SYSTEM_ALERTund fand verwirrende Lösungen. getApplicationContext()Wenn Sie möchten, dass der Dialog von einer Aktivität aus geöffnet wird, ist auch der Dialog ein Singleton, den Sie verwenden müssen , und wenn Sie möchten, dass der Dialog sein soll, müssen TYPE_SYSTEM_ALERTSie die folgenden Schritte ausführen ::

Holen Sie sich zuerst die Instanz des Dialogs mit dem richtigen Thema. Außerdem müssen Sie die Versionskompatibilität wie in meinem folgenden Snippet verwalten:

AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext(), R.style.Theme_AppCompat_Light);

Nachdem Sie den Titel, die Nachricht und die Schaltflächen festgelegt haben, müssen Sie den Dialog wie folgt erstellen:

AlertDialog alert = builder.create();

Jetzt typespielt das hier die Hauptrolle, da dies der Grund für den Absturz ist, habe ich die Kompatibilität wie folgt behandelt:

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        alert.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);

    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    }

Hinweis : Wenn Sie einen benutzerdefinierten Dialog mit AppCompatDialogden folgenden Optionen verwenden:

AppCompatDialog dialog = new AppCompatDialog(getApplicationContext(), R.style.Theme_AppCompat_Light);

Sie können Ihren Typ für die AppCompatDialogInstanz wie folgt direkt definieren :

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);

    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    }

Vergessen Sie nicht, die Manifest-Berechtigung hinzuzufügen:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
HAXM
quelle
0
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.START | Gravity.TOP;
    params.x = left;
    params.y = top;
    windowManager.addView(view, params);

} else {
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            PixelFormat.TRANSLUCENT);


    params.gravity = Gravity.START | Gravity.TOP;
    params.x = left;
    params.y = top;
    windowManager.addView(view, params);
}
Harpreet
quelle