Verhaltensänderungen unter Android 8.0

Neben neuen Funktionen und Möglichkeiten beinhaltet Android 8.0 (API-Level 26) eine Reihe von Änderungen am System- und API-Verhalten. In diesem Dokument werden einige der wichtigsten Änderungen beschrieben, die Sie in Ihren Anwendungen verstehen und berücksichtigen sollten.

Die meisten dieser Änderungen betreffen alle Apps, unabhängig davon, auf welche Android-Version sie ausgerichtet sind. Einige Änderungen betreffen jedoch nur Apps, die auf Android 8.0 ausgerichtet sind. Der Übersichtlichkeit halber ist diese Seite in zwei Abschnitte unterteilt: Änderungen für alle Apps und Änderungen für Apps, die auf Android 8.0 ausgerichtet sind.

Änderungen für alle Apps

Diese Verhaltensänderungen gelten für alle Apps, wenn sie auf der Plattform Android 8.0 (API-Level 26) ausgeführt werden, unabhängig von der Ziel-API-Ebene. Alle Entwickler sollten diese Änderungen prüfen und ihre Apps so anpassen, dass sie korrekt unterstützt werden, sofern dies von der jeweiligen App der Fall ist.

Limits für die Ausführung im Hintergrund

Eine der Änderungen, die in Android 8.0 (API-Level 26) eingeführt wird, um die Akkulaufzeit zu verlängern: Wenn deine App in den Cache-Status wechselt und keine aktiven Komponenten vorhanden sind, gibt das System alle Wakelocks der App frei.

Darüber hinaus schränkt das System zur Verbesserung der Geräteleistung bestimmte Verhaltensweisen von Apps ein, die nicht im Vordergrund ausgeführt werden. Im Detail:

  • Für Anwendungen, die im Hintergrund ausgeführt werden, gelten jetzt Einschränkungen für den freien Zugriff auf Hintergrunddienste.
  • Apps können ihre Manifeste nicht verwenden, um sich für die meisten impliziten Broadcasts zu registrieren, d. h. Broadcasts, die nicht speziell auf die App ausgerichtet sind.

Standardmäßig gelten diese Einschränkungen nur für Apps, die auf O ausgerichtet sind. Nutzer können diese Einschränkungen jedoch auf dem Bildschirm Einstellungen für jede App aktivieren, auch wenn die App nicht auf O ausgerichtet ist.

Android 8.0 (API-Level 26) umfasst außerdem die folgenden Änderungen bei bestimmten Methoden:

  • Die Methode startService() gibt jetzt ein IllegalStateException aus, wenn eine auf Android 8.0 ausgerichtete App versucht, diese Methode in einer Situation zu verwenden, in der das Erstellen von Hintergrunddiensten nicht zulässig ist.
  • Mit der neuen Methode Context.startForegroundService() wird ein Dienst im Vordergrund gestartet. Durch das System können Apps Context.startForegroundService() auch dann aufrufen, wenn die App im Hintergrund läuft. Die Anwendung muss die Methode startForeground() dieses Dienstes jedoch innerhalb von fünf Sekunden nach Erstellung des Dienstes aufrufen.

Weitere Informationen finden Sie unter Limits für die Hintergrundausführung.

Beschränkungen für die Standortermittlung im Hintergrund auf Android-Geräten

Hintergrund-Apps erhalten Standortupdates seltener, wenn sie auf einem Gerät mit Android 8.0 verwendet werden, um den Akku, die Nutzerfreundlichkeit und den Systemzustand zu schonen. Diese Verhaltensänderung betrifft alle Apps, die Standortaktualisierungen erhalten, einschließlich Google Play-Dienste.

Diese Änderungen betreffen die folgenden APIs:

  • Fused Location Provider (FLP)
  • Geofencing
  • GNSS-Messungen
  • Standortmanager
  • WLAN-Manager

So sorgen Sie dafür, dass Ihre App wie erwartet ausgeführt wird:

  • Prüfen Sie die Logik Ihrer App und achten Sie darauf, dass Sie die neuesten Standort-APIs verwenden.
  • Testen Sie, ob Ihre Anwendung das Verhalten zeigt, das Sie für jeden Anwendungsfall erwarten.
  • Du kannst den Fused Location Provider (FLP) oder Geofencing verwenden, um die Anwendungsfälle abzuwickeln, die vom aktuellen Standort des Nutzers abhängen.

Weitere Informationen zu diesen Änderungen findest du unter Limits für die Standortermittlung im Hintergrund.

App-Verknüpfungen

Unter Android 8.0 (API-Level 26) wurden die folgenden Änderungen an App-Verknüpfungen vorgenommen:

  • Die com.android.launcher.action.INSTALL_SHORTCUT-Übertragung hat keine Auswirkungen mehr auf Ihre App, da sie jetzt eine private, implizite Übertragung ist. Erstellen Sie stattdessen eine App-Verknüpfung mit der Methode requestPinShortcut() aus der Klasse ShortcutManager.
  • Der Intent ACTION_CREATE_SHORTCUT kann jetzt App-Verknüpfungen erstellen, die Sie mit der Klasse ShortcutManager verwalten. Dieser Intent kann auch Legacy-Launcher-Verknüpfungen erstellen, die nicht mit ShortcutManager interagieren. Bisher konnten mit diesem Intent nur Legacy-Launcher-Verknüpfungen erstellt werden.
  • Verknüpfungen, die mit requestPinShortcut() erstellt wurden, und Verknüpfungen, die in einer Aktivität erstellt wurden, die den Intent ACTION_CREATE_SHORTCUT verarbeitet, sind jetzt vollwertige App-Verknüpfungen. Daher können Anwendungen sie jetzt mit den Methoden in ShortcutManager aktualisieren.
  • Alte Tastenkombinationen funktionieren weiterhin wie in früheren Android-Versionen, müssen aber in deiner App manuell in App-Verknüpfungen umgewandelt werden.

