Verhaltensänderungen unter Android 8.0

Neben neuen Funktionen und Funktionen beinhaltet Android 8.0 (API-Level 26) eine Vielzahl von System- und API-Verhaltensänderungen. In diesem Dokument werden einige der wichtigsten Änderungen beschrieben, die Sie bei Ihren Anwendungen berücksichtigen und verstehen sollten.

Die meisten dieser Änderungen wirken sich auf alle Apps aus, unabhängig davon, auf welche Android-Version sie ausgerichtet sind. Einige Änderungen betreffen jedoch nur Apps, die auf Android 8.0 ausgerichtet sind. Für bessere Übersicht 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, die auf der Plattform Android 8.0 (API-Level 26) ausgeführt werden, unabhängig von der API-Ebene, auf die sie ausgerichtet sind. Alle Entwickler sollten sich diese Änderungen ansehen und ihre Apps entsprechend anpassen, sofern dies für die App zutrifft.

Einschränkungen bei der Hintergrundausführung

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 Status im Cache gespeichert wird und keine aktiven Komponenten hat, gibt das System alle Wakelocks aus, die in der App vorhanden sind.

Zur Verbesserung der Geräteleistung schränkt das System außerdem bestimmte Verhaltensweisen von Apps ein, die nicht im Vordergrund ausgeführt werden. Im Detail:

  • Der Zugriff von Apps, die im Hintergrund ausgeführt werden, auf Hintergrunddienste ist jetzt eingeschränkt.
  • Apps können sich nicht über ihre Manifeste für die meisten impliziten Übertragungen registrieren, d. h. Übertragungen, 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 über den Bildschirm Einstellungen für jede App aktivieren, auch wenn die App nicht auf O ausgerichtet ist.

Android 8.0 (API-Ebene 26) enthält außerdem die folgenden Änderungen an bestimmten Methoden:

  • Die Methode startService() löst jetzt eine IllegalStateException aus, wenn eine App, die auf Android 8.0 ausgerichtet ist, 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. Das System ermöglicht es Apps, Context.startForegroundService() auch dann aufzurufen, wenn die App im Hintergrund ausgeführt wird. Die Anwendung muss jedoch die Methode startForeground() dieses Dienstes innerhalb von fünf Sekunden nach dem Erstellen des Dienstes aufrufen.

Weitere Informationen finden Sie unter Limits für die Ausführung im Hintergrund.

Einschränkungen bei der Standortermittlung im Hintergrund unter Android

Um den Akku zu schonen, die Nutzerfreundlichkeit zu verbessern und die Systemintegrität zu erhalten, erhalten Hintergrund-Apps auf Geräten mit Android 8.0 seltener Standortaktualisierungen. Diese Verhaltensänderung betrifft alle Apps, die Standortupdates erhalten, einschließlich der Google Play-Dienste.

Diese Änderungen betreffen die folgenden APIs:

  • Anbieter für kombinierte Standortbestimmung (Fused Location Provider, FLP)
  • Geofencing
  • GNSS-Messungen
  • Standortmanager
  • WLAN-Manager

Führen Sie die folgenden Schritte aus, damit 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 App das Verhalten aufweist, das Sie für jeden Anwendungsfall erwarten.
  • Für Anwendungsfälle, die vom aktuellen Standort des Nutzers abhängen, kannst du den Anbieter für kombinierte Standortbestimmung oder Geofencing nutzen.

Weitere Informationen zu diesen Änderungen finden Sie unter Einschränkungen für die Standortermittlung im Hintergrund.

App-Verknüpfungen

Android 8.0 (API-Level 26) enthält die folgenden Änderungen an App-Verknüpfungen:

  • Die com.android.launcher.action.INSTALL_SHORTCUT-Ausstrahlung hat keine Auswirkungen mehr auf Ihre App, da es sich jetzt um eine private, implizite Ausstrahlung handelt. Stattdessen sollten Sie eine App-Verknüpfung mit der Methode requestPinShortcut() aus der Klasse ShortcutManager erstellen.
  • Der Intent ACTION_CREATE_SHORTCUT kann jetzt App-Verknüpfungen erstellen, die Sie mithilfe der Klasse ShortcutManager verwalten. Mit diesem Intent können auch alte Launcher-Verknüpfungen erstellt werden, die nicht mit ShortcutManager interagieren. Bisher konnten mit dieser Intent-Art nur alte Launcher-Verknüpfungen erstellt werden.
  • Verknüpfungen, die mit requestPinShortcut() erstellt wurden, und Verknüpfungen, die in einer Aktivität erstellt wurden, die den ACTION_CREATE_SHORTCUT-Intent verarbeitet, sind jetzt vollwertige App-Verknüpfungen. Apps können sie jetzt mit den Methoden in ShortcutManager aktualisieren.
  • Alte Verknüpfungen behalten ihre Funktionen aus früheren Android-Versionen, aber du musst sie in deiner App manuell in App-Verknüpfungen konvertieren.

