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.
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.
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:
- Apps, die auf Android 7.0 (API-Level 24) und höher ausgerichtet sind, erhalten keine
CONNECTIVITY_ACTION
-Broadcasts, wenn sie ihren Broadcast-Empfänger im Manifest angeben. Anwendungen erhalten weiterhinCONNECTIVITY_ACTION
-Broadcasts, wenn sie ihreBroadcastReceiver
beiContext.registerReceiver()
registrieren und dieser Kontext weiterhin gültig ist. - Das System sendet keine
ACTION_NEW_PICTURE
- oderACTION_NEW_VIDEO
-Broadcasts mehr. Diese Optimierung betrifft alle Apps, nicht nur Apps, die auf Android 7.0 ausgerichtet sind.
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:
-
Die Dateiberechtigungen für private Dateien sollten nicht mehr vom Eigentümer gelockert werden. Ein Versuch, dies mit
MODE_WORLD_READABLE
und/oderMODE_WORLD_WRITEABLE
zu tun, löst einSecurityException
aus.Hinweis:Diese Einschränkung ist derzeit noch nicht vollständig erzwungen. Anwendungen können mithilfe nativer APIs oder der
File
API weiterhin Berechtigungen für ihr privates Verzeichnis ändern. Wir raten jedoch dringend davon ab, die Berechtigungen für das private Verzeichnis zu lockern. -
Wenn
file://
-URIs außerhalb der Paketdomain übergeben werden, kann es beim Empfänger zu einem nicht zugänglichen Pfad kommen. Daher wird bei Versuchen, einenfile://
-URI zu übergeben, einFileUriExposedException
ausgelöst. Es wird empfohlen, den Inhalt einer privaten Datei mitFileProvider
freizugeben. -
Das
DownloadManager
kann privat gespeicherte Dateien nicht mehr anhand des Dateinamens freigeben. Legacy-Anwendungen haben möglicherweise beim Zugriff aufCOLUMN_LOCAL_FILENAME
einen nicht zugänglichen Pfad. Apps, die auf Android 7.0 oder höher ausgerichtet sind, lösen beim Versuch, aufCOLUMN_LOCAL_FILENAME
zuzugreifen, einSecurityException
aus. Legacy-Anwendungen, die den Downloadpfad mithilfe vonDownloadManager.Request.setDestinationInExternalFilesDir()
oderDownloadManager.Request.setDestinationInExternalPublicDir()
auf einen öffentlichen Speicherort festlegen, können weiterhin auf den Pfad inCOLUMN_LOCAL_FILENAME
zugreifen. Von dieser Methode wird jedoch dringend abgeraten. Die bevorzugte Methode für den Zugriff auf eine Datei, die vomDownloadManager
bereitgestellt wird, istContentResolver.openFileDescriptor()
.
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.
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
undgetJNIEnv
auslibandroid_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 privatenproperty_get
-Symbols auslibcutils.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 auslibcrypto.so
. Du solltest beispielsweiselibcyrpto.a
in deiner.so
-Datei statisch verknüpfen oder eine dynamisch verknüpfte Version vonlibcrypto.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 einenIllegalArgumentException
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 MethodenCreateUser()
undcreateAndInitializeUser()
eingestellt. Sie werden durch die neue MethodeDevicePolicyManager.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 Wertnull
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 vonDevicePolicyManager.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 wirdENCRYPTION_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 sperrtDevicePolicyManager.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 vonDevicePolicyManager
aufrufen. Dieses übergeordnete Element können Sie durch Aufrufen vonDevicePolicyManager.getParentProfileInstance()
abrufen. Wenn Sie beispielsweise die MethodelockNow()
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 BerechtigungWRITE_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 gibtTransactionTooLargeExceptions
jetzt noch einmal alsRuntimeExceptions
aus, anstatt sie unbemerkt zu protokollieren oder zu unterdrücken. Ein gängiges Beispiel ist das Speichern von zu vielen Daten inActivity.onSaveInstanceState()
. Dies führt dazu, dassActivityThread.StopInfo
eineRuntimeException
ausgibt, wenn deine App auf Android 7.0 ausgerichtet ist. -
Wenn eine Anwendung
Runnable
-Aufgaben an einView
sendet und dieView
nicht an ein Fenster angehängt ist, stellt das System dieRunnable
-Aufgabe mit derView
in die Warteschlange. DieRunnable
-Aufgabe wird erst ausgeführt, wenn dieView
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, wirdRunnable
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 AufgabeRunnable
verfügbar machen.
- Wenn eine Anwendung in einem
-
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 AnwendungenSTATUS_PENDING_USER_ACTION
als Rückgabestatus erwarten, wenn siePackageInstaller.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.