Verhaltensänderungen unter Android 7.0

Neben neuen Funktionen und Möglichkeiten beinhaltet Android 7.0 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.

Wenn du bereits eine App für Android veröffentlicht hast, solltest du beachten, dass deine App von diesen Änderungen auf der Plattform betroffen sein könnte.

Akku und Speicher

Unter Android 7.0 wurden Änderungen am Systemverhalten vorgenommen, um die Akkulaufzeit von Geräten zu verbessern und die RAM-Nutzung zu reduzieren. Diese Änderungen können sich auf den Zugriff Ihrer App auf Systemressourcen sowie auf die Interaktion der App mit anderen Apps über bestimmte implizite Intents auswirken.

Stromsparmodus

Der in Android 6.0 (API-Level 23) eingeführte Stromsparmodus verbessert die Akkulaufzeit, da CPU- und Netzwerkaktivitäten aufgeschoben werden, wenn ein Gerät nicht angeschlossen ist, sich nicht bewegt und der Bildschirm ausgeschaltet ist. Unter Android 7.0 werden weitere Verbesserungen am Stromsparmodus vorgenommen. Dabei werden einige CPU- und Netzwerkbeschränkungen angewendet, während das Gerät bei ausgeschaltetem Display bei ausgeschaltetem Display, bei ausgeschaltetem Display jedoch nicht unbedingt deaktiviert wird.

Darstellung, wie der Stromsparmodus eine erste Ebene von Einschränkungen der Systemaktivität anwendet, um die Akkulaufzeit zu verbessern

Abbildung 1: Abbildung, wie der Stromsparmodus eine erste Ebene von Einschränkungen der Systemaktivität anwendet, um die Akkulaufzeit zu verlängern.

Wenn ein Gerät im Akkubetrieb ist und der Bildschirm für eine bestimmte Zeit ausgeschaltet war, wechselt es in den Stromsparmodus und wendet den ersten Teil der Einschränkungen an: Der Zugriff auf das App-Netzwerk wird beendet und Jobs und Synchronisierungen werden ausgesetzt. Wenn das Gerät nach dem Eintreten des Stromsparmodus eine bestimmte Zeit lang nicht bewegt wurde, wendet das System die restlichen Einschränkungen des Stromsparmodus auf PowerManager.WakeLock, AlarmManager-Alarme sowie GPS- und WLAN-Scans an. Unabhängig davon, ob einige oder alle Einschränkungen des Stromsparmodus angewendet werden, aktiviert das System das Gerät für kurze Wartungsfenster, in denen Anwendungen Netzwerkzugriff gestattet und verzögerte Jobs/Synchronisierungen ausgeführt werden können.

Darstellung, wie der Stromsparmodus eine zweite Ebene von Einschränkungen der Systemaktivität anwendet, nachdem das Gerät für eine bestimmte Zeit still stand

Abbildung 2: Darstellung, wie der Stromsparmodus eine zweite Ebene von Einschränkungen der Systemaktivität anwendet, nachdem das Gerät für eine bestimmte Zeit still stand.

Wenn Sie den Bildschirm aktivieren oder das Gerät anschließen, wird der Stromsparmodus beendet und diese Verarbeitungsbeschränkungen werden aufgehoben. Das zusätzliche Verhalten hat keine Auswirkungen auf Empfehlungen und Best Practices zur Anpassung deiner App an die vorherige Version des in Android 6.0 (API-Level 23) eingeführten Stromsparmodus, wie unter Optimierung für Stromsparmodus und App-Standby beschrieben. Sie sollten dennoch diese Empfehlungen befolgen, z. B. Firebase Cloud Messaging (FCM) zum Senden und Empfangen von Nachrichten verwenden, und mit der Planung von Updates beginnen, um das zusätzliche Verhalten des Stromsparmodus zu berücksichtigen.

Project Svelte: Hintergrundoptimierungen

Unter Android 7.0 werden drei implizite Broadcasts entfernt, um sowohl die Speicher- als auch den Stromverbrauch zu optimieren. Diese Änderung ist erforderlich, da implizite Broadcasts häufig Apps starten, die für deren Überwachung im Hintergrund registriert sind. Das Entfernen dieser Broadcasts kann die Geräteleistung und die Nutzerfreundlichkeit erheblich verbessern.