Weitere Informationen zu den Änderungen an App-Verknüpfungen finden Sie im Hilfeartikel Verknüpfungen und Widgets anpinnen.

Sprachen und Internationalisierung

Mit Android 7.0 (API-Level 24) wurde das Konzept eingeführt, dass ein standardmäßiges Kategoriegebietsschema angegeben werden kann. Einige APIs verwenden jedoch weiterhin die generische Locale.getDefault()-Methode ohne Argumente, obwohl sie stattdessen die Standardeinstellung der Kategorie DISPLAY hätten verwenden sollen. Unter Android 8.0 (API-Ebene 26) wird für die folgenden Methoden jetzt Locale.getDefault(Category.DISPLAY) anstelle von Locale.getDefault() verwendet:

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

Weitere Änderungen im Zusammenhang mit Sprachen und Internationalisierung:

  • Beim Aufrufen von Currency.getDisplayName(null) wird eine NullPointerException geworfen, was dem dokumentierten Verhalten entspricht.
  • Das Parsen des Zeitzonennamens hat sich geändert. Früher haben Android-Geräte den Wert der Systemuhr verwendet, der beim Booten erfasst wurde, um die Zeitzonennamen im Cache zu speichern, die zum Parsen von Datums- und Uhrzeitangaben verwendet wurden. Daher kann das Parsen beeinträchtigt werden, wenn die Systemuhr beim Starten falsch war oder in anderen, selteneren Fällen.

    In den meisten Fällen verwendet die Parselogik beim Parsen von Zeitzonennamen ICU und den Wert der aktuellen Systemuhr. Durch diese Änderung werden genauere Ergebnisse erzielt, die sich von früheren Android-Versionen unterscheiden können, wenn Ihre App Klassen wie SimpleDateFormat verwendet.

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

Benachrichtigungsfenster

Wenn eine App die Berechtigung SYSTEM_ALERT_WINDOW verwendet und versucht, mit einem der folgenden Fenstertypen Benachrichtigungsfenster über anderen Apps und Systemfenstern anzuzeigen:

...werden diese Fenster immer unter den Fenstern angezeigt, für die der Fenstertyp TYPE_APPLICATION_OVERLAY verwendet wird. Wenn eine App auf Android 8.0 (API-Level 26) ausgerichtet ist, verwendet sie den Fenstertyp TYPE_APPLICATION_OVERLAY zum Anzeigen von Benachrichtigungsfenstern.

Weitere Informationen finden Sie im Abschnitt Gängige Fenstertypen für Benachrichtigungsfenster der Verhaltensänderungen für Apps, die auf Android 8.0 ausgerichtet sind.

Eingabe und Navigation

Mit der Einführung von Android-Apps auf ChromeOS und anderen großen Geräten wie Tablets wird die Tastaturnavigation in Android-Apps immer beliebter. In Android 8.0 (API-Level 26) haben wir die Verwendung der Tastatur als Navigationseingabegerät geändert, 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 Sie keine Farben für den Fokusstatus für ein View-Objekt (entweder für den Vordergrund oder den Hintergrund) definiert haben, legt das Framework jetzt eine Standard-Fokus-Hervorhebungsfarbe für das View fest. Dieses Fokus-Highlight ist ein Wellenmuster, das auf dem Thema der Aktivität basiert.

    Wenn Sie nicht möchten, dass ein View-Objekt dieses Standard-Highlight verwendet, wenn es den Fokus erhält, legen Sie in der Layout-XML-Datei mit dem View das Attribut android:defaultFocusHighlightEnabled auf false fest oder geben Sie false in der UI-Logik Ihrer App an setDefaultFocusHighlightEnabled() weiter.

  • Wenn Sie testen möchten, wie sich die Tastatureingabe auf den Fokus von UI-Elementen auswirkt, können Sie die Entwickleroption Zeichnen > Layoutgrenzen anzeigen aktivieren. Unter Android 8.0 wird bei dieser Option über dem Element, das derzeit den Fokus hat, ein „X“-Symbol angezeigt.