Weitere Informationen zu Änderungen an App-Verknüpfungen finden Sie im Leitfaden zum Anpinnen von Verknüpfungen und Widgets.

Sprachen und Internationalisierung

Mit Android 7.0 (API-Level 24) wurde das Konzept eingeführt, ein Standardgebietsschema für die Kategorie angeben zu können. Einige APIs nutzten jedoch weiterhin die generische Locale.getDefault()-Methode ohne Argumente, obwohl sie stattdessen die Standardsprache der DISPLAY-Kategorie verwendet hätten sollten. In Android 8.0 (API-Level 26) wird für die folgenden Methoden jetzt Locale.getDefault(Category.DISPLAY) anstelle von Locale.getDefault() verwendet:

Locale.getDisplayScript(Locale) wird auch auf Locale.getDefault() zurückgesetzt, wenn der für das Argument Locale angegebene displayScript-Wert nicht verfügbar ist.

Zusätzliche Änderungen in Bezug auf die Sprache und die Internationalisierung:

  • Durch das Aufrufen von Currency.getDisplayName(null) wird entsprechend dem dokumentierten Verhalten ein NullPointerException ausgegeben.
  • Das Parsen von Zeitzonennamen hat sich geändert. Bisher wurde auf Android-Geräten der beim Start erfasste Systemuhrwert verwendet, um die Zeitzonennamen im Cache zu speichern, die zum Parsen von Datum und Uhrzeit verwendet wurden. Dies kann sich negativ auf das Parsen auswirken, wenn die Systemuhr beim Start falsch war oder in anderen, seltenen Fällen.

    In den meisten Fällen verwendet die Parsing-Logik beim Parsen von Zeitzonennamen ICU und den aktuellen Systemuhrwert. Durch diese Änderung erhältst du korrektere Ergebnisse, die sich von früheren Android-Versionen unterscheiden können, wenn deine App Klassen wie SimpleDateFormat verwendet.

  • Unter Android 8.0 (API-Level 26) wird die ICU auf Version 58 aktualisiert.

Benachrichtigungsfenster

Wenn eine App die Berechtigung SYSTEM_ALERT_WINDOW und einen der folgenden Fenstertypen verwendet, um zu versuchen, Benachrichtigungsfenster über anderen Apps und Systemfenstern anzuzeigen:

...dann werden diese Fenster immer unter den Fenstern mit dem Fenstertyp TYPE_APPLICATION_OVERLAY angezeigt. Ist eine App auf Android 8.0 (API-Level 26) ausgerichtet, verwendet die App den Fenstertyp TYPE_APPLICATION_OVERLAY, um Benachrichtigungsfenster anzuzeigen.

Weitere Informationen finden Sie im Abschnitt Häufig verwendete Fenstertypen für Benachrichtigungsfenster in den Verhaltensänderungen für Apps für Android 8.0.

Eingabe und Navigation

Mit der Einführung von Android-Apps unter ChromeOS und anderen großen Formfaktoren wie Tablets haben wir festgestellt, dass die Tastaturnavigation in Android-Apps immer häufiger verwendet wird. Unter Android 8.0 (API-Level 26) haben wir die Tastatur als Navigationseingabegerät überarbeitet, was zu einem zuverlässigeren, vorhersehbaren Modell für die pfeil- und tabulatorbasierte Navigation führt.

Insbesondere haben wir die folgenden Änderungen am Verhalten des Elementfokus vorgenommen:

  • Wenn du für ein View-Objekt (entweder sein Drawable im Vorder- oder Hintergrund) keine Farben für den Fokusstatus definiert hast, legt das Framework jetzt eine Standardfarbe für die Hervorhebung des Fokus für View fest. Diese Fokusmarkierung ist ein Ripple-Drawable, das auf dem Thema der Aktivität basiert.

    Wenn du nicht möchtest, dass ein View-Objekt diese standardmäßige Hervorhebung beim Empfang des Fokus verwendet, setze das android:defaultFocusHighlightEnabled-Attribut in der Layout-XML-Datei, die View enthält, auf false oder übergib false in der UI-Logik deiner App an setDefaultFocusHighlightEnabled().

  • Wenn Sie testen möchten, wie sich die Tastatureingabe auf den Fokus des UI-Elements auswirkt, können Sie die Entwickleroption Zeichnung > Layoutgrenzen anzeigen aktivieren. In Android 8.0 wird durch diese Option ein „X“-Symbol über dem Element angezeigt, das derzeit im Fokus ist.

Außerdem sind alle Symbolleistenelemente in Android 8.0 automatisch Tastaturnavigationscluster, was den Nutzern das Aufrufen und Verlassen der einzelnen Symbolleisten erleichtert.

Weitere Informationen dazu, wie Sie die Unterstützung für die Tastaturnavigation in Ihrer App verbessern können, finden Sie im Leitfaden Unterstützung der Tastaturnavigation.

Webformular automatisch ausfüllen

Da das Android Autofill-Framework jetzt die Funktion zum automatischen Ausfüllen unterstützt, haben sich die folgenden Methoden für WebView-Objekte für Apps geändert, die auf Geräten mit Android 8.0 (API-Ebene 26) installiert sind:

WebSettings
  • Die Methode getSaveFormData() gibt jetzt false zurück. Zuvor wurde bei dieser Methode stattdessen true zurückgegeben.
  • Das Aufrufen von setSaveFormData() hat keine Auswirkungen mehr.
WebViewDatabase
  • Das Aufrufen von clearFormData() hat keine Auswirkungen mehr.
  • Die Methode hasFormData() gibt jetzt false zurück. Bisher wurde bei dieser Methode true zurückgegeben, wenn das Formular Daten enthielt.

Barrierefreiheit

Unter Android 8.0 (API-Level 26) wurden die folgenden Änderungen bei den Bedienungshilfen vorgenommen:

  • Das Framework für Bedienungshilfen wandelt jetzt alle Touch-Gesten zum Doppeltippen in ACTION_CLICK-Aktionen um. Durch diese Änderung verhält sich TalkBack ähnlich wie andere Bedienungshilfen.

    Wenn die View-Objekte deiner App benutzerdefinierte Touchbedienung verwenden, solltest du prüfen, ob sie noch mit TalkBack funktionieren. Unter Umständen müssen Sie nur den Klick-Handler registrieren, der von Ihren View-Objekten verwendet wird. Wenn TalkBack weiterhin keine Touch-Gesten erkennt, die für diese View-Objekte ausgeführt wurden, überschreiben Sie performAccessibilityAction().

  • Bedienungshilfen erkennen jetzt alle ClickableSpan-Instanzen in den TextView-Objekten deiner App.

Weitere Informationen dazu, wie Sie die Barrierefreiheit Ihrer App verbessern können, finden Sie unter Bedienungshilfen.

Netzwerk und HTTP(S)-Verbindung

Android 8.0 (API-Level 26) umfasst die folgenden Änderungen im Verhalten von Netzwerken und HTTP(S)-Verbindungen:

  • OPTIONS-Anfragen ohne Text haben einen Content-Length: 0-Header. Bisher hatten sie keine Content-Length-Kopfzeile.
  • HttpURLConnection normalisiert URLs mit leeren Pfaden, indem nach dem Host- oder Zertifizierungsstellennamen ein Schrägstrich mit einem Schrägstrich angehängt wird. Beispielsweise wird http://example.com in http://example.com/ umgewandelt.
  • Eine mit ProxySelector.setDefault() festgelegte benutzerdefinierte Proxyauswahl zielt nur auf die Adresse (Schema, Host und Port) einer angeforderten URL ab. Die Proxyauswahl kann daher nur auf diesen Werten basieren. Eine URL, die an einen benutzerdefinierten Proxy-Selektor übergeben wird, enthält nicht den Pfad, die Abfrageparameter oder die Fragmente der angeforderten URL.
  • URIs dürfen keine leeren Labels enthalten.

    Bisher wurde von der Plattform eine Problemumgehung unterstützt, um leere Labels in Hostnamen zu akzeptieren. Die Verwendung von URIs ist damit nicht zulässig. Diese Umgehung diente der Kompatibilität mit älteren Libcore-Releases. Entwicklern, die die API fälschlicherweise verwenden, wird die ADB-Meldung angezeigt: „URI beispiel.de enthält leere Labels im Hostnamen. Dieses ist fehlerhaft und wird in zukünftigen Android-Releases nicht mehr akzeptiert.“ Unter Android 8.0 wurde diese Problemumgehung entfernt. Das System gibt für fehlerhafte URIs null zurück.

  • Die Implementierung von HttpsURLConnection in Android 8.0 bietet keinen Fallback für unsichere TLS/SSL-Protokollversionen.
  • Die Verarbeitung von Tunneling-HTTP(S)-Verbindungen hat sich folgendermaßen geändert:
    • Beim Tunneling einer HTTPS-Verbindung über eine Verbindung fügt das System beim Senden dieser Informationen an einen Zwischenserver die Portnummer (:443) korrekt in die Host-Zeile ein. Bisher kam die Portnummer nur in der CONNECT-Zeile vor.
    • Das System sendet keine User-Agent- und Proxy-Autorisierungs-Header von einer getunnelten Anfrage an den Proxyserver.

      Beim Einrichten des Tunnels sendet das System keinen Proxy-Autorisierungs-Header auf einer getunnelten Http(s)URLConnection an den Proxy. Stattdessen generiert das System einen Proxy-Autorisierungs-Header und sendet ihn an den Proxy, wenn dieser Proxy als Antwort auf die ursprüngliche Anfrage HTTP 407 sendet.

      Ebenso wird der User-Agent-Header nicht mehr von der getunnelten Anfrage in die Proxyanfrage kopiert, die den Tunnel einrichtet. Stattdessen generiert die Bibliothek einen User-Agent-Header für diese Anfrage.

  • Die Methode send(java.net.DatagramPacket) löst eine SocketException aus, wenn die zuvor ausgeführte Methode "connect()" fehlgeschlagen ist.
    • DatagramSocket.connect() legt eine pendingSocketException fest, wenn ein interner Fehler vorliegt. Vor Android 8.0 löste ein nachfolgender recv()-Aufruf eine SocketException aus, obwohl ein send()-Aufruf erfolgreich gewesen wäre. Aus Konsistenzgründen geben beide Aufrufe jetzt eine SocketException ab.
  • InetAddress.isReachable() versucht ICMP, bevor auf das TCP Echo-Protokoll zurückgegriffen wird.
    • Einige Hosts, die Port 7 (TCP Echo) blockieren, z. B. google.com, sind jetzt möglicherweise erreichbar, wenn sie das ICMP Echo-Protokoll akzeptieren.
    • Für wirklich nicht erreichbare Hosts bedeutet diese Änderung, dass das Doppelte der Zeit aufgewendet wird, bevor der Aufruf zurückkehrt.