Bei Mobilgeräten kommt es häufig zu Konnektivitätsänderungen, z. B. wenn zwischen WLAN und mobilen Daten gewechselt wird. Derzeit können Apps auf Konnektivitätsänderungen achten, indem sie in ihrem Manifest einen Empfänger für den impliziten Broadcast CONNECTIVITY_ACTION registrieren. Da viele Apps für den Empfang dieser Übertragung registriert sind, kann ein einzelner Netzwerk-Switch dazu führen, dass sie alle gleichzeitig aktiviert und die Übertragung verarbeitet werden.

In früheren Android-Versionen konnten Apps sich so registrieren, dass sie implizite ACTION_NEW_PICTURE- und ACTION_NEW_VIDEO-Broadcasts von anderen Apps wie der Kamera empfangen konnten. Wenn ein Nutzer ein Bild mit der Kamera App aufnimmt, werden diese Apps aktiviert, um die Übertragung zu verarbeiten.

Um diese Probleme zu beheben, wendet Android 7.0 die folgenden Optimierungen an:

Wenn deine App einen dieser Intents verwendet, solltest du die entsprechenden Abhängigkeiten so schnell wie möglich entfernen, damit das Targeting auf Android 7.0-Geräte ordnungsgemäß funktioniert. Das Android-Framework bietet verschiedene Lösungen, um die Notwendigkeit dieser impliziten Broadcasts zu verringern. Die JobScheduler API bietet beispielsweise einen robusten Mechanismus zur Planung von Netzwerkvorgängen, wenn bestimmte Bedingungen, z. B. die Verbindung zu einem kostenlosen Netzwerk, erfüllt sind. Du kannst sogar JobScheduler verwenden, um auf Änderungen von Contentanbietern zu reagieren.

Weitere Informationen zu Hintergrundoptimierungen unter Android 7.0 (API-Level 24) und zur Anpassung deiner App findest du unter Hintergrundoptimierungen.

Änderungen der Berechtigungen

Unter Android 7.0 wurden Berechtigungen geändert, die sich möglicherweise auf deine App auswirken.

Änderungen der Berechtigungen für das Dateisystem

Um die Sicherheit privater Dateien zu verbessern, hat das private Verzeichnis von Apps, die auf Android 7.0 oder höher ausgerichtet sind, einen eingeschränkten Zugriff (0700). Mit dieser Einstellung wird verhindert, dass Metadaten privater Dateien weitergegeben werden, z. B. deren Größe oder Vorhandensein. Diese Änderung der Berechtigung hat mehrere Auswirkungen:

Dateien zwischen Apps teilen

Für Apps, die auf Android 7.0 ausgerichtet sind, erzwingt das Android-Framework die API-Richtlinie StrictMode, die verhindert, dass file://-URIs außerhalb Ihrer App verfügbar gemacht werden. Wenn ein Intent mit einem Datei-URI Ihre App verlässt, schlägt die App mit der Ausnahme FileUriExposedException fehl.

Wenn Sie Dateien zwischen Anwendungen freigeben möchten, senden Sie einen content://-URI und gewähren Sie eine temporäre Zugriffsberechtigung für den URI. Am einfachsten können Sie diese Berechtigung mithilfe der Klasse FileProvider erteilen. Weitere Informationen zu Berechtigungen und Freigabe von Dateien finden Sie unter Dateien freigeben.

Verbesserte Bedienungshilfen

Android 7.0 enthält Änderungen, die die Nutzerfreundlichkeit der Plattform für Nutzer mit eingeschränktem oder eingeschränktem Sehvermögen verbessern sollen. Diese Änderungen sollten in der Regel keine Codeänderungen in deiner App erfordern. Du solltest diese Funktion jedoch prüfen und mit deiner App testen, um mögliche Auswirkungen auf die Nutzerfreundlichkeit zu beurteilen.

Bildschirmzoom

Unter Android 7.0 können Nutzer die Anzeigegröße festlegen. Dadurch werden alle Elemente auf dem Bildschirm vergrößert oder verkleinert und so die Barrierefreiheit der Geräte für Nutzer mit eingeschränktem Sehvermögen verbessert. Nutzer können den Bildschirm nicht über eine Mindestbildschirmbreite von sw320dp hinaus vergrößern. Das ist die Breite eines Nexus 4, eines gängigen mittelgroßen Smartphones.

Bildschirm mit nicht gezoomter Anzeige eines Geräts mit einem Systembild von Android 7.0
Bildschirm, auf dem die Größe eines Geräts mit einem Systembild von Android 7.0 zu sehen ist

Abbildung 3: Auf dem rechten Bildschirm ist zu sehen, wie sich die Anzeige eines Geräts mit einem System-Image von Android 7.0 erhöht.