Außerdem sind alle Symbolleistenelemente in Android 8.0 automatisch Tastaturnavigationscluster, was die Navigation in und aus den einzelnen Symbolleisten insgesamt erleichtert.

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

Autofill für Webformulare

Da das Autofill-Framework von Android jetzt eine integrierte Unterstützung für die Autofill-Funktion bietet, haben sich die folgenden Methoden im Zusammenhang mit WebView-Objekten für Apps geändert, die auf Geräten mit Android 8.0 (API-Ebene 26) installiert sind:

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

Bedienungshilfen

Android 8.0 (API-Level 26) enthält die folgenden Änderungen an der Barrierefreiheit:

  • Das Framework für Barrierefreiheit wandelt jetzt alle Doppeltippen in ACTION_CLICK-Aktionen um. Dadurch verhält sich TalkBack ähnlich wie andere Bedienungshilfen.

    Wenn für die View-Objekte Ihrer App eine benutzerdefinierte Touchbedienung verwendet wird, sollten Sie prüfen, ob sie weiterhin mit TalkBack funktionieren. Möglicherweise müssen Sie nur den Klick-Handler registrieren, der von Ihren View-Objekten verwendet wird. Wenn TalkBack die an diesen View-Objekten ausgeführten Touch-Gesten immer noch nicht erkennt, überschreiben Sie performAccessibilityAction().

  • Dienste zur Barrierefreiheit erkennen jetzt alle ClickableSpan-Instanzen in den TextView-Objekten Ihrer App.

Weitere Informationen zur Verbesserung der Barrierefreiheit Ihrer App finden Sie unter Bedienungshilfen.

Netzwerke und HTTP(S)-Konnektivität

Android 8.0 (API-Level 26) enthält die folgenden Verhaltensänderungen bei Netzwerk- und HTTP(S)-Verbindungen:

  • OPTIONS-Anfragen ohne Textkörper haben einen Content-Length: 0-Header. Bisher gab es keinen Content-Length-Header.
  • HttpURLConnection normalisiert URLs mit leeren Pfaden, indem nach dem Host- oder Autoritätsnamen ein Schrägstrich angehängt wird. Beispielsweise wird http://example.com in http://example.com/ konvertiert.
  • Eine benutzerdefinierte Proxy-Auswahl, die über ProxySelector.setDefault() festgelegt wird, richtet sich nur an die Adresse (Schema, Host und Port) einer angeforderten URL. Daher basiert die Proxy-Auswahl möglicherweise nur auf diesen Werten. Eine URL, die an einen benutzerdefinierten Proxy-Selektor übergeben wird, enthält weder den Pfad noch die Abfrageparameter oder Fragmente der angeforderten URL.
  • URIs dürfen keine leeren Labels enthalten.

    Bisher unterstützte die Plattform eine Umgehung, um leere Labels in Hostnamen zuzulassen, was eine unzulässige Verwendung von URIs darstellt. Diese Umgehung diente der Kompatibilität mit älteren libcore-Releases. Wenn Entwickler die API falsch verwenden, wird eine ADB-Nachricht angezeigt: „Der URI beispiel.de hat leere Labels im Hostnamen. Dieser ist fehlerhaft und wird in zukünftigen Android-Releases nicht akzeptiert.“ Diese Umgehung ist in Android 8.0 nicht mehr möglich. Das System gibt für fehlerhafte URIs den Wert „null“ zurück.

  • Die Implementierung von HttpsURLConnection in Android 8.0 führt kein Fallback auf eine unsichere Version des TLS/SSL-Protokolls durch.
  • Die Verarbeitung von Tunneling-HTTP(S)-Verbindungen wurde wie folgt geändert:
    • Beim Tunneling einer HTTPS-Verbindung über eine Verbindung fügt das System die Portnummer (:443) korrekt in die Host-Zeile ein, wenn diese Informationen an einen zwischengeschalteten Server gesendet werden. Bisher wurde die Portnummer nur in der CONNECT-Zeile angegeben.
    • Das System sendet keine User-Agent- und Proxy-Autorisierungsheader mehr aus einer getunnelten Anfrage an den Proxyserver.

      Das System sendet beim Einrichten des Tunnels keinen Proxy-Autorisierungsheader mehr für eine getunnelte Http(s)URLConnection an den Proxy. Stattdessen generiert das System einen Proxy-Autorisierungs-Header und sendet ihn an den Proxy, wenn dieser als Antwort auf die ursprüngliche Anfrage HTTP 407 sendet.

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

  • Die Methode send(java.net.DatagramPacket) wirft eine SocketException, wenn die zuvor ausgeführte connect()-Methode fehlgeschlagen ist.
    • DatagramSocket.connect() setzt eine pendingSocketException, wenn ein interner Fehler auftritt. Vor Android 8.0 wurde bei einem nachfolgenden recv()-Aufruf eine SocketException geworfen, auch wenn ein send()-Aufruf erfolgreich gewesen wäre. Aus Gründen der Einheitlichkeit wird bei beiden Aufrufen jetzt eine SocketException geworfen.
  • InetAddress.isReachable() versucht, ICMP zu verwenden, bevor es zum TCP-Echo-Protokoll zurückkehrt.
    • Einige Hosts, die Port 7 (TCP-Echo) blockieren, z. B. google.com, sind jetzt möglicherweise erreichbar, wenn sie das ICMP-Echo-Protokoll akzeptieren.
    • Bei wirklich nicht erreichbaren Hosts bedeutet diese Änderung, dass doppelt so viel Zeit vergeht, bis der Aufruf zurückgegeben wird.

