Android 17 bietet viele neue Funktionen und APIs für Entwickler. In den folgenden Abschnitten werden diese Funktionen zusammengefasst, um Ihnen den Einstieg in die zugehörigen APIs zu erleichtern.
Eine detaillierte Liste der neuen, geänderten und entfernten APIs finden Sie im Bericht zu API-Unterschieden. Details zu neuen APIs finden Sie in der Android API-Refer1enz. Neue APIs sind zur besseren Sichtbarkeit hervorgehoben.
Sie sollten sich auch die Bereiche ansehen, in denen sich Plattformänderungen auf Ihre Apps auswirken können. Weitere Informationen finden Sie auf den folgenden Seiten:
- Verhaltensänderungen, die sich auf Apps auswirken, wenn sie auf Android 17 ausgerichtet sind
- Verhaltensänderungen, die sich unabhängig von
targetSdkVersionauf alle Apps auswirken
Hauptfunktion
Android 17 bietet die folgenden neuen Funktionen im Zusammenhang mit der Android-Kernfunktionalität.
Neue ProfilingManager-Trigger
In Android 17 wurden ProfilingManager mehrere neue Systemtrigger hinzugefügt, mit denen Sie
detaillierte Daten zur Behebung von Leistungsproblemen erfassen können.
Die neuen Trigger sind:
TRIGGER_TYPE_COLD_START: Der Trigger wird beim Kaltstart der App ausgelöst. Die Antwort enthält sowohl ein Aufrufstapelmuster als auch ein System-Trace.TRIGGER_TYPE_OOM: Der Trigger wird ausgelöst, wenn eine App einenOutOfMemoryErrorauslöst, und die Antwort enthält einen Java-Heap-Dump.TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE: Der Trigger wird ausgelöst, wenn eine App aufgrund einer ungewöhnlichen und übermäßigen CPU-Auslastung beendet wird, und die Antwort enthält ein Aufrufstapelmuster.TRIGGER_TYPE_ANOMALY: Hiermit können Sie Anomalien bei der Systemleistung erkennen, z. B. übermäßige Binder-Aufrufe und übermäßige Arbeitsspeichernutzung.
Informationen zum Einrichten des Systemtriggers finden Sie in der Dokumentation zu triggerbasierter Profilerstellung und zum Abrufen und Analysieren von Profilerstellungsdaten Dokumentation.
Profilerstellungstrigger für App-Anomalien
In Android 17 wurde ein On-Device-Dienst zur Erkennung von Anomalien eingeführt, der ressourcenintensive Verhaltensweisen und potenzielle Kompatibilitätsregressionen überwacht. Dieser Dienst ist in ProfilingManager integriert
und ermöglicht es Ihrer App, Profilerstellungs
artefakte zu empfangen, die durch bestimmte vom System erkannte Ereignisse ausgelöst werden.
Verwenden Sie den TRIGGER_TYPE_ANOMALY Trigger, um Leistungsprobleme des Systems zu erkennen, z. B. übermäßige Binder-Aufrufe und übermäßige Arbeitsspeichernutzung. Wenn eine App die vom Betriebssystem festgelegten Speicherlimits überschreitet, können Entwickler mit dem Anomalie-Trigger appspezifische Heap-Dumps erhalten, um Speicherprobleme zu identifizieren und zu beheben. Außerdem liefert der Anomalie-Trigger bei übermäßigem Binder-Spam ein Sampling-Profil für Binder-Transaktionen.
Dieser API-Callback erfolgt vor allen vom System auferlegten Maßnahmen. So können Entwickler beispielsweise Debug-Daten erfassen, bevor die App vom System beendet wird, weil sie die Speicherlimits überschritten hat.
val profilingManager =
applicationContext.getSystemService(ProfilingManager::class.java)
val triggers = ArrayList<ProfilingTrigger>()
triggers.add(ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_ANOMALY))
val mainExecutor: Executor = Executors.newSingleThreadExecutor()
val resultCallback = Consumer<ProfilingResult> { profilingResult ->
if (profilingResult.errorCode != ProfilingResult.ERROR_NONE) {
// upload profile result to server for further analysis
setupProfileUploadWorker(profilingResult.resultFilePath)
}
profilingManager.registerForAllProfilingResults(mainExecutor,
resultCallback)
profilingManager.addProfilingTriggers(triggers)
}
JobDebugInfo APIs
Mit Android 17 werden neue JobDebugInfo-APIs eingeführt, mit denen Entwickler ihre JobScheduler-Jobs debuggen können. Sie können beispielsweise herausfinden, warum die Jobs nicht ausgeführt werden, wie lange sie ausgeführt wurden und andere aggregierte Informationen abrufen.
Die erste Methode der erweiterten JobDebugInfo-APIs ist
getPendingJobReasonStats(). Sie gibt eine Zuordnung der Gründe zurück, warum sich der Job im
Status „Ausführung ausstehend“ befand, sowie die entsprechenden kumulativen
Wartezeiten. Diese Methode kombiniert die getPendingJobReasonsHistory() und
getPendingJobReasons() Methoden, um Ihnen Einblicke zu geben, warum ein geplanter
Job nicht wie erwartet ausgeführt wird. Sie vereinfacht den Abruf von Informationen, da
sowohl die Dauer als auch der Grund für den Job in einer einzigen Methode verfügbar sind.
Für eine bestimmte jobId kann die Methode beispielsweise PENDING_JOB_REASON_CONSTRAINT_CHARGING und eine Dauer von 60000 ms zurückgeben. Das bedeutet, dass der Job 60000 ms lang ausstand, weil die Ladebeschränkung nicht erfüllt war.
Weniger Wake Locks mit Listener-Unterstützung für Alarme vom Typ „allow-while-idle“
In Android 17 wird eine neue Variante von AlarmManager.setExactAndAllowWhileIdle eingeführt, die anstelle von PendingIntent ein OnAlarmListener akzeptiert. Dieser neue Callback-basierte Mechanismus eignet sich ideal für Apps, die derzeit auf kontinuierliche Wakelocks angewiesen sind, um regelmäßige Aufgaben auszuführen, z. B. Messaging-Apps, die Socket-Verbindungen aufrechterhalten.
Datenschutz
Android 17 enthält die folgenden neuen Funktionen, um den Datenschutz für Nutzer zu verbessern.
Plattformunterstützung für Encrypted Client Hello (ECH)
Mit Android 17 wird die Plattformunterstützung für Encrypted Client Hello (ECH) eingeführt, eine erhebliche Verbesserung des Datenschutzes für die Netzwerkkommunikation. ECH ist eine TLS 1.3-Erweiterung, die den Server Name Indication (SNI) während des ersten TLS-Handshakes verschlüsselt. Diese Verschlüsselung trägt zum Schutz der Privatsphäre der Nutzer bei, da es für Netzwerkvermittler schwieriger wird, die spezifische Domain zu identifizieren, mit der eine App eine Verbindung herstellt.
Die Plattform enthält jetzt die erforderlichen APIs für Netzwerkbibliotheken, um ECH zu implementieren. Dazu gehören neue Funktionen in DnsResolver zum Abfragen von
HTTPS-DNS-Einträgen mit ECH-Konfigurationen und neue Methoden in den SSLEngines und SSLSockets von Conscrypt,
um ECH zu aktivieren, indem diese Konfigurationen beim
Herstellen einer Verbindung zu einer Domain übergeben werden. Entwickler können ECH-Einstellungen konfigurieren, z. B.
die optionale Aktivierung oder die obligatorische Verwendung, über das neue
<domainEncryption> Element in der Konfigurationsdatei für die Netzwerksicherheit,
die global oder pro Domain angewendet werden kann.
Es wird erwartet, dass beliebte Netzwerkbibliotheken wie HttpEngine, WebView und OkHttp diese Plattform-APIs in zukünftigen Updates integrieren, wodurch es für Apps einfacher wird, ECH zu übernehmen und den Datenschutz für Nutzer zu verbessern.
Weitere Informationen finden Sie in der Dokumentation zu Encrypted Client Hello.
Android-Kontaktauswahl
Die Android-Kontaktauswahl ist eine standardisierte, durchsuchbare Oberfläche, über die Nutzer Kontakte für Ihre App freigeben können. Sie ist auf Geräten mit Android 17 (API‑Level 37) oder höher verfügbar und bietet eine datenschutzfreundliche Alternative zur umfassenden Berechtigung READ_CONTACTS. Anstatt Zugriff auf das gesamte Adressbuch des Nutzers anzufordern, gibt Ihre App die benötigten Datenfelder an, z. B. Telefonnummern oder E-Mail-Adressen, und der Nutzer wählt bestimmte Kontakte aus, die freigegeben werden sollen. Dadurch erhält Ihre App nur Lesezugriff auf die ausgewählten Daten. So haben Sie eine detaillierte Kontrolle und können gleichzeitig eine einheitliche Nutzererfahrung mit integrierter Suche, Profilwechsel und Mehrfachauswahl bieten, ohne die Benutzeroberfläche selbst entwickeln oder verwalten zu müssen.
Weitere Informationen finden Sie in der Dokumentation zur Kontaktauswahl.
Sicherheit
Android 17 bietet die folgenden neuen Funktionen, um die Sicherheit von Geräten und Apps zu verbessern.
Erweiterter Sicherheitsprogramm-Modus für Android (Android Advanced Protection Mode, AAPM)
Android Advanced Protection Mode offers Android users a powerful new set of security features, marking a significant step in safeguarding users—particularly those at higher risk—from sophisticated attacks. Designed as an opt-in feature, AAPM is activated with a single configuration setting that users can turn on at any time to apply an opinionated set of security protections.
These core configurations include blocking app installation from unknown sources
(sideloading), restricting USB data signaling, and mandating Google Play Protect
scanning, which significantly reduces the device's attack surface area.
Developers can integrate with this feature using the
AdvancedProtectionManager API to detect the mode's status, enabling
applications to automatically adopt a hardened security posture or restrict
high-risk functionality when a user has opted in.
PQC-APK-Signierung
Android unterstützt jetzt ein hybrides APK-Signaturschema, um die Signaturidentität Ihrer App vor der potenziellen Bedrohung durch Angriffe zu schützen, bei denen Quantencomputer zum Einsatz kommen. Mit dieser Funktion wird ein neues APK-Signaturschema eingeführt, mit dem Sie einen klassischen Signaturschlüssel (z. B. RSA oder EC) mit einem neuen Post-Quanten-Kryptografie-Algorithmus (PQC) (ML-DSA) kombinieren können.
Dieser hybride Ansatz sorgt dafür, dass Ihre App auch in Zukunft vor Quantenangriffen geschützt ist und gleichzeitig die volle Abwärtskompatibilität mit älteren Android-Versionen und Geräten, die auf klassische Signaturprüfung angewiesen sind, erhalten bleibt.
Auswirkungen auf Entwickler
- Apps mit Play App-Signatur:Wenn Sie die Play App-Signatur verwenden, können Sie warten, bis Google Play Ihnen die Möglichkeit gibt, eine Hybridsignatur mit einem von Google Play generierten PQC-Schlüssel zu aktualisieren. So ist Ihre App geschützt, ohne dass eine manuelle Schlüsselverwaltung erforderlich ist.
- Apps mit selbst verwalteten Schlüsseln:Entwickler, die ihre eigenen Signaturschlüssel verwalten, können aktualisierte Android-Build-Tools (z. B. apksigner) verwenden, um zu einer hybriden Identität zu wechseln, die einen PQC-Schlüssel mit einem neuen klassischen Schlüssel kombiniert. Sie müssen einen neuen klassischen Schlüssel erstellen. Der alte kann nicht wiederverwendet werden.
Konnektivität
Android 17 bietet die folgenden Funktionen, um die Konnektivität von Geräten und Apps zu verbessern.
Eingeschränkte Satellitennetzwerke
Implements optimizations to enable apps to function effectively over low-bandwidth satellite networks.
Nutzererfahrung und System-UI
Android 17 enthält die folgenden Änderungen, um die Nutzererfahrung zu verbessern.
Dedizierter Lautstärkestream für Assistant
In Android 17 wird ein dedizierter Assistant-Lautstärkestream für Assistant-Apps eingeführt, der mit USAGE_ASSISTANT wiedergegeben werden kann. Durch diese Änderung wird die Audioausgabe von Assistant vom Standard-Medienstream entkoppelt. Nutzer können die Lautstärke beider Streams unabhängig voneinander regeln. So können Sie beispielsweise die Medienwiedergabe stummschalten, während Assistant-Antworten weiterhin hörbar sind, und umgekehrt.
Assistant-Apps mit Zugriff auf den neuen Audiomodus MODE_ASSISTANT_CONVERSATION können die Konsistenz der Lautstärkeregelung weiter verbessern. Assistant-Apps können diesen Modus verwenden, um dem System einen Hinweis auf eine aktive Assistant-Sitzung zu geben. So kann der Assistant-Stream außerhalb der aktiven USAGE_ASSISTANT-Wiedergabe oder mit verbundenen Bluetooth-Peripheriegeräten gesteuert werden.
Handoff
Handoff is a new feature and API coming to Android 17 that app developers can integrate with to provide cross-device continuity for their users. It allows the user to start an app activity on one Android device and transition it to another Android device. Handoff runs in the background of a user's device and surfaces available activities from the user's other nearby devices through various entry points, like the launcher and taskbar, on the receiving device.
Apps can designate Handoff to launch the same native Android app, if it is installed and available on the receiving device. In this app-to-app flow, the user is deep-linked to the designated activity. Alternatively, app-to-web Handoff can be offered as a fallback option or directly implemented with URL Handoff.
Handoff support is implemented on a per-activity basis. To enable Handoff, call
the
setHandoffEnabled()
method for the activity. Additional data may need to be passed along with the
handoff so the recreated activity on the receiving device can restore
appropriate state. Implement the
onHandoffActivityDataRequested()
callback to return a
HandoffActivityData object which
contains details that specify how Handoff should handle and recreate the
activity on the receiving device.
Live-Update – Semantische Farb-API
Mit Android 17 werden mit Live Update die Semantic Coloring APIs eingeführt, um Farben mit universeller Bedeutung zu unterstützen.
Die folgenden Klassen unterstützen die semantische Farbgebung:
NotificationNotification.MetricNotification.ProgressStyle.PointNotification.ProgressStyle.Segment
Ausmalen
- Grün: Steht für Sicherheit. Diese Farbe sollte verwendet werden, wenn Sie sich in einer sicheren Situation befinden.
- Orange: Zur Kennzeichnung von Vorsicht und physischen Gefahren. Diese Farbe sollte verwendet werden, wenn Nutzer auf eine bessere Schutzmaßnahme achten müssen.
- Rot: Steht in der Regel für Gefahr oder „Stopp“. Sie sollte in Fällen angezeigt werden, in denen die Aufmerksamkeit der Nutzer dringend erforderlich ist.
- Blau: Neutrale Farbe für informative Inhalte, die sich von anderen Inhalten abheben sollen.
Das folgende Beispiel zeigt, wie Sie semantische Stile auf Text in einer Benachrichtigung anwenden:
val ssb = SpannableStringBuilder()
.append("Colors: ")
.append("NONE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_UNSPECIFIED), 0)
.append(", ")
.append("INFO", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_INFO), 0)
.append(", ")
.append("SAFE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_SAFE), 0)
.append(", ")
.append("CAUTION", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_CAUTION), 0)
.append(", ")
.append("DANGER", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_DANGER), 0)
Notification.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_icon)
.setContentTitle("Hello World!")
.setContentText(ssb)
.setOngoing(true)
.setRequestPromotedOngoing(true)
UWB-Downlink-TDoA-API für Android 17
Downlink Time Difference of Arrival (DL-TDoA) ranging lets a device determine its position relative to multiple anchors by measuring the relative arrival times of signals.
The following snippet demonstrates how to initialize the Ranging Manager, verify device capabilities, and start a DL-TDoA session:
Kotlin
class RangingApp {
fun initDlTdoa(context: Context) {
// Initialize the Ranging Manager
val rangingManager = context.getSystemService(RangingManager::class.java)
// Register for device capabilities
val capabilitiesCallback = object : RangingManager.RangingCapabilitiesCallback {
override fun onRangingCapabilities(capabilities: RangingCapabilities) {
// Make sure Dl-TDoA is supported before starting the session
if (capabilities.uwbCapabilities != null && capabilities.uwbCapabilities!!.isDlTdoaSupported) {
startDlTDoASession(context)
}
}
}
rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback)
}
fun startDlTDoASession(context: Context) {
// Initialize the Ranging Manager
val rangingManager = context.getSystemService(RangingManager::class.java)
// Create session and configure parameters
val executor = Executors.newSingleThreadExecutor()
val rangingSession = rangingManager.createRangingSession(executor, RangingSessionCallback())
val rangingRoundIndexes = byteArrayOf(0)
val config: ByteArray = byteArrayOf() // OOB config data
val params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes)
val rangingDevice = RangingDevice.Builder().build()
val rawTagDevice = RawRangingDevice.Builder()
.setRangingDevice(rangingDevice)
.setDlTdoaRangingParams(params)
.build()
val dtTagConfig = RawDtTagRangingConfig.Builder(rawTagDevice).build()
val preference = RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
.setSessionConfig(SessionConfig.Builder().build())
.build()
// Start the ranging session
rangingSession.start(preference)
}
}
private class RangingSessionCallback : RangingSession.Callback {
override fun onDlTdoaResults(peer: RangingDevice, measurement: DlTdoaMeasurement) {
// Process measurement results here
}
}
Java
public class RangingApp {
public void initDlTdoa(Context context) {
// Initialize the Ranging Manager
RangingManager rangingManager = context.getSystemService(RangingManager.class);
// Register for device capabilities
RangingManager.CapabilitiesCallback capabilitiesCallback = new RangingManager.RangingCapabilitiesCallback() {
@Override
public void onRangingCapabilities(RangingCapabilities capabilities) {
// Make sure Dl-TDoA is supported before starting the session
if (capabilities.getUwbCapabilities() != null && capabilities.getUwbCapabilities().isDlTdoaSupported()) {
startDlTDoASession(context);
}
}
};
rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback);
}
public void startDlTDoASession(Context context) {
RangingManager rangingManager = context.getSystemService(RangingManager.class);
// Create session and configure parameters
Executor executor = Executors.newSingleThreadExecutor();
RangingSession rangingSession = rangingManager.createRangingSession(executor, new RangingSessionCallback());
byte[] rangingRoundIndexes = new byte[] {0};
byte[] config = new byte[0]; // OOB config data
DlTdoaRangingParams params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes);
RangingDevice rangingDevice = new RangingDevice.Builder().build();
RawRangingDevice rawTagDevice = new RawRangingDevice.Builder()
.setRangingDevice(rangingDevice)
.setDlTdoaRangingParams(params)
.build();
RawDtTagRangingConfig dtTagConfig = new RawDtTagRangingConfig.Builder(rawTagDevice).build();
RangingPreference preference = new RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
.setSessionConfig(new SessionConfig.Builder().build())
.build();
// Start the ranging session
rangingSession.start(preference);
}
private static class RangingSessionCallback implements RangingSession.Callback {
@Override
public void onDlTdoaResults(RangingDevice peer, DlTdoaMeasurement measurement) {
// Process measurement results here
}
}
}
Out-of-Band (OOB) Configurations
The following snippet provides an example of DL-TDoA OOB configuration data for Wi-Fi and BLE:
Java
// Wifi Configuration
byte[] wifiConfig = {
(byte) 0xDD, (byte) 0x2D, (byte) 0x5A, (byte) 0x18, (byte) 0xFF, // Header
(byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
(byte) 0x02, (byte) 0x00, // Profile ID
(byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
(byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
(byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
(byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
(byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
(byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
(byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
(byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01 // Session ID
};
// BLE Configuration
byte[] bleConfig = {
(byte) 0x2D, (byte) 0x16, (byte) 0xF4, (byte) 0xFF, // Header
(byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
(byte) 0x02, (byte) 0x00, // Profile ID
(byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
(byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
(byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
(byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
(byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
(byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
(byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
(byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01 // Session ID
};
If you can't use an OOB configuration because it is missing, or if you need to
change default values that aren't in the OOB config, you can build parameters
with DlTdoaRangingParams.Builder as shown in the following snippet. You can use
these parameters in place of DlTdoaRangingParams.createFromFiraConfigPacket():
Kotlin
val dlTdoaParams = DlTdoaRangingParams.Builder(1)
.setComplexChannel(UwbComplexChannel.Builder()
.setChannel(9).setPreambleIndex(10).build())
.setDeviceAddress(deviceAddress)
.setSessionKeyInfo(byteArrayOf(0x01, 0x02, 0x03, 0x04))
.setRangingIntervalMillis(240)
.setSlotDuration(UwbRangingParams.DURATION_2_MS)
.setSlotsPerRangingRound(20)
.setRangingRoundIndexes(byteArrayOf(0x01, 0x05))
.build()
Java
DlTdoaRangingParams dlTdoaParams = new DlTdoaRangingParams.Builder(1)
.setComplexChannel(new UwbComplexChannel.Builder()
.setChannel(9).setPreambleIndex(10).build())
.setDeviceAddress(deviceAddress)
.setSessionKeyInfo(new byte[]{0x01, 0x02, 0x03, 0x04})
.setRangingIntervalMillis(240)
.setSlotDuration(UwbRangingParams.DURATION_2_MS)
.setSlotsPerRangingRound(20)
.setRangingRoundIndexes(new byte[]{0x01, 0x05})
.build();