Wenn sich die Gerätedichte ändert, benachrichtigt das System laufende Apps folgendermaßen:

  • Ist eine App auf API-Level 23 oder niedriger ausgerichtet, beendet das System automatisch alle zugehörigen Hintergrundprozesse. Wenn ein Nutzer also von einer solchen App wegschaltet, um den Bildschirm Einstellungen zu öffnen, und die Einstellung Anzeigegröße ändert, beendet das System die App auf dieselbe Weise wie bei einer Situation mit wenig Arbeitsspeicher. Wenn die App Prozesse im Vordergrund hat, benachrichtigt das System diese Prozesse über die Konfigurationsänderung, wie unter Laufzeitänderungen verarbeiten beschrieben, so als ob sich die Ausrichtung des Geräts geändert hätte.
  • Wenn eine App auf Android 7.0 ausgerichtet ist, werden alle zugehörigen Prozesse (Vorder- und Hintergrund) wie unter Umgang mit Laufzeitänderungen beschrieben über die Konfigurationsänderung benachrichtigt.

Bei den meisten Apps müssen keine Änderungen vorgenommen werden, um diese Funktion zu unterstützen. Voraussetzung ist, dass die Apps den Best Practices für Android entsprechen. Überprüfen Sie Folgendes:

  • Teste deine App auf einem Gerät mit einer Bildschirmbreite von sw320dp und sorge dafür, dass sie ordnungsgemäß funktioniert.
  • Wenn sich die Gerätekonfiguration ändert, aktualisieren Sie alle dichteabhängigen zwischengespeicherten Informationen wie im Cache gespeicherte Bitmaps oder aus dem Netzwerk geladene Ressourcen. Prüfen Sie, ob Konfigurationsänderungen vorgenommen wurden, wenn die Anwendung im Status „Pausiert“ fortgesetzt wird.

    Hinweis:Wenn konfigurationsabhängige Daten im Cache gespeichert werden, ist es ratsam, relevante Metadaten wie die entsprechende Bildschirmgröße oder Pixeldichte für diese Daten anzugeben. Durch das Speichern dieser Metadaten können Sie entscheiden, ob Sie die im Cache gespeicherten Daten nach einer Konfigurationsänderung aktualisieren müssen.

  • Vermeide es, Abmessungen mit Pixel-Einheiten anzugeben, da diese nicht mit der Bildschirmdichte skaliert werden. Geben Sie Dimensionen stattdessen mit dichteunabhängigen Pixeleinheiten (dp) an.

Einstellungen für Sehbehinderte im Einrichtungsassistenten

Android 7.0 enthält Vision-Einstellungen auf dem Begrüßungsbildschirm, über die Nutzer die folgenden Einstellungen für Bedienungshilfen auf einem neuen Gerät festlegen können: Vergrößerungsbewegung, Schriftgröße, Anzeigegröße und TalkBack. Durch diese Änderung werden Fehler im Zusammenhang mit verschiedenen Bildschirmeinstellungen besser sichtbar. Wenn du die Auswirkungen dieser Funktion beurteilen möchtest, solltest du deine Apps mit diesen Einstellungen testen. Die Einstellungen finden Sie unter Einstellungen > Bedienungshilfen.

NDK-Apps mit Plattformbibliotheken verknüpfen

Ab Android 7.0 verhindert das System, dass Apps dynamisch mit Nicht-NDK-Bibliotheken verknüpft werden, was zum Absturz deiner App führen kann. Diese Verhaltensänderung zielt darauf ab, eine einheitliche App-Erfahrung über Plattformupdates und verschiedene Geräte hinweg zu schaffen. Auch wenn dein Code nicht mit privaten Bibliotheken verknüpft ist, kann es sein, dass die statische Bibliothek eines Drittanbieters in deiner App dies tut. Daher sollten alle Entwickler darauf achten, dass ihre Apps auf Geräten mit Android 7.0 nicht abstürzen. Wenn Ihre App nativen Code verwendet, sollten Sie nur öffentliche NDK APIs nutzen.