Bluetooth

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

  • Die Methode getBytes() macht keine Annahmen in Bezug auf die Anzahl der empfangenen Byte. Daher sollten Anwendungen nicht von einer Mindest- oder Höchstanzahl zurückgegebener Byte abhängig sein. Stattdessen sollte die Länge des resultierenden Arrays ausgewertet werden.
  • Bluetooth 5-kompatible Geräte können eine Datenlänge zurückgeben, die über dem bisherigen Maximum von etwa 60 Byte liegt.
  • 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 zu vereinfachen, das die beste Nutzererfahrung bietet. Zu den Änderungen gehören:

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

Sicherheit

Android 8.0 enthält die folgenden sicherheitsrelevanten Änderungen:

  • SSLv3 wird von dieser Plattform nicht mehr unterstützt.
  • Beim Herstellen einer HTTPS-Verbindung zu einem Server, der die TLS-Protokollversion falsch implementiert, versucht HttpsURLConnection nicht mehr, auf frühere TLS-Protokollversionen umzustellen und es noch einmal zu versuchen.
  • Unter Android 8.0 (API-Ebene 26) wird ein SECCOMP-Filter (Secure Computing) auf alle Apps angewendet. Die Liste der zulässigen Syscalls ist auf die durch Bioonic bereitgestellten beschränkt. Es gibt zwar mehrere andere Systemaufrufe zur Abwärtskompatibilität, wir empfehlen jedoch, diese nicht zu verwenden.
  • Die WebView-Objekte Ihrer App werden jetzt im Mehrprozessmodus ausgeführt. Webinhalte werden in einem separaten, vom Prozess der App getrennten Prozess verarbeitet, um die Sicherheit zu erhöhen.
  • 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 nicht direkt das Verzeichnisformat verwenden.
  • Informationen zu Sicherheitsverbesserungen im Zusammenhang mit der Verwendung nativer Bibliotheken finden Sie unter Native Bibliotheken.

Außerdem werden mit Android 8.0 (API-Ebene 26) die folgenden Änderungen in Bezug auf die Installation unbekannter Apps aus unbekannten Quellen eingeführt:

Weitere Informationen zur Installation unbekannter Apps finden Sie im Leitfaden Berechtigungen zur Installation unbekannter Apps.

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