Bluetooth

Unter Android 8.0 (API-Level 26) werden die folgenden Änderungen an der Länge der Daten vorgenommen, die von der Methode ScanRecord.getBytes() abgerufen werden:

  • Bei der Methode getBytes() wird keine Annahme in Bezug auf die Anzahl der empfangenen Byte getroffen. Daher sollten sich Anwendungen nicht auf eine Mindest- oder Höchstanzahl der zurückgegebenen Byte verlassen. Stattdessen sollten sie die Länge des resultierenden Arrays auswerten.
  • Bluetooth 5-kompatible Geräte geben möglicherweise Daten zurück, die das vorherige Maximum von ca. 60 Byte überschreiten.
  • Wenn ein Remote-Gerät keine Scanantwort zurückgibt, werden möglicherweise auch weniger als 60 Byte zurückgegeben.

Nahtlose Konnektivität

Unter Android 8.0 (API-Level 26) wurden eine Reihe von Verbesserungen an den WLAN-Einstellungen vorgenommen, um die Auswahl des WLANs mit der besten Nutzererfahrung zu erleichtern. Zu den Änderungen gehören:

  • Verbesserte Stabilität und Zuverlässigkeit
  • Eine intuitivere Benutzeroberfläche.
  • Ein einzelnes, konsolidiertes Menü für die WLAN-Einstellungen.
  • Auf kompatiblen Geräten wird die WLAN-Funktion automatisch aktiviert, wenn sich ein hochwertiges gespeichertes Netzwerk in der Nähe befindet.

Sicherheit

Android 8.0 umfasst die folgenden sicherheitsbezogenen Änderungen:

  • SSLv3 wird von der Plattform nicht mehr unterstützt.
  • Beim Herstellen einer HTTPS-Verbindung zu einem Server, auf dem die Verhandlung von TLS-Protokollversionen falsch implementiert ist, versucht HttpsURLConnection nicht mehr, auf frühere TLS-Protokollversionen zurückzugreifen und es noch einmal zu versuchen.
  • Android 8.0 (API-Level 26) wendet einen SECCOMP-Filter (Secure Computing) auf alle Apps an. Die Liste der zulässigen Systemaufrufe ist auf diejenigen beschränkt, die über Bionik ausgelöst werden. Obwohl aus Gründen der Abwärtskompatibilität einige andere Systemaufrufe bereitgestellt werden, raten wir von ihrer Verwendung ab.
  • Die WebView-Objekte Ihrer App werden jetzt im Multiprozessmodus ausgeführt. Zur erhöhten Sicherheit werden Webinhalte in einem separaten, isolierten Prozess von dem Prozess der beinhaltenden Anwendung verarbeitet.
  • Sie können nicht mehr davon ausgehen, dass sich APKs in Verzeichnissen befinden, deren Namen auf -1 oder -2 enden. Anwendungen sollten zum Abrufen des Verzeichnisses sourceDir verwenden und sich nicht direkt vom Verzeichnisformat abhängig machen.
  • Informationen zu Sicherheitsverbesserungen in Bezug auf die Verwendung nativer Bibliotheken finden Sie unter Native Bibliotheken.

Darüber hinaus werden in Android 8.0 (API-Level 26) die folgenden Änderungen im Zusammenhang mit der Installation unbekannter Apps aus unbekannten Quellen eingeführt:

Weitere Informationen zum Installieren unbekannter Apps finden Sie in der Anleitung Unbekannte App-Installationsberechtigungen.

Weitere Richtlinien zur Erhöhung der Sicherheit Ihrer App finden Sie unter Sicherheit für Android-Entwickler.

Datenschutz

Unter Android 8.0 (API-Level 26) werden die folgenden datenschutzbezogenen Änderungen an der Plattform vorgenommen.

  • Kennungen werden auf der Plattform jetzt unterschiedlich verarbeitet.
    • Bei Apps, die vor einem OTA-Update auf eine Version von Android 8.0 (API-Level 26) (API-Level 26) installiert wurden, bleibt der Wert von ANDROID_ID gleich, sofern sie nicht deinstalliert und nach dem OTA-Update wieder neu installiert wird. Damit Werte nach dem OTA-Update auch bei Deinstallationen beibehalten werden, können Entwickler die alten und neuen Werte mithilfe der Schlüssel/Wert-Sicherung verknüpfen.
    • Für Apps, die auf einem Gerät mit Android 8.0 installiert sind, wird der Wert von ANDROID_ID jetzt pro App-Signaturschlüssel und pro Nutzer definiert. Der Wert von ANDROID_ID ist für jede Kombination aus App-Signaturschlüssel, Nutzer und Gerät eindeutig. Dadurch wird für Apps mit unterschiedlichen Signaturschlüsseln, die auf demselben Gerät ausgeführt werden, nicht mehr dieselbe Android-ID angezeigt (auch nicht für denselben Nutzer).
    • Der Wert von ANDROID_ID ändert sich bei der Deinstallation oder Neuinstallation eines Pakets nicht, solange der Signaturschlüssel gleich ist und die App nicht vor einem OTA-Update auf eine Version von Android 8.0 installiert wurde.
    • Der Wert von ANDROID_ID ändert sich nicht, auch wenn ein Systemupdate eine Änderung des Paketsignaturschlüssels zur Folge hat.
    • Auf Geräten, die mit Google Play-Diensten und der Werbe-ID ausgeliefert werden, musst du die Werbe-ID verwenden. Die Werbe-ID ist eine eindeutige, vom Nutzer zurücksetzbare Werbe-ID, ein einfaches Standardsystem zur Monetarisierung von Apps. Sie wird von den Google Play-Diensten bereitgestellt.

      Andere Gerätehersteller sollten weiterhin ANDROID_ID bereitstellen.

  • Beim Abfragen der Systemeigenschaft net.hostname wird ein Nullergebnis zurückgegeben.