Es gibt drei Möglichkeiten, wie Ihre Anwendung auf APIs einer privaten Plattform zugreifen kann:

  • Deine App greift direkt auf private Plattformbibliotheken zu. Sie sollten Ihre App so aktualisieren, dass sie eine eigene Kopie dieser Bibliotheken enthält, oder die öffentlichen NDK APIs verwenden.
  • Ihre App verwendet eine Bibliothek eines Drittanbieters, die auf private Plattformbibliotheken zugreift. Auch wenn Sie sicher sind, dass Ihre Anwendung nicht direkt auf private Bibliotheken zugreift, sollten Sie Ihre App trotzdem für dieses Szenario testen.
  • Ihre App verweist auf eine Bibliothek, die nicht im APK enthalten ist. Ein solches Problem kann beispielsweise auftreten, wenn Sie versucht haben, Ihre eigene Kopie von OpenSSL zu verwenden, aber vergessen haben, sie mit dem APK Ihrer App zu bündeln. Die App wird unter Umständen auf Versionen der Android-Plattform, die libcrypto.so enthalten, normal ausgeführt. Die App könnte jedoch in neueren Android-Versionen abstürzen, die diese Bibliothek nicht enthalten, z. B. Android 6.0 und höher. Um dieses Problem zu beheben, musst du alle Nicht-NDK-Bibliotheken mit deinem APK bündeln.

Apps sollten keine nativen Bibliotheken verwenden, die nicht im NDK enthalten sind, da sie sich je nach Android-Version ändern oder entfernen können. Der Wechsel von OpenSSL zu BoringSSL ist ein Beispiel für eine solche Änderung. Da es keine Kompatibilitätsanforderungen für Plattformbibliotheken gibt, die nicht im NDK enthalten sind, können unterschiedliche Geräte unterschiedliche Kompatibilitätsstufen bieten.

Um die Auswirkungen dieser Einschränkung auf aktuell veröffentlichte Apps zu verringern, ist eine Reihe von Bibliotheken, die häufig verwendet werden (z. B. libandroid_runtime.so, libcutils.so, libcrypto.so und libssl.so), unter Android 7.0 (API-Level 24) vorübergehend für Apps verfügbar, die auf API-Level 23 oder niedriger ausgerichtet sind. Wenn Ihre App eine dieser Bibliotheken lädt, generiert Logcat eine Warnung und auf dem Zielgerät wird ein Toast angezeigt, um Sie zu benachrichtigen. Falls diese Warnungen angezeigt werden, sollten Sie Ihre Anwendung aktualisieren und entweder eine eigene Kopie dieser Bibliotheken hinzufügen oder nur die öffentlichen NDK APIs verwenden. In zukünftigen Releases der Android-Plattform wird die Nutzung privater Bibliotheken unter Umständen vollständig eingeschränkt und deine App könnte abstürzen.

Alle Anwendungen generieren einen Laufzeitfehler, wenn sie eine API aufrufen, die weder öffentlich noch vorübergehend zugänglich ist. Dies führt dazu, dass System.loadLibrary und dlopen(3) beide den Wert NULL zurückgeben, was zum Absturz Ihrer App führen kann. Sie sollten Ihren App-Code überprüfen, um die Nutzung von APIs der privaten Plattform zu entfernen, und Ihre Apps gründlich mit einem Gerät oder Emulator mit Android 7.0 (API-Level 24) testen. Wenn Sie sich nicht sicher sind, ob Ihre Anwendung private Bibliotheken verwendet, können Sie mit logcat den Laufzeitfehler ermitteln.

In der folgenden Tabelle wird das Verhalten einer App in Abhängigkeit von ihrer Verwendung privater nativer Bibliotheken und ihres Ziel-API-Levels (android:targetSdkVersion) beschrieben.

Bibliotheken Ziel-API-Level Laufzeitzugriff über eine dynamische Verknüpfung Verhalten von Android 7.0 (API-Level 24) Zukünftiges Verhalten der Android-Plattform
NDK Public Alle Zugänglich Funktioniert wie erwartet Funktioniert wie erwartet
Privat (vorübergehend zugängliche Privatbibliotheken) 23 oder niedriger Vorübergehend zugänglich Funktioniert wie erwartet, aber Sie erhalten eine Logcat-Warnung. Laufzeitfehler
Privat (vorübergehend zugängliche Privatbibliotheken) 24 oder höher Eingeschränkt Laufzeitfehler Laufzeitfehler
Privat (sonstige) Alle Eingeschränkt Laufzeitfehler Laufzeitfehler

Prüfen, ob in deiner App private Bibliotheken verwendet werden

Damit Sie Probleme beim Laden privater Bibliotheken erkennen können, generiert Logcat möglicherweise eine Warnung oder einen Laufzeitfehler. Wenn deine App beispielsweise auf API-Level 23 oder niedriger ausgerichtet ist und auf einem Gerät mit Android 7.0 versucht, auf eine private Bibliothek zuzugreifen, wird möglicherweise eine Warnung wie die folgende angezeigt:

03-21 17:07:51.502 31234 31234 W linker  : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120