Datenschutz

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

  • Die Plattform behandelt Kennungen jetzt anders.
    • Bei Apps, die vor einem Over-the-air-Update auf eine Version von Android 8.0 (API-Level 26) installiert wurden, bleibt der Wert von ANDROID_ID unverändert, es sei denn, die App wird nach dem Over-the-air-Update deinstalliert und dann wieder installiert. Damit die Werte auch bei Deinstallationen nach dem Over-the-air-Update beibehalten werden, können Entwickler die alten und neuen Werte mithilfe der Schlüssel-/Wert-Sicherung verknüpfen.
    • Für Apps, die auf Geräten mit Android 8.0 installiert sind, wird der Wert von ANDROID_ID jetzt pro App-Signaturschlüssel und Nutzer festgelegt. Der Wert von ANDROID_ID ist für jede Kombination aus App-Signaturschlüssel, Nutzer und Gerät eindeutig. Daher sehen Apps mit unterschiedlichen Signaturschlüsseln, die auf demselben Gerät ausgeführt werden, nicht mehr dieselbe Android-ID (auch nicht für denselben Nutzer).
    • Der Wert von ANDROID_ID ändert sich bei der Deinstallation oder Neuinstallation des Pakets nicht, solange der Signaturschlüssel derselbe ist (und die App nicht vor einem OTA-Update für eine Version von Android 8.0 installiert wurde).
    • Der Wert von ANDROID_ID ändert sich nicht, auch wenn sich der Schlüssel für die Paketsignatur durch ein Systemupdate ändert.
    • Auf Geräten, die mit Google Play-Diensten und der Werbe-ID ausgeliefert werden, müssen Sie die Werbe-ID verwenden. Ein einfaches, standardmäßiges System zur Monetarisierung von Apps. Die Werbe-ID ist eine eindeutige ID für Werbezwecke, die vom Nutzer zurückgesetzt werden kann. Sie wird von den Google Play-Diensten bereitgestellt.

      Andere Gerätehersteller sollten ANDROID_ID weiterhin anbieten.

  • Die Abfrage der Systemeigenschaft net.hostname ergibt ein Nullergebnis.

Protokollierung nicht abgefangener Ausnahmen

Wenn eine App eine Thread.UncaughtExceptionHandler installiert, die nicht den Standard-Thread.UncaughtExceptionHandler aufruft, wird die App vom System nicht beendet, wenn eine nicht abgefangene Ausnahme auftritt. Ab Android 8.0 (API-Level 26) protokolliert das System in dieser Situation den Stacktrace der Ausnahme. In früheren Versionen der Plattform wurde der Stacktrace der Ausnahme 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.

Änderung der Signatur von findViewById()

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 nun einen mehrdeutigen Rückgabetyp hat, z. B. wenn sowohl someMethod(View) als auch someMethod(TextView) vorhanden sind, das das Ergebnis eines Aufrufs von findViewById() annimmt.
  • Bei Verwendung der Java 8-Quellsprache ist ein expliziter Cast zu View erforderlich, wenn der Rückgabetyp nicht eingeschränkt ist (z. B. assertNotNull(findViewById(...)).someViewMethod())).
  • Bei Überschreibungen nicht abschließender 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 mithilfe der Komponente „Kontakteanbieter“ Nutzungsdaten für jeden Kontakt abrufen. Diese Nutzungsdaten enthalten Informationen zu jeder E-Mail-Adresse und Telefonnummer, die mit einem Kontakt verknüpft sind, einschließlich der Häufigkeit, mit der der Kontakt kontaktiert wurde, und des letzten Kontakts. 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-Ebene 26) und höher werden bei Abfragen von Nutzungsdaten keine genauen Werte, sondern Näherungswerte zurückgegeben. Die genauen Werte werden intern im Android-System verwaltet. Diese Änderung hat daher keine Auswirkungen auf die Autocomplete API.

Diese Verhaltensänderung betrifft die folgenden Abfrageparameter:

Umgang mit Datenerhebung

AbstractCollection.removeAll() und AbstractCollection.retainAll() werfen jetzt immer eine NullPointerException; zuvor wurde die NullPointerException nicht geworfen, wenn die Sammlung leer war. Durch diese Änderung entspricht das Verhalten der Dokumentation.

Android Enterprise

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

  • Neue Verhaltensweisen, damit Apps Arbeitsprofile auf vollständig verwalteten Geräten unterstützen.
  • Änderungen an der Verarbeitung von Systemupdates, der App-Überprüfung und der Authentifizierung, um die Geräte- und Systemintegrität zu erhöhen.
  • Verbesserungen bei der Nutzerfreundlichkeit bei Bereitstellung, Benachrichtigungen, dem Bildschirm „Letzte“ und dem Always-on-VPN.

Alle Änderungen für Unternehmen in Android 8.0 (API-Ebene 26) und ihre Auswirkungen auf Ihre App finden Sie unter Android in Unternehmen.

Apps für Android 8.0

Diese Verhaltensänderungen gelten ausschließlich für Apps, die auf Android 8.0 (API-Level 26) oder höher ausgerichtet sind. Entwickler von Apps, die für Android 8.0 kompiliert werden oder für die targetSdkVersion auf Android 8.0 oder höher festgelegt ist, müssen ihre Apps entsprechend anpassen, sofern dies für die App zutrifft.

Benachrichtigungsfenster

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

