Warum gibt es in der Android O-Methode Settings.canDrawOverlays () "false", wenn der Benutzer die Berechtigung zum Zeichnen von Überlagerungen und zur Rückgabe an meine Anwendung erteilt hat?

11

Ich habe die MDM-App für Eltern, um Kindergeräte zu steuern, und sie verwendet die Berechtigung SYSTEM_ALERT_WINDOW , um Warnungen auf dem Gerät des Kindes anzuzeigen, wenn eine verbotene Aktion ausgeführt wurde. Auf Geräten M + während der Installation überprüft die App die Berechtigung mit dieser Methode:

%Vor%

Wenn diese Methode false zurückgibt, öffnet die App den Systemdialog, in dem der Benutzer die Berechtigung erteilen kann:

%Vor%

Wenn Sie in Android O die Berechtigung erteilen und durch Drücken der Zurück-Taste zur App zurückkehren, gibt die Methode canDrawOverlays() immer noch false zurück, bis der Benutzer die App nicht schließt und öffnet oder wählen Sie es im letzten App-Dialog. Ich habe es auf der neuesten Version des virtuellen Geräts mit Android O in Android Studio getestet, weil ich kein echtes Gerät habe.

Ich habe ein wenig recherchiert und zusätzlich die Berechtigung mit AppOpsManager überprüft:

%Vor%

Und so:

  • Wenn die Anwendung diese Berechtigung nicht hat, ist der Modus "2" (MODE_ERRORED) ( canDrawOverlays() gibt false zurück) wenn der Benutzer
  • erteilt Erlaubnis und kehrte zur Anwendung zurück, der Modus ist "1" (MODE_IGNORED) ( canDrawOverlays() gibt false zurück)
  • Wenn Sie die App jetzt erneut öffnen, ist der Modus "0" (MODE_ALLOWED) ( canDrawOverlays() gibt true )
  • zurück

Bitte, kann mir jemand dieses Verhalten erklären? Kann ich mich auf mode == 1 der Operation "android:system_alert_window" verlassen und davon ausgehen, dass der Benutzer die Berechtigung erteilt hat?

    
Nikolay 12.09.2017, 10:00
quelle

4 Antworten

3

Ich habe diese Probleme auch mit checkOp gefunden. In meinem Fall habe ich den Fluss, der erlaubt, auf Einstellungen nur umzuleiten, wenn die Erlaubnis nicht eingestellt wird. Und die AppOps wird nur beim Weiterleiten an Einstellungen festgelegt.

Angenommen AppOps Callback wird nur aufgerufen, wenn sich etwas geändert hat und es nur einen Schalter gibt, der geändert werden kann. Das heißt, wenn ein Rückruf aufgerufen wird, muss der Benutzer die Berechtigung erteilen.

%Vor%

Nachdem die App wiederhergestellt wurde, hat die Überprüfung mit canDrawOverlays() für mich funktioniert. Natürlich starte ich die App neu und überprüfe, ob die Erlaubnis über den Standardweg erteilt wurde.

Es ist definitiv keine perfekte Lösung, aber es sollte funktionieren, bis wir mehr von Google wissen.

BEARBEITEN: Ich fragte Google: Ссылка

EDIT 2: Google behebt dies. Aber es scheint, dass die Android O-Version immer noch betroffen sein wird.

    
l0v3 19.09.2017, 13:36
quelle
8

Ich stieß auf das gleiche Problem. Ich verwende einen Workaround, der versucht, ein unsichtbares Overlay hinzuzufügen. Wenn eine Ausnahme ausgelöst wird, wird die Berechtigung nicht erteilt. Es ist vielleicht nicht die beste Lösung, aber es funktioniert. Ich kann Ihnen nichts über die AppOps-Lösung erzählen, aber es sieht zuverlässig aus.

%Vor%     
Ch4t4r 12.09.2017 11:09
quelle
1

In meinem Fall habe ich die API-Ebene & lt; Oreo und die unsichtbare Überlagerungsmethode in Ch4t4's Antwort funktioniert nicht, da es keine Ausnahme auslöst.

Bei der obigen Antwort von l0v3 und der Notwendigkeit, den Benutzer davor zu schützen, die Berechtigung mehrmals zu wechseln, habe ich den folgenden Code verwendet (Android-Versionsprüfungen wurden weggelassen):

In der Aktivität / Fragment:

%Vor%

Um die Berechtigung in der Aktivität / dem Fragment anzufordern:

%Vor%

Und in onActivityResult

%Vor%

Um zu verhindern, dass Ihre Aktivität im Hintergrund zerstört wird, in onCreate :

%Vor%

und intern onDestroy , stopWatchingMode sollten aufgerufen werden, wenn onOpChangedListener nicht null ist, ähnlich wie onActivityResult oben.

Es ist wichtig zu beachten, dass das System ab der aktuellen Implementierung (Android O) registrierte Listener vor dem Zurückrufen nicht de-duplizieren wird. Die Registrierung von startWatchingMode(ops, packageName, listener) führt dazu, dass der Listener entweder für übereinstimmende Operationen oder den übereinstimmenden Paketnamen aufgerufen wird und für den Fall, dass beide übereinstimmen, zweimal aufgerufen wird. Daher wird der Paketname oben auf null gesetzt, um den doppelten Aufruf zu vermeiden. Wenn Sie den Listener mehrmals registrieren, ohne die Registrierung von stopWatchingMode aufzuheben, wird der Listener mehrere Male aufgerufen - dies gilt auch für die gesamten Lebenszyklen der Aktivität destroy-create.

Alternativ zu den obigen Schritten können Sie eine Verzögerung von etwa 1 Sekunde vor dem Aufruf von Settings.canDrawOverlays(context) festlegen. Der Wert der Verzögerung hängt jedoch vom Gerät ab und ist möglicherweise nicht zuverlässig. (Referenz: Ссылка )

    
headuck 06.01.2018 12:09
quelle
1

Tatsächlich gibt es unter Android 8.0 true zurück, aber es gibt Catch, es wird nur zurückgegeben, wenn Sie 5 bis 15 Sekunden warten und erneut nach Overlay-Berechtigung mit Settings.canDrawOverlays(context) Methode suchen.

Sie müssen also dem Benutzer eine ProgressDialog mit einer Fehlermeldung anzeigen und eine CountDownTimer ausführen, um mit Settings.canDrawOverlays(context) in onTick method nach Overlay-Berechtigungen zu suchen.

Bitte schauen Sie sich einen Beispielcode aus einem Fragment an:

%Vor%     
Vikas Patidar 16.03.2018 19:53
quelle

Tags und Links