Diese Logcat-Warnungen geben Aufschluss darüber, welche Bibliothek versucht, auf eine API der privaten Plattform zuzugreifen. Sie führen jedoch nicht zum Absturz Ihrer App. Ist die Anwendung jedoch auf API-Level 24 oder höher ausgerichtet, generiert Logcat den folgenden Laufzeitfehler und Ihre Anwendung kann abstürzen:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by
"/system/lib/libnativeloader.so" is not accessible for the namespace
"classloader-namespace"
  at java.lang.Runtime.loadLibrary0(Runtime.java:977)
  at java.lang.System.loadLibrary(System.java:1602)

Diese Logcat-Ausgaben können auch angezeigt werden, wenn Ihre Anwendung Bibliotheken von Drittanbietern verwendet, die dynamisch eine Verknüpfung zu privaten Plattform-APIs herstellen. Mit dem readelf-Tool in Android 7.0DK können Sie eine Liste aller dynamisch verknüpften gemeinsam genutzten Bibliotheken einer bestimmten .so-Datei generieren. Dazu führen Sie den folgenden Befehl aus:

aarch64-linux-android-readelf -dW libMyLibrary.so

App aktualisieren

Hier sind einige Schritte, mit denen du diese Art von Fehlern beheben und dafür sorgen kannst, dass deine App bei zukünftigen Plattformupdates nicht abstürzt:

  • Wenn Ihre App private Plattformbibliotheken verwendet, sollten Sie eine eigene Kopie dieser Bibliotheken hinzufügen oder die öffentlichen NDK APIs verwenden.
  • Wenn deine App eine Bibliothek eines Drittanbieters verwendet, die auf private Symbole zugreift, wende dich an den Autor der Bibliothek, um die Bibliothek zu aktualisieren.
  • Achten Sie darauf, dass Sie alle Nicht-NDK-Bibliotheken mit Ihrem APK verpacken.
  • Verwenden Sie anstelle von getJavaVM und getJNIEnv aus libandroid_runtime.so die JNI-Standardfunktionen:
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • Verwenden Sie __system_property_get anstelle des privaten property_get-Symbols aus libcutils.so. Verwenden Sie dazu __system_property_get mit den folgenden Elementen:
    #include <sys/system_properties.h>
    

    Hinweis: Die Verfügbarkeit und der Inhalt von Systemeigenschaften werden nicht über CTS getestet. Eine bessere Lösung wäre, diese Attribute gar nicht zu verwenden.

  • Verwende eine lokale Version des SSL_ctrl-Symbols aus libcrypto.so. Du solltest beispielsweise libcyrpto.a in deiner .so-Datei statisch verknüpfen oder eine dynamisch verknüpfte Version von libcrypto.so von BoringSSL/OpenSSL einfügen und in deinem APK verpacken.

Android for Work