Stattdessen müssen Apps einen neuen Fenstertyp namens TYPE_APPLICATION_OVERLAY verwenden.

Wenn Sie den Fenstertyp TYPE_APPLICATION_OVERLAY verwenden, um Benachrichtigungsfenster für Ihre App anzuzeigen, beachten Sie die folgenden Eigenschaften des neuen Fenstertyps:

  • Die Benachrichtigungsfenster einer App werden immer unter wichtigen Systemfenstern wie der Statusleiste und der Eingabemethode angezeigt.
  • Das System kann Fenster, die den Fenstertyp TYPE_APPLICATION_OVERLAY verwenden, verschieben oder deren Größe anpassen, um die Bildschirmdarstellung zu verbessern.
  • Wenn Nutzer die Benachrichtigungsleiste öffnen, können sie die Einstellungen aufrufen, um zu verhindern, dass eine App Warnfenster mit dem Fenstertyp TYPE_APPLICATION_OVERLAY anzeigt.

Benachrichtigungen zu Inhaltsänderungen

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

Für diese APIs muss jetzt in allen URIs ein gültiger ContentProvider für die Zertifizierungsstelle definiert sein. Wenn Sie eine gültige ContentProvider mit den entsprechenden Berechtigungen definieren, können Sie Ihre App besser vor Inhaltsänderungen durch schädliche Apps schützen und verhindern, dass potenziell vertrauliche Daten an schädliche Apps weitergegeben werden.

Fokus ansehen

Klickbare View-Objekte sind jetzt standardmäßig fokussierbar. Wenn ein View-Objekt anklickbar, aber nicht fokussierbar sein soll, legen Sie das android:focusable-Attribut in der Layout-XML-Datei, die View enthält, auf false fest oder übergeben Sie false in der UI-Logik Ihrer App an 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 Browsererkennung einen anderen Browser als Opera identifiziert. Hier ist ein Beispiel für eine solche Musterübereinstimmung:

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

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

Sicherheit

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

  • Wenn die Netzwerksicherheitskonfiguration Ihrer Anwendung die Unterstützung von Klartext-Traffic deaktiviert, können die WebView-Objekte Ihrer App nicht über HTTP auf Websites zugreifen. Stattdessen muss für jedes WebView-Objekt HTTPS verwendet werden.
  • Die Systemeinstellung Unbekannte Quellen zulassen wurde entfernt. Stattdessen wird die Installation unbekannter Apps aus unbekannten Quellen jetzt über die Berechtigung Unbekannte Apps installieren verwaltet. Weitere Informationen zu dieser neuen Berechtigung finden Sie im Leitfaden Berechtigungen zum Installieren unbekannter Apps.

Weitere Richtlinien zur Erhöhung der Sicherheit deiner App findest du unter Sicherheit für Android-Entwickler.

Kontozugriff und Sichtbarkeit

In Android 8.0 (API-Level 26) können Apps nur dann auf Nutzerkonten zugreifen, wenn der Authenticator der Inhaber der Konten ist oder der Nutzer den Zugriff gewährt. Die Berechtigung GET_ACCOUNTS reicht nicht mehr aus. Damit Apps Zugriff auf ein Konto erhalten, müssen 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. Apps sollten stattdessen addOnAccountsUpdatedListener() verwenden, um während der Laufzeit Aktualisierungen zu Konten zu erhalten.

Informationen zu den neuen APIs und Methoden für den Kontozugriff und die Sichtbarkeit finden Sie im Abschnitt Neue APIs unter Kontozugriff und Sichtbarkeit.

Datenschutz

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

  • Die Systemeigenschaften net.dns1, net.dns2, net.dns3 und net.dns4 sind nicht mehr verfügbar. Durch diese Änderung wird der Datenschutz auf der Plattform verbessert.
  • Um Netzwerkinformationen wie DNS-Server abzurufen, 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 Hardware-Seriennummer benötigen, sollten stattdessen die neue Methode Build.getSerial() verwenden, für die die Berechtigung READ_PHONE_STATE erforderlich ist.
  • Über die LauncherApps API können Apps in Arbeitsprofilen keine Informationen mehr über das Hauptprofil abrufen. Wenn sich ein Nutzer in einem Arbeitsprofil befindet, verhält sich die LauncherApps API so, als wären keine Anwendungen in anderen Profilen innerhalb derselben Profilgruppe installiert. Wie bisher führen Versuche, auf nicht zueinander gehörende Profile zuzugreifen, zu SecurityExceptions.