Protokollierung nicht erfasster Ausnahmen

Wenn eine App eine Thread.UncaughtExceptionHandler installiert, die nicht den standardmäßigen Thread.UncaughtExceptionHandler aufruft, beendet das System die App nicht, wenn eine nicht abgefangene Ausnahme auftritt. Ab Android 8.0 (API-Ebene 26) protokolliert das System in dieser Situation den Ausnahme-Stacktrace. In früheren Versionen der Plattform hätte das System den Ausnahme-Stacktrace nicht protokolliert.

Wir empfehlen, dass benutzerdefinierte Thread.UncaughtExceptionHandler-Implementierungen immer den Standard-Handler aufrufen. Apps, die dieser Empfehlung folgen, sind von der Änderung in Android 8.0 nicht betroffen.

findViewById()-Signaturänderung

Alle Instanzen der findViewById()-Methode geben jetzt <T extends View> T anstelle von View zurück. Diese Änderung hat folgende Auswirkungen:

  • Dies kann dazu führen, dass vorhandener Code einen mehrdeutigen Rückgabetyp hat, z. B. wenn sowohl someMethod(View) als auch someMethod(TextView) das Ergebnis eines Aufrufs von findViewById() annimmt.
  • Bei Verwendung der Java 8-Quellsprache erfordert dies eine explizite Umwandlung in View, wenn der Rückgabetyp nicht eingeschränkt ist (z. B. assertNotNull(findViewById(...)).someViewMethod())).
  • Für Überschreibungen nicht finaler findViewById()-Methoden (z. B. Activity.findViewById()) muss der Rückgabetyp aktualisiert werden.

Änderung der Nutzungsstatistiken des Kontaktanbieters

In früheren Android-Versionen können Entwickler mit der Contact Provider-Komponente Nutzungsdaten für jeden Kontakt abrufen. In diesen Nutzungsdaten finden Sie Informationen für jede E-Mail-Adresse und jede Telefonnummer, die mit einem Kontakt verknüpft ist, einschließlich der Häufigkeit, mit der der Kontakt kontaktiert wurde, und der letzten Kontaktaufnahme mit dem Kontakt. Apps, die die Berechtigung READ_CONTACTS anfordern, können diese Daten lesen.

Apps können diese Daten weiterhin lesen, wenn sie die Berechtigung READ_CONTACTS anfordern. Unter Android 8.0 (API-Level 26) und höher werden bei Abfragen von Nutzungsdaten Näherungswerte und nicht exakte Werte zurückgegeben. Das Android-System verwaltet die genauen Werte intern, sodass diese Änderung keine Auswirkungen auf die API für die automatische Vervollständigung hat.

Diese Verhaltensänderung betrifft die folgenden Abfrageparameter:

Umgang mit Sammlungen

AbstractCollection.removeAll() und AbstractCollection.retainAll() geben jetzt immer ein NullPointerException aus. Zuvor wurde NullPointerException nicht ausgegeben, wenn die Sammlung leer war. Durch diese Änderung entspricht das Verhalten der Dokumentation.

Android Enterprise

Android 8.0 (API-Level 26) ändert das Verhalten einiger APIs und Funktionen für Unternehmensanwendungen, einschließlich Device Policy Controller (DPCs). Zu den Änderungen gehören:

  • Neue Funktionsweisen, damit Apps Arbeitsprofile auf vollständig verwalteten Geräten unterstützen
  • Änderungen an der Verarbeitung von Systemupdates, App-Überprüfung und Authentifizierung zur Verbesserung der Geräte- und Systemintegrität.
  • Verbesserungen für Bereitstellung, Benachrichtigungen, den Bildschirm „Zuletzt verwendet“ und das durchgehend aktive VPN

Alle Änderungen für Unternehmen in Android 8.0 (API-Level 26) und deren Auswirkungen auf deine App findest du unter Android in Unternehmen.

Apps, die auf Android 8.0 ausgerichtet sind

Diese Änderungen gelten ausschließlich für Apps, die auf Android 8.0 (API-Level 26) oder höher ausgerichtet sind. Apps, die für Android 8.0 kompiliert werden oder für targetSdkVersion Android 8.0 oder höher festlegen, müssen gegebenenfalls diese Verhaltensweisen entsprechend anpassen.

Benachrichtigungsfenster

Apps mit der Berechtigung SYSTEM_ALERT_WINDOW können die folgenden Fenstertypen nicht mehr verwenden, um Benachrichtigungsfenster über anderen Apps und Systemfenstern anzuzeigen:

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

Wenn Sie den Fenstertyp TYPE_APPLICATION_OVERLAY zum Anzeigen von Benachrichtigungsfenstern für Ihre App verwenden, beachten Sie die folgenden Eigenschaften des neuen Fenstertyps:

  • Die Benachrichtigungsfenster einer Anwendung werden immer unter kritischen Systemfenstern wie der Statusleiste und den IMEs angezeigt.
  • Das System kann Fenster, die den Fenstertyp TYPE_APPLICATION_OVERLAY verwenden, verschieben oder ihre Größe anpassen, um die Bildschirmdarstellung zu verbessern.
  • Durch Öffnen der Benachrichtigungsleiste können Nutzer auf die Einstellungen zugreifen, um zu verhindern, dass eine App Benachrichtigungsfenster anzeigt, die mit dem Fenstertyp TYPE_APPLICATION_OVERLAY angezeigt werden.