Unter Android 7.0 wurden Änderungen an Apps vorgenommen, die auf Android for Work ausgerichtet sind. Dazu gehören Änderungen an der Installation von Zertifikaten, der Passwortzurücksetzung, der sekundären Nutzerverwaltung und des Zugriffs auf Gerätekennungen. Wenn Sie Apps für Android for Work-Umgebungen erstellen, sollten Sie diese Änderungen prüfen und Ihre App entsprechend anpassen.

  • Sie müssen ein delegiertes Zertifikatinstallationsprogramm installieren, bevor der DPC es festlegen kann. Sowohl für Profil- als auch für Geräteinhaber-Apps, die auf Android 7.0 (API-Level 24) ausgerichtet sind, solltest du das delegierte Zertifikatinstallationsprogramm installieren, bevor der Device Policy Controller (DPC) DevicePolicyManager.setCertInstallerPackage() aufruft. Wenn das Installationsprogramm noch nicht installiert ist, gibt das System einen IllegalArgumentException aus.
  • Passworteinschränkungen für Geräteadministratoren können jetzt für Profilinhaber zurückgesetzt werden. Geräteadministratoren können DevicePolicyManager.resetPassword() nicht mehr verwenden, um Passwörter zu löschen oder bereits festgelegte Passwörter zu ändern. Geräteadministratoren können weiterhin ein Passwort festlegen, aber nur, wenn für das Gerät kein Passwort, keine PIN und kein Muster festgelegt ist.
  • Geräte- und Profilinhaber können Konten auch dann verwalten, wenn Einschränkungen festgelegt sind. Geräte- und Profilinhaber können die Account Management APIs auch dann aufrufen, wenn DISALLOW_MODIFY_ACCOUNTS-Nutzereinschränkungen gelten.
  • Geräteeigentümer können sekundäre Nutzer einfacher verwalten. Wenn ein Gerät im Modus „Geräteeigentümer“ ausgeführt wird, wird die Einschränkung DISALLOW_ADD_USER automatisch festgelegt. Dadurch wird verhindert, dass Nutzer nicht verwaltete sekundäre Nutzer erstellen. Außerdem wurden die Methoden CreateUser() und createAndInitializeUser() eingestellt. Sie werden durch die neue Methode DevicePolicyManager.createAndManageUser() ersetzt.
  • Geräteeigentümer können auf Geräte-IDs zugreifen. Ein Geräteinhaber kann mit DevicePolicyManager.getWifiMacAddress() auf die WLAN-MAC-Adresse eines Geräts zugreifen. Wenn WLAN auf dem Gerät noch nie aktiviert war, gibt diese Methode den Wert null zurück.
  • Über die Einstellung „Arbeitsmodus“ wird der Zugriff auf geschäftliche Apps gesteuert. Wenn der Arbeitsmodus deaktiviert ist, blendet der System Launcher sie ausgegraut aus und zeigt so an, dass keine geschäftlichen Apps verfügbar sind. Wenn Sie den Arbeitsmodus wieder aktivieren, wird das normale Verhalten wiederhergestellt.
  • Beim Installieren einer PKCS #12-Datei, die eine Clientzertifikatskette und den entsprechenden privaten Schlüssel aus der Einstellungs-UI enthält, wird das CA-Zertifikat in der Kette nicht mehr im Speicher für vertrauenswürdige Anmeldedaten installiert. Dies hat keinen Einfluss auf das Ergebnis von KeyChain.getCertificateChain(), wenn Anwendungen später versuchen, die Clientzertifikatskette abzurufen. Falls erforderlich, sollte das CA-Zertifikat separat über die Einstellungs-UI in einem DER-codierten Format unter der Dateiendung .crt oder .cer im Speicher für vertrauenswürdige Anmeldedaten installiert werden.
  • Ab Android 7.0 werden Registrierung und Speicherung von Fingerabdrücken pro Nutzer verwaltet. Wenn der Device Policy Client (DPC) eines Profilinhabers auf einem Gerät mit Android 7.0 (API-Level 24) auf API-Level 23 (oder niedriger) ausgerichtet ist, kann der Nutzer weiterhin einen Fingerabdruck auf dem Gerät festlegen. Arbeitsanwendungen können jedoch nicht auf den Fingerabdruck des Geräts zugreifen. Wenn der DPC auf API-Level 24 oder höher ausgerichtet ist, kann der Nutzer den Fingerabdruck unter Einstellungen > Sicherheit > Sicherheit des Arbeitsprofils speziell für das Arbeitsprofil festlegen.
  • Der neue Verschlüsselungsstatus ENCRYPTION_STATUS_ACTIVE_PER_USER wird von DevicePolicyManager.getStorageEncryptionStatus() zurückgegeben und gibt an, dass die Verschlüsselung aktiv und der Verschlüsselungsschlüssel an den Nutzer gebunden ist. Der neue Status wird nur zurückgegeben, wenn DPC auf API-Level 24 oder höher abzielt. Bei Anwendungen für ältere API-Levels wird ENCRYPTION_STATUS_ACTIVE zurückgegeben, auch wenn der Verschlüsselungsschlüssel für den Nutzer oder das Profil spezifisch ist.
  • Unter Android 7.0 verhalten sich verschiedene Methoden, die normalerweise das gesamte Gerät betreffen, anders, wenn auf dem Gerät ein Arbeitsprofil mit einer separaten geschäftlichen Identitätsbestätigung installiert ist. Diese Methoden wirken sich nicht auf das gesamte Gerät aus, sondern gelten nur für das Arbeitsprofil. Die vollständige Liste solcher Methoden finden Sie in der DevicePolicyManager.getParentProfileInstance()-Dokumentation. Beispielsweise sperrt DevicePolicyManager.lockNow() nur das Arbeitsprofil, nicht das gesamte Gerät. Für jede dieser Methoden können Sie das alte Verhalten abrufen, indem Sie die Methode in der übergeordneten Instanz von DevicePolicyManager aufrufen. Dieses übergeordnete Element können Sie durch Aufrufen von DevicePolicyManager.getParentProfileInstance() abrufen. Wenn Sie beispielsweise die Methode lockNow() der übergeordneten Instanz aufrufen, wird das gesamte Gerät gesperrt.

Aufbewahrung von Anmerkungen