Berechtigungen

Vor Android 8.0 (API-Ebene 26) wurde einer App, die zur Laufzeit eine Berechtigung anforderte und die Berechtigung auch erhielt, fälschlicherweise auch der Rest der Berechtigungen erteilt, die zu derselben Berechtigungsgruppe gehörten und im Manifest registriert waren.

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

Beispiel: Eine App listet in ihrem Manifest sowohl READ_EXTERNAL_STORAGE als auch WRITE_EXTERNAL_STORAGE auf. Die App 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 auch WRITE_EXTERNAL_STORAGE, da die App 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 dass der Nutzer dazu aufgefordert wird.

Medien

  • Das Framework kann automatische Audio-Ducking-Funktionen selbst ausführen. Wenn in diesem Fall eine andere Anwendung den Fokus mit AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK anfordert, reduziert die App, die den Fokus hat, ihre Lautstärke, erhält aber in der Regel keinen onAudioFocusChange()-Callback und verliert den Audiofokus nicht. Es gibt neue APIs, mit denen dieses Verhalten für Anwendungen überschrieben werden kann, die angehalten werden müssen, anstatt leiser gestellt zu werden.
  • Wenn der Nutzer einen Anruf annimmt, werden aktive Medienstreams für die Dauer des Anrufs stummgeschaltet.
  • In allen audiobezogenen APIs sollte AudioAttributes anstelle von Audiostreamtypen verwendet werden, um den Anwendungsfall der Audiowiedergabe zu beschreiben. Audiostreamtypen sollten nur noch für die Lautstärkeregelung verwendet werden. Andere Verwendungen von Streamtypen funktionieren weiterhin (z. B. das streamType-Argument für den veralteten Konstruktor AudioTrack), werden aber vom System als Fehler protokolliert.
  • Wenn die Anwendung bei Verwendung eines AudioTrack einen ausreichend großen Audiopuffer anfordert, versucht das Framework, die Tiefenpufferausgabe zu verwenden, sofern diese verfügbar ist.
  • Unter Android 8.0 (API-Ebene 26) werden Ereignisse von Medienschaltflächen anders verarbeitet:
    1. Die Verarbeitung von Medienschaltflächen in einer UI-Aktivität hat sich nicht geändert: Aktivitäten im Vordergrund haben weiterhin Vorrang bei der Verarbeitung von Ereignissen von Medienschaltflächen.
    2. Wenn die Aktivität im Vordergrund das Ereignis der Medientaste nicht verarbeitet, leitet das System das Ereignis an die App weiter, die zuletzt lokal Audio abgespielt hat. Der aktive Status, Flags und der Wiedergabestatus einer Mediensitzung werden nicht berücksichtigt, wenn ermittelt wird, welche App Medienschalter-Ereignisse empfängt.
    3. Wenn die Mediensitzung der App freigegeben wurde, sendet das System das Medienschalter-Ereignis an die MediaButtonReceiver der App, falls vorhanden.
    4. In allen anderen Fällen verwirft das System das Ereignis der Medientaste.

Native Bibliotheken

In Apps, die auf Android 8.0 (API-Ebene 26) ausgerichtet sind, werden native Bibliotheken nicht mehr geladen, wenn sie ein Ladesegment enthalten, das sowohl beschreibbar als auch ausführbar ist. Einige Apps funktionieren aufgrund dieser Änderung möglicherweise nicht mehr, wenn sie native Bibliotheken mit falschen Ladesegmenten haben. Dies ist eine Maßnahme zur Erhöhung der Sicherheit.

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

Linkeränderungen sind an die API-Ebene gebunden, auf die eine App ausgerichtet ist. Wenn sich der Linker auf der Ziel-API-Ebene ändert, kann die App die Bibliothek nicht laden. Wenn Sie eine API-Ebene ansteuern, die niedriger ist als die API-Ebene, auf der die Linkeränderung auftritt, wird in logcat eine Warnung angezeigt.

Umgang mit Datenerhebung

Unter Android 8.0 (API-Ebene 26) wird Collections.sort() über List.sort() implementiert. In Android 7.x (API-Ebenen 24 und 25) war das Gegenteil der Fall: Die Standardimplementierung von List.sort() hieß Collections.sort().