Benachrichtigungen zu Inhaltsänderungen

Unter Android 8.0 (API-Level 26) ändert sich das Verhalten von ContentResolver.notifyChange() und registerContentObserver(Uri, boolean, ContentObserver) bei Apps, die auf Android 8.0 ausgerichtet sind.

Für diese APIs muss jetzt ein gültiger ContentProvider für die Zertifizierungsstelle in allen URIs definiert sein. Wenn du eine gültige ContentProvider mit entsprechenden Berechtigungen definierst, kannst du deine App besser vor Inhaltsänderungen durch schädliche Anwendungen schützen und verhindern, dass potenziell private Daten an schädliche Anwendungen weitergegeben werden.

Fokus anzeigen

Anklickbare View-Objekte sind jetzt auch standardmäßig fokussierbar. Wenn ein View-Objekt anklickbar, aber nicht fokussierbar sein soll, setzen Sie das Attribut android:focusable in der Layout-XML-Datei, die View enthält, auf false oder übergeben Sie false in der UI-Logik Ihrer App auf setFocusable().

User-Agent-Abgleich bei der Browsererkennung

Android 8.0 (API-Level 26) und höher enthalten den Build-ID-String OPR. Einige Musterübereinstimmungen können dazu führen, dass die Browsererkennungslogik einen Nicht-Opera-Browser fälschlicherweise als Opera identifiziert. Ein Beispiel für eine solche Musterübereinstimmung könnte sein:

if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}

Um Probleme aufgrund einer solchen Fehlidentifizierung zu vermeiden, verwenden Sie einen anderen String als OPR als Musterübereinstimmung für den Opera-Browser.

Sicherheit

Die folgenden Änderungen wirken sich auf die Sicherheit unter Android 8.0 (API-Level 26) aus:

  • Wenn in der Netzwerksicherheitskonfiguration Ihrer App die Unterstützung von Klartext-Traffic deaktiviert wird, können die WebView-Objekte Ihrer App nicht über HTTP auf Websites zugreifen. Jedes WebView-Objekt muss stattdessen HTTPS verwenden.
  • Die Systemeinstellung Unbekannte Quellen zulassen wurde entfernt. Mit der Berechtigung Unbekannte Apps installieren werden unbekannte App-Installationen aus unbekannten Quellen verwaltet. Weitere Informationen zu dieser neuen Berechtigung finden Sie in der Anleitung Unbekannte Berechtigungen für die Installation von Apps.

Weitere Richtlinien zur Erhöhung der Sicherheit Ihrer App finden Sie unter Sicherheit für Android-Entwickler.

Kontozugriff und Sichtbarkeit

In Android 8.0 (API-Ebene 26) können Apps nur dann auf Nutzerkonten zugreifen, wenn der Authenticator Inhaber der Konten ist oder der Nutzer diesen Zugriff gewährt. Die Berechtigung GET_ACCOUNTS reicht nicht mehr aus. Damit Anwendungen Zugriff auf ein Konto erhalten, sollten sie entweder AccountManager.newChooseAccountIntent() oder eine Authenticator-spezifische Methode verwenden. Nachdem eine App Zugriff auf Konten erhalten hat, kann sie AccountManager.getAccounts() aufrufen, um darauf zuzugreifen.

Unter Android 8.0 wird LOGIN_ACCOUNTS_CHANGED_ACTION eingestellt. Anwendungen sollten stattdessen addOnAccountsUpdatedListener() verwenden, um während der Laufzeit Updates zu Konten zu erhalten.

Informationen zu neuen APIs und Methoden, die für den Kontozugriff und die Sichtbarkeit hinzugefügt wurden, finden Sie in diesem Dokument im Abschnitt zu den neuen APIs unter Kontozugriff und Auffindbarkeit.

Datenschutz

Die folgenden Änderungen wirken sich auf den Datenschutz unter Android 8.0 (API-Level 26) aus.

  • Die Systemeigenschaften net.dns1, net.dns2, net.dns3 und net.dns4 sind nicht mehr verfügbar. Mit dieser Änderung wird der Datenschutz auf der Plattform verbessert.
  • Um Netzwerkinformationen wie DNS-Server zu erhalten, können Apps mit der Berechtigung ACCESS_NETWORK_STATE ein NetworkRequest- oder NetworkCallback-Objekt registrieren. Diese Klassen sind ab Android 5.0 (API-Level 21) verfügbar.
  • Build.SERIAL wurde eingestellt. Apps, die die Seriennummer der Hardware kennen müssen, sollten stattdessen die neue Methode Build.getSerial() verwenden, für die die Berechtigung READ_PHONE_STATE erforderlich ist.
  • Mit der LauncherApps API können Apps im Arbeitsprofil keine Informationen mehr zum primären Profil abrufen. Wenn sich ein Nutzer in einem Arbeitsprofil befindet, verhält sich die LauncherApps API so, als ob keine Apps in anderen Profilen in derselben Profilgruppe installiert sind. Wie zuvor verursachen Versuche, auf nicht relevante Profile zuzugreifen, SecurityExceptions.

Berechtigungen

Vor Android 8.0 (API-Level 26) hat das System der App auch fälschlicherweise die restlichen Berechtigungen erteilt, die zur selben Berechtigungsgruppe gehören und im Manifest registriert waren, wenn eine App zur Laufzeit eine Berechtigung angefordert und die Berechtigung erteilt wurde.