In Android 7.0 wurde ein Fehler behoben, bei dem die Sichtbarkeit von Anmerkungen ignoriert wurde. Durch dieses Problem konnte die Laufzeit auf Anmerkungen zugreifen, auf die sie hätte nicht zugreifen können. Zu diesen Anmerkungen gehörten:

  • VISIBILITY_BUILD: Ist nur während der Build-Erstellung sichtbar.
  • VISIBILITY_SYSTEM: Soll während der Laufzeit sichtbar sein, aber nur für das zugrunde liegende System.

Wenn Ihre App von diesem Verhalten abhängig ist, fügen Sie Annotationen, die zur Laufzeit verfügbar sein müssen, eine Aufbewahrungsrichtlinie hinzu. Dazu verwenden Sie @Retention(RetentionPolicy.RUNTIME).

Änderungen der TLS/SSL-Standardkonfiguration

Unter Android 7.0 werden die folgenden Änderungen an der TLS/SSL-Standardkonfiguration vorgenommen, die von Apps für HTTPS- und anderen TLS/SSL-Traffic verwendet wird:

  • RC4-Cipher Suites sind jetzt deaktiviert.
  • Cipher Suites CHACHA20-POLY1305 sind jetzt aktiviert.

Wenn RC4 standardmäßig deaktiviert ist, kann dies zu Problemen bei der HTTPS- oder TLS/SSL-Konnektivität führen, wenn der Server keine modernen Chiffresammlungen aushandelt. Die bevorzugte Lösung besteht darin, die Konfiguration des Servers zu verbessern, um stärkere und modernere Cipher Suites und Protokolle zu ermöglichen. Idealerweise sollten TLSv1.2 und AES-GCM aktiviert und Forward Secrecy Cipher Suites (ECDHE) aktiviert und bevorzugt sein.

Alternativ kannst du die Anwendung so ändern, dass für die Kommunikation mit dem Server ein benutzerdefiniertes SSLSocketFactory verwendet wird. Die Factory sollte so konzipiert sein, dass SSLSocket-Instanzen erstellt werden, für die einige der vom Server erforderlichen Cipher Suites zusätzlich zu den standardmäßigen Cipher Suites aktiviert sind.

Hinweis:Diese Änderungen gelten nicht für WebView.

Apps, die auf Android 7.0 ausgerichtet sind

Diese Änderungen im Verhalten gelten ausschließlich für Apps, die auf Android 7.0 (API-Level 24) oder höher ausgerichtet sind. Apps, die für Android 7.0 kompiliert werden oder für targetSdkVersion Android 7.0 oder höher festlegen, müssen gegebenenfalls ihre Apps so ändern, dass diese Verhaltensweisen ordnungsgemäß unterstützt werden.

Änderungen bei der Serialisierung

Mit Android 7.0 (API-Level 24) wurde ein Fehler in der Berechnung der Standard-serialVersionUID behoben, bei der nicht die Spezifikation übereinstimmte.

Bei Klassen, die Serializable implementieren und kein explizites serialVersionUID-Feld angeben, kann sich die Standard-serialVersionUID ändern. Dies führt dazu, dass beim Versuch, Instanzen der Klasse zu deserialisieren, die in einer früheren Version seriellisiert wurden oder von einer Anwendung, die auf eine frühere Version ausgerichtet ist, deserialisiert werden, eine Ausnahme ausgelöst wird. Die Fehlermeldung sieht in etwa so aus:

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

Zur Behebung dieser Probleme muss jeder betroffenen Klasse ein serialVersionUID-Feld mit dem Wert stream classdesc serialVersionUID aus der Fehlermeldung hinzugefügt werden, in diesem Fall 1234. Diese Änderung entspricht allen Empfehlungen für Best Practices zum Schreiben von Serialisierungscode und funktioniert mit allen Android-Versionen.

Der spezifische Fehler, der behoben wurde, war auf das Vorhandensein statischer Initialisierungsmethoden (z.B. <clinit>) zurückzuführen. Gemäß der Spezifikation wirkt sich das Vorhandensein oder Fehlen einer statischen Initialisierermethode in der Klasse auf die für diese Klasse berechnete Standard-serialVersionUID aus. Vor der Fehlerkorrektur wurde bei der Berechnung die Superklasse auch auf einen statischen Initialisierer geprüft, wenn eine Klasse keinen solchen hatte.

Zur Klarstellung: Diese Änderung wirkt sich nicht auf Apps aus, die auf API-Level 23 oder niedriger ausgerichtet sind, Klassen mit einem serialVersionUID-Feld oder Klassen mit einer statischen Initialisierermethode.

