Android 17 offre aux développeurs de nouvelles fonctionnalités et API de qualité. Les sections suivantes récapitulent ces fonctionnalités pour vous aider à vous lancer avec les API associées.
Pour obtenir une liste détaillée des nouvelles API, des API modifiées et supprimées, consultez le rapport de différences des API. Pour en savoir plus sur les nouvelles API, consultez la documentation de référence des API Android. Les nouvelles API sont mises en évidence pour une meilleure visibilité.
Vous devez également examiner les domaines dans lesquels les changements de plate-forme peuvent affecter vos applications. Pour en savoir plus, consultez les pages suivantes :
- Changements de comportement affectant les applications lorsqu'elles ciblent Android 17
- Changements de comportement affectant toutes les applications, quelle que soit la
targetSdkVersion.
Fonctionnalité de base
Android 17 ajoute les nouvelles fonctionnalités suivantes liées à la fonctionnalité Android de base.
Nouveaux déclencheurs ProfilingManager
Android 17 ajoute plusieurs nouveaux déclencheurs système à ProfilingManager pour
vous aider à collecter des données détaillées afin de déboguer les problèmes de performances.
Les nouveaux déclencheurs sont les suivants :
TRIGGER_TYPE_COLD_START: le déclencheur se produit lors du démarrage à froid de l'application. Il fournit à la fois un exemple de pile d'appels et une trace système dans la réponse.TRIGGER_TYPE_OOM: le déclencheur se produit lorsqu'une application génère uneOutOfMemoryErroret fournit un vidage de tas Java en réponse.TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE: le déclencheur se produit lorsqu'une application est arrêtée en raison d'une utilisation anormale et excessive du processeur, et fournit un exemple de pile d'appels en réponse.TRIGGER_TYPE_ANOMALY: détecte les anomalies de performances du système, telles que les appels de liaison excessifs et l'utilisation excessive de la mémoire.
Pour savoir comment configurer le déclencheur système, consultez la documentation sur le profilage basé sur les déclencheurs et la documentation sur la récupération et l’analyse des données de profilage.
Déclencheur de profilage pour les anomalies d'application
Android 17 introduit un service de détection des anomalies sur l'appareil qui surveille les comportements gourmands en ressources et les régressions de compatibilité potentielles. Intégré
à ProfilingManager, ce service permet à votre application de recevoir des artefacts de profilage
déclenchés par des événements spécifiques détectés par le système.
Utilisez le déclencheur TRIGGER_TYPE_ANOMALY pour détecter les problèmes de performances du système
tels que les appels de liaison excessifs et l'utilisation excessive de la mémoire. Lorsqu'une application dépasse les limites de mémoire définies par le système d'exploitation, le déclencheur d'anomalie permet aux développeurs de recevoir des vidages de tas spécifiques à l'application pour les aider à identifier et à résoudre les problèmes de mémoire. De plus, en cas de spam de liaison excessif, le déclencheur d'anomalie fournit un profil d'échantillonnage de pile sur les transactions de liaison.
Ce rappel d'API se produit avant toute application imposée par le système. Par exemple, il peut aider les développeurs à collecter des données de débogage avant que l'application ne soit arrêtée par le système pour dépassement des limites de mémoire.
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)
}
API JobDebugInfo
Android 17 引入了新的 JobDebugInfo API,可帮助开发者调试其 JobScheduler 作业,了解作业未运行的原因、运行时长以及其他汇总信息。
扩展后的 JobDebugInfo API 的第一个方法是 getPendingJobReasonStats(),该方法会返回一个映射,其中包含作业处于待执行状态的原因及其各自的累计待执行时长。此方法将 getPendingJobReasonsHistory() 和 getPendingJobReasons() 方法联接在一起,可让您了解预定作业未按预期运行的原因,但通过在单个方法中同时提供时长和作业原因,简化了信息检索。
例如,对于指定的 jobId,该方法可能会返回 PENDING_JOB_REASON_CONSTRAINT_CHARGING 和 60000 毫秒的时长,表示作业因未满足充电约束而处于等待状态 60000 毫秒。
Réduire les verrous de réveil avec la prise en charge des écouteurs pour les alarmes "allow-while-idle"
Android 17 introduit une nouvelle variante de AlarmManager.setExactAndAllowWhileIdle qui accepte un OnAlarmListener au lieu d'un PendingIntent. Ce nouveau mécanisme basé sur des rappels est idéal pour les applications qui s'appuient actuellement sur des wakelocks continus pour effectuer des tâches périodiques, telles que les applications de messagerie qui maintiennent des connexions de socket.
Confidentialité
Android 17 inclut les nouvelles fonctionnalités suivantes pour améliorer la confidentialité des utilisateurs.
Compatibilité de la plate-forme avec Encrypted Client Hello (ECH)
Android 17 introduit la compatibilité de la plate-forme avec ECH (Encrypted Client Hello), une amélioration significative de la confidentialité pour les communications réseau. ECH est une extension TLS 1.3 qui chiffre l'indication du nom du serveur (SNI) lors du handshake TLS initial. Ce chiffrement permet de protéger la confidentialité des utilisateurs en rendant plus difficile l'identification du domaine spécifique auquel une application se connecte par les intermédiaires réseau.
La plate-forme inclut désormais les API nécessaires pour que les bibliothèques réseau implémentent ECH. Cela inclut de nouvelles fonctionnalités dans DnsResolver pour interroger les
enregistrements DNS HTTPS contenant des configurations ECH, ainsi que de nouvelles méthodes dans les
SSLEngines et SSLSockets de Conscrypt pour activer ECH en transmettant ces configurations lors de la
connexion à un domaine. Les développeurs peuvent configurer les préférences ECH, par exemple
en l'activant de manière opportuniste ou en imposant son utilisation, via le nouvel élément
<domainEncryption> dans le fichier de configuration de la sécurité réseau,
applicable globalement ou par domaine.
Les bibliothèques réseau populaires telles que HttpEngine, WebView et OkHttp devraient intégrer ces API de plate-forme dans de futures mises à jour, ce qui permettra aux applications d'adopter plus facilement ECH et d'améliorer la confidentialité des utilisateurs.
Pour en savoir plus, consultez la documentation Encrypted Client Hello.
Sélecteur de contacts Android
The Android Contact Picker is a standardized, browsable interface for users to
share contacts with your app. Available on devices running
Android 17 (API level 37) or higher, the picker offers a privacy-preserving
alternative to the broad READ_CONTACTS permission. Instead of requesting
access to the user's entire address book, your app specifies the data fields it
needs, such as phone numbers or email addresses, and the user selects specific
contacts to share. This grants your app read access to only the selected data,
ensuring granular control while providing a consistent user experience with
built-in search, profile switching, and multi-selection capabilities without
having to build or maintain the UI.
For more information, see the contact picker documentation.
Sécurité
Android 17 ajoute les nouvelles fonctionnalités suivantes pour améliorer la sécurité des appareils et des applications.
Mode Protection Avancée Android (AAPM)
Le mode Protection Avancée d'Android offre aux utilisateurs Android un nouvel ensemble de fonctionnalités de sécurité puissantes. Il s'agit d'une étape importante pour protéger les utilisateurs, en particulier ceux qui sont plus exposés, contre les attaques sophistiquées. Conçue comme une fonctionnalité optionnelle, l'AAPM s'active avec un seul paramètre de configuration que les utilisateurs peuvent activer à tout moment pour appliquer un ensemble de protections de sécurité.
Ces configurations de base incluent le blocage de l'installation d'applications provenant de sources inconnues (téléchargement indépendant), la restriction de la signalisation des données USB et l'analyse obligatoire de Google Play Protect, ce qui réduit considérablement la surface d'attaque de l'appareil.
Les développeurs peuvent s'intégrer à cette fonctionnalité à l'aide de l'API AdvancedProtectionManager pour détecter l'état du mode, ce qui permet aux applications d'adopter automatiquement une posture de sécurité renforcée ou de restreindre les fonctionnalités à haut risque lorsqu'un utilisateur a activé le mode.
Signature d'APK PQC
Android 现在支持混合 APK 签名方案,以保护应用的签名身份免受利用量子计算的攻击的潜在威胁。此功能引入了一种新的 APK 签名方案,可让您将经典签名密钥(例如 RSA 或 EC)与新的后量子加密 (PQC) 算法 (ML-DSA) 配对。
这种混合方法可确保您的应用在未来免受量子攻击,同时与依赖于经典签名验证的旧版 Android 和设备保持完全的向后兼容性。
对开发者的影响
- 使用 Play 应用签名的应用:如果您使用 Play 应用签名,可以等待 Google Play 为您提供使用 Google Play 生成的 PQC 密钥升级混合签名的选项,从而确保您的应用受到保护,而无需手动管理密钥。
- 使用自行管理的密钥的应用:自行管理签名密钥的开发者可以利用更新后的 Android build 工具(例如 apksigner)轮换到混合身份,将 PQC 密钥与新的经典密钥相结合。(您必须创建新的经典密钥,无法重复使用旧密钥。)
Connectivité
Android 17 ajoute les fonctionnalités suivantes pour améliorer la connectivité des appareils et des applications.
Réseaux satellites contraints
Implémente des optimisations pour permettre aux applications de fonctionner efficacement sur les réseaux satellites à faible bande passante.
Expérience utilisateur et UI du système
Android 17 inclut les modifications suivantes pour améliorer l'expérience utilisateur.
Flux de volume dédié à l'Assistant
Android 17 introduit un flux de volume Assistant dédié aux applications Assistant,
pour la lecture avec USAGE_ASSISTANT. Cette modification dissocie l'audio de l'Assistant du flux média standard, ce qui permet aux utilisateurs de contrôler les deux volumes de manière isolée. Cela permet de couper la lecture média tout en conservant l'audibilité des réponses de l'Assistant, et inversement.
Les applications Assistant ayant accès au nouveau MODE_ASSISTANT_CONVERSATION audio
mode peuvent améliorer davantage la cohérence du contrôle du volume. Les applications Assistant peuvent utiliser ce mode pour fournir au système un indice concernant une session Assistant active, ce qui garantit que le flux Assistant peut être contrôlé en dehors de la lecture USAGE_ASSISTANT active ou avec des périphériques Bluetooth connectés.
Transfert
Le transfert est une nouvelle fonctionnalité et API qui sera disponible dans Android 17. Les développeurs d'applications pourront l'intégrer pour offrir une continuité inter-appareils à leurs utilisateurs. Il permet à l'utilisateur de démarrer une activité d'application sur un appareil Android et de la transférer vers un autre appareil Android. Le transfert s'exécute en arrière-plan de l'appareil d'un utilisateur et affiche les activités disponibles à partir des autres appareils à proximité de l'utilisateur via différents points d'entrée, comme le lanceur d'applications et la barre des tâches, sur l'appareil de réception.
Les applications peuvent désigner Handoff pour lancer la même application Android native, si elle est installée et disponible sur l'appareil de réception. Dans ce flux d'application à application, l'utilisateur est redirigé vers l'activité désignée à l'aide d'un lien profond. Vous pouvez également proposer le transfert d'application à Web comme option de secours ou l'implémenter directement avec le transfert d'URL.
La prise en charge du transfert est implémentée par activité. Pour activer le transfert, appelez la méthode setHandoffEnabled() pour l'activité. Des données supplémentaires peuvent être nécessaires pour le transfert afin que l'activité recréée sur l'appareil de réception puisse restaurer l'état approprié. Implémentez le rappel onHandoffActivityDataRequested() pour renvoyer un objet HandoffActivityData qui contient des détails spécifiant comment le transfert doit gérer et recréer l'activité sur l'appareil de réception.
Mise à jour en direct : API de couleurs sémantiques
Avec Android 17, Live Update lance les API de coloration sémantique pour prendre en charge les couleurs ayant une signification universelle.
Les classes suivantes prennent en charge la coloration sémantique :
NotificationNotification.MetricNotification.ProgressStyle.PointNotification.ProgressStyle.Segment
Jeux de coloriage
- Vert : associé à la sécurité. Cette couleur doit être utilisée pour indiquer aux utilisateurs qu'ils sont en sécurité.
- Orange : pour indiquer la prudence et signaler les dangers physiques. Cette couleur doit être utilisée lorsque les utilisateurs doivent faire attention à définir de meilleurs paramètres de protection.
- Rouge : indique généralement un danger ou un arrêt. Elle doit être utilisée lorsque l'attention des utilisateurs est requise de toute urgence.
- Bleu : couleur neutre pour le contenu informatif qui doit se démarquer des autres contenus.
L'exemple suivant montre comment appliquer des styles sémantiques à du texte dans une notification :
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)
API UWB Downlink-TDoA pour Android 17
下行链路到达时间差 (DL-TDoA) 测距功能可让设备通过测量信号的相对到达时间来确定其相对于多个锚点的相对位置。
以下代码段演示了如何初始化 测距管理器、 验证设备功能以及启动 DL-TDoA 会话:
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
}
}
}
带外 (OOB) 配置
以下代码段提供了 Wi-Fi 和 BLE 的 DL-TDoA OOB 配置数据示例:
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
};
如果您无法使用 OOB 配置(因为该配置缺失),或者需要更改 OOB 配置中没有的默认值,则可以使用 DlTdoaRangingParams.Builder 构建参数,如以下代码段所示。您可以使用这些参数代替 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();