Bei Apps, die auf Android 8.0 ausgerichtet sind, wurde dieses Verhalten korrigiert. Der Anwendung werden nur die Berechtigungen gewährt, die sie explizit angefordert hat. Sobald der Nutzer der App jedoch eine Berechtigung erteilt, werden alle nachfolgenden Berechtigungsanfragen in dieser Berechtigungsgruppe automatisch gewährt.

Angenommen, eine Anwendung listet in ihrem Manifest sowohl READ_EXTERNAL_STORAGE als auch WRITE_EXTERNAL_STORAGE auf. Die Anwendung fordert READ_EXTERNAL_STORAGE an und der Nutzer gewährt sie. Wenn die App auf API-Level 25 oder niedriger ausgerichtet ist, gewährt das System gleichzeitig WRITE_EXTERNAL_STORAGE, da sie zur selben STORAGE-Berechtigungsgruppe gehört und auch im Manifest registriert ist. Wenn die App auf Android 8.0 (API-Level 26) ausgerichtet ist, gewährt das System zu diesem Zeitpunkt nur READ_EXTERNAL_STORAGE. Wenn die App jedoch später WRITE_EXTERNAL_STORAGE anfordert, gewährt das System diese Berechtigung sofort, ohne den Nutzer zu fragen.

Medien

  • Das Framework kann automatisches Audio-Ducking selbst ausführen. Wenn in diesem Fall eine andere Anwendung den Fokus mit AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK anfordert, verringert die fokussierte Anwendung die Lautstärke, erhält aber normalerweise keinen onAudioFocusChange()-Callback und verliert den Audiofokus nicht. Mit neuen APIs lässt sich dieses Verhalten bei Anwendungen überschreiben, die anstelle von Ducking pausiert werden müssen.
  • Wenn der Nutzer einen Anruf annimmt, werden aktive Medien für die Dauer des Anrufs stummgeschaltet.
  • Alle audiobezogenen APIs sollten AudioAttributes anstelle von Audiostreamtypen verwenden, um den Anwendungsfall für die Audiowiedergabe zu beschreiben. Audiostreamtypen weiterhin nur für die Lautstärkeregelung verwenden. Andere Verwendungen von Streamtypen funktionieren weiterhin (z. B. das streamType-Argument für den verworfenen AudioTrack-Konstruktor), das System protokolliert dies jedoch als Fehler.
  • Wenn die Anwendung bei Verwendung eines AudioTrack einen ausreichend großen Audiozwischenspeicher anfordert, versucht das Framework, die tiefe Zwischenspeicherausgabe zu verwenden, sofern verfügbar.
  • In Android 8.0 (API-Level 26) werden Ereignisse für Medienschaltflächen anders verarbeitet:
    1. Die Verarbeitung von Medienschaltflächen in einer UI-Aktivität bleibt unverändert: Vordergrundaktivitäten haben bei der Verarbeitung von Medienschaltflächenereignissen weiterhin Vorrang.
    2. Wenn die Aktivität im Vordergrund das Medienschaltflächenereignis nicht verarbeitet, leitet das System das Ereignis an die App weiter, die zuletzt Audio lokal wiedergegeben hat. Der aktive Status, die Flags und der Wiedergabestatus einer Mediensitzung werden nicht berücksichtigt, wenn ermittelt wird, welche App Medienschaltflächenereignisse empfängt.
    3. Wenn die Mediensitzung der App veröffentlicht wurde, sendet das System das Medienschaltflächenereignis an MediaButtonReceiver, sofern vorhanden.
    4. In allen anderen Fällen verwirft das System das Medienschaltflächenereignis.

Native Bibliotheken

In Apps, die auf Android 8.0 (API-Level 26) ausgerichtet sind, werden native Bibliotheken nicht mehr geladen, wenn sie Ladesegmente enthalten, die sowohl beschreibbar als auch ausführbar sind. Einige Anwendungen funktionieren aufgrund dieser Änderung möglicherweise nicht mehr, wenn sie native Bibliotheken mit falschen Ladesegmenten haben. Dies ist eine Maßnahme, um die Sicherheit zu erhöhen.

Weitere Informationen finden Sie unter Beschreibbare und ausführbare Segmente.

Änderungen an der Verknüpfung sind an das API-Level gebunden, auf das eine App ausgerichtet ist. Wird eine Verknüpfungsänderung auf Ziel-API-Ebene vorgenommen, kann die Anwendung die Bibliothek nicht laden. Wenn Sie Ihre Anzeigen auf eine API-Ebene ausrichten, die niedriger ist als die API-Ebene, auf der die Verknüpfungsänderung erfolgt, zeigt Logcat eine Warnung an.

Umgang mit Sammlungen

In Android 8.0 (API-Level 26) wird Collections.sort() zusätzlich zu List.sort() implementiert. In Android 7.x (API-Level 24 und 25) galt das umgekehrte Ergebnis: Die Standardimplementierung von List.sort() mit dem Namen Collections.sort().