Durch diese Änderung kann Collections.sort() von optimierten List.sort()-Implementierungen profitieren. Es gelten jedoch die folgenden 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 stattdessen das Standardverhalten in Ihrer List-Implementierung verwenden möchten, sollten Sie sort() nicht überschreiben.

    Wenn eine übergeordnete Klasse sort() nicht ordnungsgemäß implementiert, ist es in der Regel in Ordnung, List.sort() mit einer Implementierung zu überschreiben, die auf List.toArray(), Arrays.sort() und ListIterator.set() basiert. Beispiel:

    @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 können Sie List.sort() auch mit einer Implementierung überschreiben, die je nach API-Ebene an verschiedene Standardimplementierungen delegiert. Beispiel:

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

    Wenn Sie das nur tun, weil Sie eine sort()-Methode auf allen API-Ebenen verfügbar haben möchten, 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-Level 26) würde beispielsweise bei der Iteration über eine ArrayList und dem Aufruf von sort() in der Mitte der Iteration eine ConcurrentModificationException geworfen werden, wenn die Sortierung durch Aufrufen von List.sort() erfolgt. Collections.sort() hat keine Ausnahme ausgelöst.

    Durch diese Änderung wird das Plattformverhalten einheitlicher: Beide Ansätze führen jetzt zu einem ConcurrentModificationException.

Verhalten beim Laden von Klassen

Unter Android 8.0 (API-Ebene 26) wird geprüft, ob die Klassenlader beim Laden neuer Klassen die Annahmen der Laufzeit nicht verletzen. Diese Prüfungen werden durchgeführt, unabhängig davon, ob auf die Klasse aus Java (forName()), aus Dalvik-Bytecode oder aus JNI verwiesen wird. Die Plattform fängt keine direkten Aufrufe von Java an die Methode loadClass() ab und prüft auch nicht die Ergebnisse solcher Aufrufe. Dieses Verhalten sollte sich nicht auf die Funktionsweise ordnungsgemäßer Class Loader auswirken.

Die Plattform prüft, ob der Descriptor der Klasse, den der Klassenloader zurückgibt, mit dem erwarteten Descriptor übereinstimmt. Wenn der zurückgegebene Descriptor nicht übereinstimmt, löst die Plattform einen NoClassDefFoundError-Fehler aus und speichert in der Ausnahme eine detaillierte Meldung, in der die Abweichung angegeben wird.

Außerdem wird geprüft, ob die Beschreibungen der angeforderten Klassen gültig sind. Diese Prüfung fängt JNI-Aufrufe ab, die Klassen wie GetFieldID() indirekt laden und diesen Klassen ungültige Descriptor übergeben. Ein Feld mit der Signatur java/lang/String wird beispielsweise nicht gefunden, weil diese Signatur ungültig ist. Sie muss Ljava/lang/String; sein.

Dies unterscheidet sich von einem JNI-Aufruf von FindClass(), wobei java/lang/String ein gültiger vollständig qualifizierter Name ist.

Android 8.0 (API-Level 26) unterstützt nicht, dass mehrere Klassenlader versuchen, Klassen mit demselben DexFile-Objekt zu definieren. Bei einem solchen Versuch löst die Android-Laufzeit einen InternalError-Fehler mit der Meldung „Attempt to register dex file <filename> with multiple class loaders“ (Versuch, die Dex-Datei <filename> mit mehreren Klassenladern zu registrieren) aus.

Die DexFile API ist jetzt eingestellt. Wir empfehlen Ihnen dringend, stattdessen einen der Plattform-Klassenloader wie PathClassLoader oder BaseDexClassLoader zu verwenden.

Hinweis : Sie können mehrere Klassenlader 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 statt komprimiert werden, 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 das Verweisen auf eine DEX-Datei auf diese Weise viel Arbeitsspeicher belegen.

Unter Android gelten alle Klassenlader als parallelfähig. Wenn mehrere Threads versuchen, dieselbe Klasse mit demselben Classloader zu laden, gewinnt der erste Thread, der den Vorgang abschließt, und das Ergebnis wird für die anderen Threads verwendet. Dieses Verhalten tritt unabhängig davon auf, ob das Klassenladeprogramm dieselbe Klasse, eine andere Klasse oder eine Ausnahme zurückgegeben hat. Solche Ausnahmen werden von der Plattform ignoriert.

Achtung : Bei Versionen der Plattform, die niedriger als Android 8.0 (API-Level 26) sind, kann das Brechen dieser Annahmen dazu führen, dass dieselbe Klasse mehrmals definiert wird, dass der Heap aufgrund von Klassenverwirrung beschädigt wird und dass es zu anderen unerwünschten Auswirkungen kommt.