Weitere wichtige Punkte

  • Wenn eine App unter Android 7.0 ausgeführt wird, aber auf eine niedrigere API-Ebene ausgerichtet ist und der Nutzer die Anzeigegröße ändert, wird der App-Prozess beendet. Die App muss in der Lage sein, dieses Szenario problemlos zu bewältigen. Andernfalls stürzt es ab, wenn der Nutzer es unter „Recents“ wiederhergestellt hat.

    Testen Sie Ihre Anwendung, um sicherzustellen, dass dieses Verhalten nicht auftritt. Dies erreichen Sie, indem Sie beim manuellen Beenden der App über DDMS einen identischen Absturz verursachen.

    Apps, die auf Android 7.0 (API-Level 24) und höher ausgerichtet sind, werden bei Änderungen der Dichte nicht automatisch beendet. Sie reagieren aber möglicherweise immer noch unzureichend auf Konfigurationsänderungen.

  • Apps unter Android 7.0 sollten Konfigurationsänderungen problemlos verarbeiten können und bei nachfolgenden Starts nicht abstürzen. Sie können das Verhalten der App überprüfen, indem Sie die Schriftgröße ändern (Einstellungen > Display > Schriftgröße) und dann die App unter „Zuletzt verwendet“ wiederherstellen.
  • Aufgrund eines Fehlers in früheren Android-Versionen hat das System das Schreiben auf einem TCP-Socket im Hauptthread nicht als Verletzung des strikten Modus gekennzeichnet. Mit Android 7.0 wird dieser Fehler behoben. Apps, die dieses Verhalten zeigen, geben jetzt android.os.NetworkOnMainThreadException aus. Im Allgemeinen ist die Durchführung von Netzwerkvorgängen im Hauptthread eine schlechte Idee, da diese Vorgänge normalerweise eine hohe Latenz haben, die ANR-Fehler und Verzögerungen verursacht.
  • Bei den Methoden der Debug.startMethodTracing()-Methodenfamilie wird die Ausgabe jetzt standardmäßig in Ihrem paketspezifischen Verzeichnis im freigegebenen Speicher gespeichert, nicht auf der obersten Ebene der SD-Karte. Das bedeutet, dass Apps nicht mehr die Berechtigung WRITE_EXTERNAL_STORAGE anfordern müssen, um diese APIs zu verwenden.
  • Viele Plattform-APIs haben jetzt mit der Prüfung auf große Nutzlasten begonnen, die über Binder-Transaktionen gesendet werden. Das System gibt TransactionTooLargeExceptions jetzt noch einmal als RuntimeExceptions aus, anstatt sie unbemerkt zu protokollieren oder zu unterdrücken. Ein gängiges Beispiel ist das Speichern von zu vielen Daten in Activity.onSaveInstanceState(). Dies führt dazu, dass ActivityThread.StopInfo eine RuntimeException ausgibt, wenn deine App auf Android 7.0 ausgerichtet ist.
  • Wenn eine Anwendung Runnable-Aufgaben an ein View sendet und die View nicht an ein Fenster angehängt ist, stellt das System die Runnable-Aufgabe mit der View in die Warteschlange. Die Runnable-Aufgabe wird erst ausgeführt, wenn die View an ein Fenster angehängt wurde. Durch dieses Verhalten werden die folgenden Fehler behoben:
    • Wenn eine Anwendung in einem View aus einem anderen Thread als dem UI-Thread des beabsichtigten Fensters gepostet wird, wird Runnable möglicherweise im falschen Thread ausgeführt.
    • Wenn die Aufgabe Runnable aus einem anderen Thread als einem Looper-Thread gepostet wurde, könnte die Anwendung die Aufgabe Runnable verfügbar machen.
  • Wenn eine App auf Android 7.0 mit der Berechtigung DELETE_PACKAGES versucht, ein Paket zu löschen, aber eine andere App das Paket installiert hat, fordert das System die Bestätigung durch den Nutzer an. In diesem Szenario sollten Anwendungen STATUS_PENDING_USER_ACTION als Rückgabestatus erwarten, wenn sie PackageInstaller.uninstall() aufrufen.
  • Der JCA-Anbieter namens Crypto wurde verworfen, da sein einziger Algorithmus, SHA1PRNG, kryptografisch schwach ist. Anwendungen können SHA1PRNG nicht mehr zum Ableiten von Schlüsseln (unsicher) verwenden, da dieser Anbieter nicht mehr verfügbar ist. Weitere Informationen findest du im Blogpost Sicherheitsanbieter „Kryptografie“ in Android N verworfen.