Durch diese Änderung kann Collections.sort() von optimierten List.sort()-Implementierungen profitieren. Dabei gelten jedoch folgende Einschränkungen:

  • Implementierungen von List.sort() dürfen Collections.sort() nicht aufrufen, da dies zu einem Stacküberlauf aufgrund unendlicher Rekursion führen würde. Wenn Sie das Standardverhalten in Ihrer List-Implementierung verwenden möchten, sollten Sie sort() nicht überschreiben.

    Wenn eine übergeordnete Klasse sort() auf unangemessene Weise implementiert, kann List.sort() in der Regel mit einer Implementierung überschrieben werden, die auf List.toArray(), Arrays.sort() und ListIterator.set() basiert. Beispiele:

    @Override
    public void sort(Comparator<? super E> c) {
      Object[] elements = toArray();
      Arrays.sort(elements, c);
      ListIterator<E> iterator = (ListIterator<Object>) listIterator();
      for (Object element : elements) {
        iterator.next();
        iterator.set((E) element);
      }
    }
    

    In den meisten Fällen kannst du List.sort() auch mit einer Implementierung überschreiben, die je nach API-Ebene an verschiedene Standardimplementierungen delegiert. Beispiele:

    @Override
    public void sort(Comparator<? super E> comparator) {
      if (Build.VERSION.SDK_INT <= 25) {
        Collections.sort(this);
      } else {
        super.sort(comparator);
      }
    }
    

    Wenn Sie Letzteres nur durchführen möchten, um eine sort()-Methode auf allen API-Ebenen verfügbar zu haben, sollten Sie ihr einen eindeutigen Namen wie sortCompat() geben, anstatt sort() zu überschreiben.

  • Collections.sort() gilt jetzt als strukturelle Änderung in Listenimplementierungen, die sort() aufrufen. In Versionen der Plattform vor Android 8.0 (API-Ebene 26) hätte beispielsweise eine Iteration über ein ArrayList und das Aufrufen von sort() innerhalb der Iteration ein ConcurrentModificationException ausgelöst, wenn die Sortierung durch Aufrufen von List.sort() erfolgte. Collections.sort() hat keine Ausnahme ausgelöst.

    Durch diese Änderung wird das Plattformverhalten einheitlicher: Jeder Ansatz führt jetzt zu einem ConcurrentModificationException.

Verhalten beim Laden von Klassen

Android 8.0 (API-Level 26) prüft, ob Klassenlader die Annahmen der Laufzeit beim Laden neuer Klassen nicht durcheinanderbringen. Diese Prüfungen werden durchgeführt, unabhängig davon, ob die Klasse in Java (von forName()), Davik-Bytecode oder JNI referenziert wird. Die Plattform fängt weder direkte Aufrufe von Java an die Methode loadClass() noch die Ergebnisse solcher Aufrufe ab. Dieses Verhalten sollte sich nicht auf die Funktionsweise von gut funktionierenden Klassenladeprogrammen auswirken.

Die Plattform prüft, ob der Deskriptor der Klasse, den das Klassenladeprogramm zurückgibt, mit dem erwarteten Deskriptor übereinstimmt. Wenn der zurückgegebene Deskriptor nicht übereinstimmt, gibt die Plattform den Fehler NoClassDefFoundError aus und speichert in der Ausnahme eine detaillierte Nachricht, in der die Abweichung angegeben ist.

Die Plattform prüft außerdem, ob die Deskriptoren der angeforderten Klassen gültig sind. Mit dieser Prüfung werden JNI-Aufrufe abgefangen, die Klassen wie GetFieldID() indirekt laden und ungültige Deskriptoren an diese Klassen übergeben. Beispielsweise wurde ein Feld mit der Signatur java/lang/String nicht gefunden, weil die Signatur ungültig ist. Sie sollte Ljava/lang/String; lauten.

Dies unterscheidet sich von einem JNI-Aufruf an FindClass(), bei dem java/lang/String ein gültiger, voll qualifizierter Name ist.

Android 8.0 (API-Level 26) unterstützt nicht, dass mehrere Klassenladeprogramme versuchen, Klassen mit demselben DexFile-Objekt zu definieren. Andernfalls gibt die Android-Laufzeit den Fehler InternalError mit der Meldung „Versuch, die Dex-Datei <filename> mit mehreren Klassenladegeräten zu registrieren“ aus.

Die DexFile API wurde eingestellt. Es wird dringend empfohlen, stattdessen einen der Klassenladeprogramme der Plattform zu verwenden, einschließlich PathClassLoader oder BaseDexClassLoader.

Hinweis: Sie können mehrere Klassenladeprogramme erstellen, die auf denselben APK- oder JAR-Dateicontainer aus dem Dateisystem verweisen. Das führt normalerweise nicht zu einem großen Speicheraufwand: Wenn DEX-Dateien im Container gespeichert und nicht komprimiert sind, kann die Plattform einen mmap-Vorgang auf ihnen ausführen, anstatt sie direkt zu extrahieren. Wenn die Plattform jedoch die DEX-Datei aus dem Container extrahieren muss, kann ein Verweis auf eine DEX-Datei auf diese Weise viel Arbeitsspeicher verbrauchen.

Bei Android gelten alle Klassenladeprogramme als parallel-fähig. Wenn mehrere Threads im Rennen um dieselbe Klasse mit demselben Klassenladeprogramm laufen, gewinnt der erste Thread, der den Vorgang abgeschlossen hat. Das Ergebnis wird für die anderen Threads verwendet. Dieses Verhalten ist unabhängig davon, ob das Klassenladeprogramm dieselbe Klasse, eine andere Klasse oder eine Ausnahme zurückgegeben hat. Die Plattform ignoriert solche Ausnahmen automatisch.

Achtung : In Versionen der Plattform vor Android 8.0 (API-Level 26) kann das Fehlen dieser Annahmen dazu führen, dass dieselbe Klasse mehrmals definiert wird, Heap-Beschädigungen aufgrund von Klassenverwirrungen und andere unerwünschte Auswirkungen auftreten.