Niveau d'API: 19
Android 4.4 (KITKAT
) est une nouvelle version de la plate-forme Android qui propose de nouvelles fonctionnalités aux utilisateurs et aux développeurs d'applications. Ce document présente les nouvelles API les plus notables.
En tant que développeur d'applications, vous devez télécharger l'image système et la plate-forme de SDK Android 4.4 à partir de SDK Manager dès que possible. Si vous ne disposez pas d'appareil exécutant Android 4.4 sur lequel tester votre application, utilisez l'image système Android 4.4 pour tester votre application sur Android Emulator. Ensuite, compilez vos applications pour la plate-forme Android 4.4 afin de commencer à utiliser les dernières API.
Mettre à jour votre niveau d'API cible
Pour optimiser davantage votre application pour les appareils équipés d'Android 4.4, vous devez définir votre targetSdkVersion
sur "19"
, l'installer sur une image système Android 4.4, la tester, puis publier une mise à jour avec cette modification.
Vous pouvez utiliser des API dans Android 4.4 tout en prenant en charge les versions antérieures en ajoutant des conditions à votre code qui vérifient le niveau d'API du système avant d'exécuter les API non compatibles avec votre minSdkVersion
.
Pour en savoir plus sur la rétrocompatibilité, consultez Prendre en charge différentes versions de plate-forme.
Pour en savoir plus sur le fonctionnement des niveaux d'API, consultez Qu'est-ce que le niveau d'API ?
Nouveaux comportements importants
Si vous avez déjà publié une application pour Android, sachez qu'elle peut être affectée par les modifications apportées à Android 4.4.
Si votre application lit à partir d'un espace de stockage externe :
Votre application ne peut pas lire les fichiers partagés sur le stockage externe lorsqu'elle s'exécute sur Android 4.4, sauf si elle dispose de l'autorisation READ_EXTERNAL_STORAGE
. Autrement dit, les fichiers du répertoire renvoyé par getExternalStoragePublicDirectory()
ne sont plus accessibles sans autorisation. Toutefois, si vous n'avez besoin d'accéder qu'aux répertoires spécifiques à votre application, fournis par getExternalFilesDir()
, vous n'avez pas besoin de l'autorisation READ_EXTERNAL_STORAGE
.
Si votre application utilise WebView :
Votre application peut se comporter différemment lorsqu'elle s'exécute sur Android 4.4, en particulier lorsque vous mettez à jour la valeur targetSdkVersion
de votre application sur "19" ou une valeur supérieure.
Le code sous-jacent de la classe WebView
et des API associées a été mis à niveau pour être basé sur un instantané moderne du code source Chromium. Cela apporte diverses améliorations des performances, la prise en charge de nouvelles fonctionnalités HTML5 et le débogage à distance de votre contenu WebView
. La portée de cette mise à niveau signifie que si votre application utilise WebView
, son comportement peut être affecté dans certains cas. Bien que les modifications de comportement connues soient documentées et n'affectent votre application que lorsque vous mettez à jour sa targetSdkVersion
vers la version 19 ou ultérieure (la nouvelle WebView
fonctionne en mode "quirks" pour fournir certaines fonctionnalités obsolètes dans les applications qui ciblent le niveau d'API 18 ou version antérieure), il est possible que votre application dépende de comportements inconnus de la version précédente de WebView
.
Par conséquent, si votre application existante utilise WebView
, nous vous recommandons de la tester sur Android 4.4 dès que possible et de consulter Passer à WebView sous Android 4.4 pour savoir comment votre application peut être affectée lorsque vous mettez à jour votre targetSdkVersion
vers la version 19 ou ultérieure.
Si votre application utilise AlarmManager :
Lorsque vous définissez le paramètre targetSdkVersion
de votre application sur "19 " ou une version ultérieure, les alarmes que vous créez à l'aide de set()
ou setRepeating()
sont inexactes.
Pour améliorer l'efficacité énergétique, Android regroupe désormais les alarmes de toutes les applications qui se déclenchent à des heures raisonnablement similaires afin que le système réveille l'appareil une seule fois au lieu de plusieurs fois pour gérer chaque alarme.
Si votre alarme n'est pas associée à une heure exacte, mais qu'il est important qu'elle soit déclenchée dans une plage horaire spécifique (par exemple, entre 14h et 16h), vous pouvez utiliser la nouvelle méthode setWindow()
, qui accepte une heure "la plus tôt possible" pour l'alarme et une "fenêtre" d'heures suivant l'heure la plus tôt possible au cours de laquelle le système doit déclencher l'alarme.
Si votre alarme doit être fixée à une heure exacte (par exemple, pour un rappel d'événement d'agenda), vous pouvez utiliser la nouvelle méthode setExact()
.
Ce comportement de traitement par lot inexact ne s'applique qu'aux applications mises à jour. Si vous avez défini targetSdkVersion
sur "18" ou moins, vos alarmes continueront de se comporter comme dans les versions précédentes lorsque vous les exécuterez sur Android 4.4.
Si votre application synchronise des données à l'aide de ContentResolver :
Lorsque vous définissez le paramètre targetSdkVersion
de votre application sur "19" ou une valeur supérieure, la création d'une synchronisation avec addPeriodicSync()
effectue vos opérations de synchronisation dans un intervalle flexible par défaut d'environ 4% de la période que vous spécifiez. Par exemple, si la fréquence d'interrogation est de 24 heures, votre opération de synchronisation peut se produire dans un créneau d'environ une heure chaque jour, au lieu d'être effectuée exactement à la même heure chaque jour.
Pour spécifier votre propre intervalle flexible pour les opérations de synchronisation, vous devez commencer à utiliser la nouvelle méthode requestSync()
. Pour en savoir plus, consultez la section ci-dessous sur les adaptateurs de synchronisation.
Ce comportement d'intervalle flexible ne s'applique qu'aux applications mises à jour. Si vous avez défini targetSdkVersion
sur "18" ou moins, vos requêtes de synchronisation existantes continueront de se comporter comme dans les versions précédentes lorsqu'elles s'exécutent sur Android 4.4.
Framework d'impression
Android inclut désormais un framework complet qui permet aux utilisateurs d'imprimer n'importe quel document à l'aide d'une imprimante connectée via Wi-Fi, Bluetooth ou d'autres services. Le système gère la transaction entre une application qui souhaite imprimer un document et les services qui envoient des tâches d'impression à une imprimante. Le framework android.print
fournit toutes les API nécessaires pour spécifier un document d'impression et l'envoyer au système pour l'impression. Les API dont vous avez réellement besoin pour une tâche d'impression donnée dépendent de votre contenu.
Impression de contenu générique
Si vous souhaitez imprimer du contenu à partir de votre UI en tant que document, vous devez d'abord créer une sous-classe de PrintDocumentAdapter
. Dans cette classe, vous devez implémenter quelques méthodes de rappel, y compris onLayout()
pour établir votre mise en page en fonction des propriétés d'impression fournies et onWrite()
pour sérialiser votre contenu imprimable dans un ParcelFileDescriptor
.
Pour écrire votre contenu dans ParcelFileDescriptor
, vous devez lui transmettre un PDF. Les nouvelles API PdfDocument
vous permettent de le faire facilement en fournissant un Canvas
à partir de getCanvas()
, sur lequel vous pouvez dessiner votre contenu imprimable. Écrivez ensuite le PdfDocument
dans le ParcelFileDescriptor
à l'aide de la méthode writeTo()
.
Une fois que vous avez défini votre implémentation pour PrintDocumentAdapter
, vous pouvez exécuter des tâches d'impression à la demande de l'utilisateur à l'aide de la méthode PrintManager
, print()
, qui utilise PrintDocumentAdapter
comme l'un de ses arguments.
Imprimer des images
Si vous souhaitez n'imprimer qu'une photo ou un autre bitmap, les API d'assistance de la bibliothèque d'assistance s'en chargent. Il vous suffit de créer une instance de PrintHelper
, de définir le mode de mise à l'échelle avec setScaleMode()
, puis de transmettre votre Bitmap
à printBitmap()
. Et voilà ! La bibliothèque gère toutes les interactions restantes avec le système pour transmettre le bitmap à l'imprimante.
Services d'impression
En tant qu'OEM d'imprimantes, vous pouvez utiliser le framework android.printservice
pour assurer l'interopérabilité avec vos imprimantes à partir d'appareils Android. Vous pouvez créer et distribuer des services d'impression sous forme d'APK, que les utilisateurs peuvent installer sur leurs appareils . Une application de service d'impression fonctionne principalement en tant que service sans interface graphique en sous-classant la classe PrintService
, qui reçoit les tâches d'impression du système et les communique à ses imprimantes à l'aide des protocoles appropriés.
Pour savoir comment imprimer le contenu de votre application, consultez Imprimer du contenu.
Fournisseur de SMS
Le fournisseur de contenu Telephony
(le "fournisseur de SMS") permet aux applications de lire et d'écrire des SMS et des MMS sur l'appareil. Il comprend des tableaux pour les SMS et MMS reçus, rédigés, envoyés, en attente, etc.
À partir d'Android 4.4, les paramètres système permettent aux utilisateurs de sélectionner une "application SMS par défaut". Une fois cette option sélectionnée, seule l'application de SMS par défaut peut écrire au fournisseur de SMS, et seule l'application de SMS par défaut reçoit la diffusion SMS_DELIVER_ACTION
lorsque l'utilisateur reçoit un SMS ou la diffusion WAP_PUSH_DELIVER_ACTION
lorsqu'il reçoit un MMS. L'application de SMS par défaut est chargée d'écrire des informations au fournisseur de SMS lorsqu'elle reçoit ou envoie un nouveau message.
Les autres applications qui ne sont pas sélectionnées comme application SMS par défaut ne peuvent lire que le fournisseur de SMS, mais peuvent également être averties lorsqu'un nouveau SMS arrive en écoutant la diffusion SMS_RECEIVED_ACTION
, qui est une diffusion non interrompable pouvant être envoyée à plusieurs applications. Cette diffusion est destinée aux applications qui, bien qu'elles ne soient pas sélectionnées comme application SMS par défaut, doivent lire des messages entrants spéciaux, par exemple pour effectuer la validation d'un numéro de téléphone.
Pour en savoir plus, consultez l'article de blog Préparer vos applications de SMS pour KitKat.
Connectivité et réseau sans fil
Émulation de carte hôte
Les applications Android peuvent désormais émuler les cartes NFC ISO14443-4 (ISO-DEP) qui utilisent des APDU pour l'échange de données (comme spécifié dans ISO7816-4). Cela permet à un appareil NFC équipé d'Android 4.4 d'émuler plusieurs cartes NFC en même temps, et à un terminal de paiement NFC ou à un autre lecteur NFC d'initier une transaction avec la carte NFC appropriée en fonction de l'identifiant d'application (AID).
Si vous souhaitez émuler une carte NFC qui utilise ces protocoles dans votre application, créez un composant de service basé sur la classe HostApduService
. Si votre application utilise plutôt un composant sécurisé pour l'émulation de carte, vous devez créer un service basé sur la classe OffHostApduService
, qui ne sera pas directement impliqué dans les transactions, mais qui est nécessaire pour enregistrer les AID qui doivent être gérés par le composant sécurisé.
Pour en savoir plus, consultez le guide sur l'émulation de carte NFC.
Mode lecteur NFC
Un nouveau mode lecteur NFC permet à une activité de limiter toute activité NFC à la lecture uniquement des types de tags qui l'intéressent lorsqu'elle est au premier plan. Vous pouvez activer le mode Lecteur pour votre activité avec enableReaderMode()
, en fournissant une implémentation de NfcAdapter.ReaderCallback
qui reçoit un rappel lorsque de nouvelles balises sont détectées.
Cette nouvelle fonctionnalité, associée à l'émulation de carte hôte, permet à Android de fonctionner aux deux extrémités d'une interface de paiement mobile: un appareil fonctionne comme un terminal de paiement (un appareil exécutant une activité en mode lecteur) et un autre appareil fonctionne comme un client de paiement (un appareil émulant une carte NFC).
Transmetteurs infrarouges
Lorsque vous exécutez votre application sur un appareil qui inclut un émetteur infrarouge (IR), vous pouvez désormais transmettre des signaux infrarouges à l'aide des API ConsumerIrManager
. Pour obtenir une instance de ConsumerIrManager
, appelez getSystemService()
avec CONSUMER_IR_SERVICE
comme argument. Vous pouvez ensuite interroger les fréquences IR compatibles de l'appareil avec getCarrierFrequencies()
et transmettre des signaux en transmettant la fréquence et le schéma de signal souhaités avec transmit()
.
Vous devez toujours vérifier d'abord si un appareil inclut un émetteur infrarouge en appelant hasIrEmitter()
. Toutefois, si votre application n'est compatible qu'avec les appareils qui en disposent, vous devez inclure un élément <uses-feature>
dans votre fichier manifeste pour "android.hardware.consumerir"
(FEATURE_CONSUMER_IR
).
Multimédia
Lecture adaptative
La lecture vidéo adaptative est désormais disponible avec les API MediaCodec
, ce qui permet de modifier facilement la résolution pendant la lecture sur un Surface
. Vous pouvez alimenter les images d'entrée du décodeur d'une nouvelle résolution, et la résolution des tampons de sortie change sans écart significatif.
Vous pouvez activer la lecture adaptative en ajoutant deux clés à MediaFormat
qui spécifient la résolution maximale requise par votre application du codec: KEY_MAX_WIDTH
et KEY_MAX_HEIGHT
. Une fois ces éléments ajoutés à votre MediaFormat
, transmettez le MediaFormat
à votre instance MediaCodec
avec configure()
.
Le codec effectuera une transition fluide entre les résolutions identiques ou inférieures à ces valeurs. Le codec peut également prendre en charge des résolutions supérieures aux valeurs maximales spécifiées (à condition qu'elles ne dépassent pas les limites des profils compatibles), mais les transitions vers des résolutions plus élevées peuvent ne pas être fluides.
Pour modifier la résolution lors du décodage d'une vidéo H.264, continuez à mettre en file d'attente des images à l'aide de MediaCodec.queueInputBuffer(), mais assurez-vous de fournir les nouvelles valeurs du paramètre de séquence (SPS) et du paramètre d'image (PPS) avec le frame d'actualisation instantanée du décodeur (IDR) dans un seul tampon.
Toutefois, avant de tenter de configurer votre codec pour la lecture adaptative, vous devez vérifier que l'appareil est compatible avec la lecture adaptative en appelant isFeatureSupported(String)
avec FEATURE_AdaptivePlayback
.
Remarque:La compatibilité avec la lecture adaptative est spécifique au fournisseur. Certains codecs peuvent nécessiter plus de mémoire pour des indices de résolution plus élevés. Par conséquent, vous devez définir les résolutions maximales en fonction du matériel source que vous décodez.
Codes temporels audio à la demande
Pour faciliter la synchronisation audio-vidéo, la nouvelle classe AudioTimestamp
fournit des informations sur la chronologie d'un "frame" spécifique dans un flux audio géré par AudioTrack
. Pour obtenir le code temporel le plus récent disponible, instanciez un objet AudioTimestamp
et transmettez-le à getTimestamp()
. Si la requête de code temporel aboutit, l'instance AudioTrack
est renseignée avec une position en unités de frame, ainsi que l'heure estimée à laquelle ce frame a été présenté ou est prévu d'être présenté.
Vous pouvez utiliser la valeur de nanoTime
dans AudioTimestamp
(qui est monotone) pour trouver le frame vidéo associé le plus proche de framePosition
. Vous pouvez ainsi supprimer, dupliquer ou interpoler des frames vidéo pour les faire correspondre à l'audio. Vous pouvez également déterminer le temps delta entre la valeur de nanoTime
et l'heure attendue d'un futur frame vidéo (en tenant compte du taux d'échantillonnage) pour prédire le frame audio attendu au même moment qu'un frame vidéo.
Lecteur d'images de surface
La nouvelle API ImageReader
vous permet d'accéder directement aux tampons d'image lorsqu'ils sont affichés dans un Surface
. Vous pouvez acquérir un ImageReader
avec la méthode statique newInstance()
. Appelez ensuite getSurface()
pour créer un Surface
et transmettre vos données d'image avec un producteur tel que MediaPlayer
ou MediaCodec
. Pour être informé lorsque de nouvelles images sont disponibles à partir de la surface, implémentez l'interface ImageReader.OnImageAvailableListener
et enregistrez-la avec setOnImageAvailableListener()
.
Lorsque vous dessinez du contenu dans votre Surface
, votre ImageReader.OnImageAvailableListener
reçoit un appel à onImageAvailable()
à chaque nouveau frame d'image disponible, ce qui vous fournit le ImageReader
correspondant. Vous pouvez utiliser ImageReader
pour acquérir les données d'image du frame en tant qu'objet Image
en appelant acquireLatestImage()
ou acquireNextImage()
.
L'objet Image
permet d'accéder directement au code temporel, au format, aux dimensions et aux données de pixel de l'image dans un ByteBuffer
. Toutefois, pour que la classe Image
puisse interpréter vos images, elles doivent être mises en forme selon l'un des types définis par des constantes dans ImageFormat
ou PixelFormat
.
Mesure de la valeur de crête et de la valeur RMS
Vous pouvez désormais interroger le pic et le RMS du flux audio actuel à partir de Visualizer
en créant une instance de Visualizer.MeasurementPeakRms
et en la transmettant à getMeasurementPeakRms()
. Lorsque vous appelez cette méthode, les valeurs de crête et RMS de l'Visualizer.MeasurementPeakRms
donnée sont définies sur les dernières valeurs mesurées.
Amélioration du volume
LoudnessEnhancer
est une nouvelle sous-classe de AudioEffect
qui vous permet d'augmenter le volume audible de votre MediaPlayer
ou AudioTrack
. Cela peut être particulièrement utile en association avec la nouvelle méthode getMeasurementPeakRms()
mentionnée ci-dessus, afin d'augmenter le volume des pistes audio parlées pendant la lecture d'autres contenus multimédias.
Télécommandes
Android 4.0 (niveau d'API 14) a introduit les API RemoteControlClient
qui permettent aux applications multimédias de consommer des événements de contrôleur multimédia à partir de clients distants, tels que les commandes multimédias sur l'écran de verrouillage. Les nouvelles API RemoteController
vous permettent désormais de créer votre propre télécommande, ce qui vous permet de créer de nouvelles applications et de nouveaux périphériques innovants pouvant contrôler la lecture de n'importe quelle application multimédia intégrée à RemoteControlClient
.
Pour créer une télécommande, vous pouvez implémenter votre interface utilisateur comme vous le souhaitez. Toutefois, pour transmettre les événements des boutons multimédias à l'application multimédia de l'utilisateur, vous devez créer un service qui étend la classe NotificationListenerService
et implémente l'interface RemoteController.OnClientUpdateListener
. Il est important d'utiliser NotificationListenerService
comme base, car il fournit les restrictions de confidentialité appropriées, qui exigent que les utilisateurs activent votre application en tant qu'écouteur de notifications dans les paramètres de sécurité du système.
La classe NotificationListenerService
inclut quelques méthodes abstraites que vous devez implémenter. Toutefois, si vous ne vous intéressez qu'aux événements du contrôleur multimédia pour gérer la lecture multimédia, vous pouvez laisser votre implémentation vide et vous concentrer sur les méthodes RemoteController.OnClientUpdateListener
.
Évaluations provenant de télécommandes
Android 4.4 s'appuie sur les fonctionnalités existantes des clients de télécommande (applications qui reçoivent des événements de contrôle multimédia avec RemoteControlClient
) en permettant aux utilisateurs d'évaluer le titre en cours depuis la télécommande.
La nouvelle classe Rating
encapsule les informations sur une note utilisateur. Une note est définie par son style (RATING_HEART
, RATING_THUMB_UP_DOWN
, RATING_3_STARS
, RATING_4_STARS
, RATING_5_STARS
ou RATING_PERCENTAGE
) et la valeur de note appropriée pour ce style.
Pour autoriser les utilisateurs à évaluer vos titres à l'aide d'une télécommande:
- Indiquez que vous souhaitez exposer l'UI de notation à l'utilisateur (le cas échéant) en ajoutant l'indicateur
FLAG_KEY_MEDIA_RATING
danssetTransportControlFlags()
. - Appelez
editMetadata()
pour récupérer unRemoteControlClient.MetadataEditor
et transmettez-le àRATING_KEY_BY_USER
avecaddEditableKey()
. - Spécifiez ensuite le style d'évaluation en appelant
putObject()
et en lui transmettantRATING_KEY_BY_USER
comme clé et l'un des styles d'évaluation ci-dessus comme valeur.
Pour recevoir un rappel lorsque l'utilisateur modifie la note à partir de la télécommande, implémentez la nouvelle interface RemoteControlClient.OnMetadataUpdateListener
et transmettez une instance à setMetadataUpdateListener()
. Lorsque l'utilisateur modifie la note, votre RemoteControlClient.OnMetadataUpdateListener
reçoit un appel à onMetadataUpdate()
, en transmettant RATING_KEY_BY_USER
comme clé et un objet Rating
comme valeur.
Sous-titres
VideoView
est désormais compatible avec les pistes de sous-titres WebVTT lors de la lecture de vidéos HTTP Live Streaming (HLS). Les pistes de sous-titres sont affichées en fonction des préférences de sous-titres définies par l'utilisateur dans les paramètres système.
Vous pouvez également fournir à VideoView
vos pistes de sous-titres WebVTT à l'aide de la méthode addSubtitleSource()
. Cette méthode accepte un InputStream
qui contient les données de sous-titres et un objet MediaFormat
qui spécifie le format des données de sous-titres, que vous pouvez spécifier à l'aide de createSubtitleFormat()
. Ces sous-titres s'affichent également au-dessus de la vidéo en fonction des préférences de l'utilisateur.
Si vous n'utilisez pas VideoView
pour afficher votre contenu vidéo, vous devez faire en sorte que votre superposition de sous-titres corresponde le plus possible aux préférences de l'utilisateur concernant les sous-titres. Une nouvelle API CaptioningManager
vous permet d'interroger les préférences de l'utilisateur concernant les sous-titres, y compris les styles définis par CaptioningManager.CaptionStyle
, tels que la typographie et la couleur. Si l'utilisateur ajuste certaines préférences une fois votre vidéo lancée, vous devez écouter les modifications apportées aux préférences en enregistrant une instance de CaptioningManager.CaptioningChangeListener
pour recevoir un rappel lorsque l'une des préférences change, puis mettre à jour vos sous-titres si nécessaire.
Animation et graphismes
Scènes et transitions
Le nouveau framework android.transition
fournit des API qui facilitent les animations entre les différents états de votre interface utilisateur. Une fonctionnalité clé est la possibilité de définir des états distincts de votre UI, appelés "scènes", en créant une mise en page distincte pour chacun d'eux. Lorsque vous souhaitez animer une scène à partir d'une autre, exécutez une "transition", qui calcule l'animation nécessaire pour passer de la mise en page de la scène actuelle à celle de la scène suivante.
Pour effectuer une transition entre deux scènes, vous devez généralement effectuer les opérations suivantes:
- Spécifiez le
ViewGroup
contenant les composants d'interface utilisateur que vous souhaitez modifier. - Spécifiez la mise en page représentant le résultat final de la modification (la scène suivante).
- Spécifiez le type de transition qui doit animer le changement de mise en page.
- Exécutez la transition.
Vous pouvez utiliser un objet Scene
pour effectuer les étapes 1 et 2. Un Scene
contient des métadonnées décrivant les propriétés d'une mise en page nécessaires à l'exécution d'une transition, y compris la vue parente de la scène et la mise en page de la scène. Vous pouvez créer un Scene
à l'aide d'un constructeur de classe ou de la méthode statique getSceneForLayout()
.
Vous devez ensuite utiliser TransitionManager
pour effectuer les étapes 3 et 4. Vous pouvez par exemple transmettre votre Scene
à la méthode statique go()
. Cela permet de trouver la vue parente de la scène dans la mise en page actuelle et d'effectuer une transition sur les vues enfants afin d'atteindre la mise en page définie par Scene
.
Vous n'avez pas besoin de créer un objet Scene
, mais vous pouvez appeler beginDelayedTransition()
en spécifiant un ViewGroup
contenant les vues que vous souhaitez modifier. Ajoutez, supprimez ou reconfigurez ensuite les vues cibles. Une fois que le système a mis en page les modifications, une transition commence à animer toutes les vues concernées.
Pour un contrôle supplémentaire, vous pouvez définir des ensembles de transitions qui doivent se produire entre des scènes prédéfinies à l'aide d'un fichier XML dans le répertoire res/transition/
de votre projet. Dans un élément <transitionManager>
, spécifiez une ou plusieurs balises <transition>
qui spécifient chacune une scène (une référence à un fichier de mise en page) et la transition à appliquer lors de l'entrée et/ou de la sortie de cette scène. Ensuite, gonflez cet ensemble de transitions à l'aide de inflateTransitionManager()
. Utilisez le TransitionManager
renvoyé pour exécuter chaque transition avec transitionTo()
, en transmettant un Scene
représenté par l'une des balises <transition>
. Vous pouvez également définir des ensembles de transitions de manière programmatique avec les API TransitionManager
.
Lorsque vous spécifiez une transition, vous pouvez utiliser plusieurs types prédéfinis définis par des sous-classes de Transition
, comme Fade
et ChangeBounds
. Si vous ne spécifiez pas de type de transition, le système utilise AutoTransition
par défaut, qui estompe, déplace et redimensionne automatiquement les vues si nécessaire. Vous pouvez également créer des transitions personnalisées en étendant l'une de ces classes pour effectuer les animations comme vous le souhaitez. Une transition personnalisée peut suivre toutes les modifications de propriété souhaitées et créer n'importe quelle animation en fonction de ces modifications. Par exemple, vous pouvez fournir une sous-classe de Transition
qui écoute les modifications apportées à la propriété "rotation" d'une vue, puis animer les modifications.
Pour en savoir plus, consultez la documentation TransitionManager
.
Mise en pause de l'animateur
Les API Animator
vous permettent désormais de mettre en pause et de reprendre une animation en cours à l'aide des méthodes pause()
et resume()
.
Pour suivre l'état d'une animation, vous pouvez implémenter l'interface Animator.AnimatorPauseListener
, qui fournit des rappels lorsqu'une animation est mise en pause et reprise: pause()
et resume()
. Ajoutez ensuite l'écouteur à un objet Animator
avec addPauseListener()
.
Vous pouvez également sous-classer la classe abstraite AnimatorListenerAdapter
, qui inclut désormais des implémentations vides pour les rappels de suspension et de reprise définis par Animator.AnimatorPauseListener
.
Bitmaps réutilisables
Vous pouvez désormais réutiliser n'importe quel bitmap modifiable dans BitmapFactory
pour décoder n'importe quel autre bitmap, même si le nouveau bitmap est d'une taille différente, à condition que le nombre d'octets résultant du bitmap décodé (disponible à partir de getByteCount()
) soit inférieur ou égal au nombre d'octets alloués du bitmap réutilisé (disponible à partir de getAllocationByteCount()
). Pour en savoir plus, consultez inBitmap
Les nouvelles API pour Bitmap
permettent une reconfiguration similaire pour la réutilisation en dehors de BitmapFactory
(pour la génération manuelle de bitmaps ou la logique de décodage personnalisée). Vous pouvez désormais définir les dimensions d'un bitmap avec les méthodes setHeight()
et setWidth()
, et spécifier un nouveau Bitmap.Config
avec setConfig()
sans affecter l'allocation de bitmap sous-jacente. La méthode reconfigure()
permet également de combiner facilement ces modifications en un seul appel.
Toutefois, vous ne devez pas reconfigurer un bitmap actuellement utilisé par le système de vue, car le tampon de pixels sous-jacent ne sera pas remappé de manière prévisible.
Contenu généré par l'utilisateur
Storage Access Framework
Sur les versions précédentes d'Android, si vous souhaitez que votre application récupère un type de fichier spécifique à partir d'une autre application, elle doit appeler un intent avec l'action ACTION_GET_CONTENT
. Cette action reste le moyen approprié de demander un fichier que vous souhaitez importer dans votre application. Toutefois, Android 4.4 introduit l'action ACTION_OPEN_DOCUMENT
, qui permet à l'utilisateur de sélectionner un fichier d'un type spécifique et d'accorder à votre application un accès en lecture à long terme à ce fichier (éventuellement avec un accès en écriture) sans l'importer dans votre application.
Si vous développez une application qui fournit des services de stockage pour les fichiers (tel qu'un service de sauvegarde dans le cloud), vous pouvez participer à cette UI unifiée pour sélectionner des fichiers en implémentant un fournisseur de contenu en tant que sous-classe de la nouvelle classe DocumentsProvider
. Votre sous-classe de DocumentsProvider
doit inclure un filtre d'intent qui accepte l'action PROVIDER_INTERFACE
("android.content.action.DOCUMENTS_PROVIDER"
). Vous devez ensuite implémenter les quatre méthodes abstraites dans DocumentsProvider
:
queryRoots()
- Cette opération doit renvoyer un
Cursor
qui décrit tous les répertoires racine de votre espace de stockage de documents, à l'aide des colonnes définies dansDocumentsContract.Root
. queryChildDocuments()
- Cette opération doit renvoyer un
Cursor
qui décrit tous les fichiers du répertoire spécifié, à l'aide des colonnes définies dansDocumentsContract.Document
. queryDocument()
- Doit renvoyer un
Cursor
qui décrit le fichier spécifié, à l'aide des colonnes définies dansDocumentsContract.Document
. openDocument()
- Cette opération doit renvoyer un
ParcelFileDescriptor
représentant le fichier spécifié. Le système appelle cette méthode une fois que l'utilisateur a sélectionné un fichier et que l'application cliente demande à y accéder en appelantopenFileDescriptor()
.
Pour en savoir plus, consultez le guide Storage Access Framework.
Accès au stockage externe
Vous pouvez désormais lire et écrire des fichiers spécifiques à l'application sur des supports de stockage externes secondaires, par exemple lorsqu'un appareil fournit à la fois un espace de stockage émulé et une carte SD. La nouvelle méthode getExternalFilesDirs()
fonctionne de la même manière que la méthode getExternalFilesDir()
existante, sauf qu'elle renvoie un tableau d'objets File
. Avant de lire ou d'écrire dans l'un des chemins de retour de cette méthode, transmettez l'objet File
à la nouvelle méthode getStorageState()
pour vérifier que l'espace de stockage est actuellement disponible.
D'autres méthodes d'accès au répertoire de cache et au répertoire OBB spécifiques à votre application disposent désormais de versions correspondantes qui permettent d'accéder aux appareils de stockage secondaire: getExternalCacheDirs()
et getObbDirs()
, respectivement.
La première entrée du tableau File
renvoyé est considérée comme le stockage externe principal de l'appareil, qui est identique à l'File
renvoyé par les méthodes existantes telles que getExternalFilesDir()
.
Remarque:À partir d'Android 4.4, la plate-forme n'exige plus que votre application acquière WRITE_EXTERNAL_STORAGE
ou READ_EXTERNAL_STORAGE
lorsque vous ne devez accéder qu'aux régions de stockage externe spécifiques à votre application à l'aide des méthodes ci-dessus. Toutefois, les autorisations sont requises si vous souhaitez accéder aux régions partageables du stockage externe, fournies par getExternalStoragePublicDirectory()
.
Adaptateurs de synchronisation
La nouvelle méthode requestSync()
de ContentResolver
simplifie certaines étapes de la procédure de définition d'une requête de synchronisation pour votre ContentProvider
en encapsulant les requêtes dans le nouvel objet SyncRequest
, que vous pouvez créer avec SyncRequest.Builder
. Les propriétés de SyncRequest
offrent les mêmes fonctionnalités que les appels de synchronisation ContentProvider
existants, mais permettent de spécifier qu'une synchronisation doit être abandonnée si le réseau est limité en débit, en activant setDisallowMetered()
.
Entrée utilisateur
Nouveaux types de capteurs
Le nouveau capteur TYPE_GEOMAGNETIC_ROTATION_VECTOR
fournit des données de vecteur de rotation basées sur un magnétomètre, ce qui constitue une alternative utile au capteur TYPE_ROTATION_VECTOR
lorsqu'un gyroscope n'est pas disponible ou lorsqu'il est utilisé avec des événements de capteur groupés pour enregistrer l'orientation de l'appareil lorsque le téléphone est en veille. Ce capteur nécessite moins d'énergie que TYPE_ROTATION_VECTOR
, mais peut être sujet à des données d'événements bruyantes et est le plus efficace lorsque l'utilisateur est à l'extérieur.
Android est désormais également compatible avec les capteurs de pas intégrés au matériel:
TYPE_STEP_DETECTOR
- Ce capteur déclenche un événement chaque fois que l'utilisateur fait un pas. À chaque étape de l'utilisateur, ce capteur envoie un événement avec une valeur de 1,0 et un code temporel indiquant quand l'étape s'est produite.
TYPE_STEP_COUNTER
- Ce capteur déclenche également un événement à chaque pas détecté, mais fournit le nombre total de pas cumulés depuis la première inscription de ce capteur par une application.
Notez que ces deux capteurs de pas n'affichent pas toujours les mêmes résultats. Les événements TYPE_STEP_COUNTER
se produisent avec une latence plus élevée que ceux de TYPE_STEP_DETECTOR
, mais cela est dû au fait que l'algorithme TYPE_STEP_COUNTER
effectue plus de traitement pour éliminer les faux positifs. Par conséquent, l'TYPE_STEP_COUNTER
peut mettre plus de temps à envoyer des événements, mais ses résultats devraient être plus précis.
Les deux capteurs de pas sont dépendants du matériel (le Nexus 5 est le premier appareil à les prendre en charge). Vous devez donc vérifier la disponibilité avec hasSystemFeature()
, à l'aide des constantes FEATURE_SENSOR_STEP_DETECTOR
et FEATURE_SENSOR_STEP_COUNTER
.
Événements de capteur groupés
Pour mieux gérer l'alimentation de l'appareil, les API SensorManager
vous permettent désormais de spécifier la fréquence à laquelle vous souhaitez que le système envoie des lots d'événements de capteur à votre application. Cela ne réduit pas le nombre d'événements de capteur réels disponibles pour votre application pendant une période donnée, mais réduit la fréquence à laquelle le système appelle votre SensorEventListener
avec des mises à jour de capteur. Autrement dit, au lieu de transmettre chaque événement à votre application au moment où il se produit, le système enregistre tous les événements qui se produisent sur une période donnée, puis les transmet à votre application en une seule fois.
Pour fournir le traitement par lot, la classe SensorManager
ajoute deux nouvelles versions de la méthode registerListener()
qui vous permettent de spécifier la "latence maximale des rapports". Ce nouveau paramètre spécifie le délai maximal que votre SensorEventListener
tolérera pour la diffusion de nouveaux événements de capteur. Par exemple, si vous spécifiez une latence de traitement par lot d'une minute, le système transmettra l'ensemble récent d'événements par lot à un intervalle maximal d'une minute en effectuant des appels consécutifs à votre méthode onSensorChanged()
, une fois pour chaque événement traité par lot. Les événements du capteur ne seront jamais retardés plus longtemps que la valeur de latence maximale du rapport, mais ils peuvent arriver plus tôt si d'autres applications ont demandé une latence plus courte pour le même capteur.
Toutefois, sachez que le capteur ne transmettra à votre application les événements groupés en fonction de votre latence de rapport que lorsque le processeur est actif. Bien qu'un capteur matériel compatible avec le traitement par lot continue de collecter des événements de capteur lorsque le processeur est en veille, il ne le réveille pas pour transmettre les événements groupés à votre application. Lorsque la mémoire du capteur est saturée, il commence à supprimer les événements les plus anciens pour enregistrer les plus récents. Pour éviter de perdre des événements, réveillez l'appareil avant que le capteur ne remplisse sa mémoire, puis appelez flush()
pour capturer le dernier lot d'événements. Pour estimer quand la mémoire sera pleine et doit être effacée, appelez getFifoMaxEventCount()
pour obtenir le nombre maximal d'événements de capteur qu'elle peut enregistrer, puis divisez ce nombre par la fréquence à laquelle votre application souhaite chaque événement. Utilisez ce calcul pour définir des alarmes de réveil avec AlarmManager
qui appellent votre Service
(qui implémente SensorEventListener
) pour vider le capteur.
Remarque:Tous les appareils ne sont pas compatibles avec le traitement par lot des événements de capteur, car cette fonctionnalité nécessite la prise en charge par le capteur matériel. Toutefois, à partir d'Android 4.4, vous devez toujours utiliser les nouvelles méthodes registerListener()
. En effet, si l'appareil n'est pas compatible avec le traitement par lot, le système ignore correctement l'argument de latence de traitement par lot et envoie des événements de capteur en temps réel.
Identités des contrôleurs
Android identifie désormais chaque manette connectée à l'aide d'un entier unique que vous pouvez interroger avec getControllerNumber()
. Vous pouvez ainsi associer plus facilement chaque manette à un joueur différent dans un jeu. Le numéro de chaque contrôleur peut changer si l'utilisateur le déconnecte, le connecte ou le reconfigure. Vous devez donc suivre le numéro de contrôleur correspondant à chaque périphérique d'entrée en enregistrant une instance de InputManager.InputDeviceListener
. Appelez ensuite getControllerNumber()
pour chaque InputDevice
lorsqu'une modification se produit.
Les appareils connectés fournissent désormais également des ID produit et fournisseur disponibles dans getProductId()
et getVendorId()
. Si vous devez modifier vos mappages de touches en fonction de l'ensemble de touches disponibles sur un appareil, vous pouvez interroger l'appareil pour vérifier si certaines touches sont disponibles avec hasKeys(int...)
.
Interface utilisateur
Mode plein écran immersif
Pour fournir à votre application une mise en page qui remplit l'intégralité de l'écran, le nouveau drapeau SYSTEM_UI_FLAG_IMMERSIVE
pour setSystemUiVisibility()
(associé à SYSTEM_UI_FLAG_HIDE_NAVIGATION
) active un nouveau mode plein écran immersif. Lorsque le mode plein écran immersif est activé, votre activité continue de recevoir tous les événements tactiles. L'utilisateur peut afficher les barres système en balayant l'écran vers l'intérieur dans la zone où elles apparaissent normalement. Cette action efface l'indicateur SYSTEM_UI_FLAG_HIDE_NAVIGATION
(et l'indicateur SYSTEM_UI_FLAG_FULLSCREEN
, le cas échéant) afin que les barres système restent visibles. Toutefois, si vous souhaitez que les barres système se cachent à nouveau au bout de quelques instants, vous pouvez utiliser l'indicateur SYSTEM_UI_FLAG_IMMERSIVE_STICKY
.
Barres système transparentes
Vous pouvez désormais rendre les barres système partiellement transparentes avec les nouveaux thèmes Theme.Holo.NoActionBar.TranslucentDecor
et Theme.Holo.Light.NoActionBar.TranslucentDecor
. En activant les barres système transparentes, votre mise en page remplira la zone située derrière les barres système. Vous devez donc également activer fitsSystemWindows
pour la partie de votre mise en page qui ne doit pas être couverte par les barres système.
Si vous créez un thème personnalisé, définissez l'un de ces thèmes comme thème parent ou incluez les propriétés de style windowTranslucentNavigation
et windowTranslucentStatus
dans votre thème.
Écouteur de notification amélioré
Android 4.3 a ajouté les API NotificationListenerService
, qui permettent aux applications de recevoir des informations sur les nouvelles notifications lorsqu'elles sont publiées par le système. Sous Android 4.4, les écouteurs de notification peuvent récupérer des métadonnées supplémentaires pour la notification et des informations complètes sur les actions de la notification:
Le nouveau champ Notification.extras
inclut un Bundle
pour fournir à votre outil de création de notifications des métadonnées supplémentaires telles que EXTRA_TITLE
et EXTRA_PICTURE
.
La nouvelle classe Notification.Action
définit les caractéristiques d'une action associée à la notification, que vous pouvez récupérer à partir du nouveau champ actions
.
Mise en miroir des drawables pour les mises en page de droite à gauche
Dans les versions précédentes d'Android, si votre application inclut des images dont l'orientation horizontale doit être inversée pour les mises en page de droite à gauche, vous devez inclure l'image en miroir dans un répertoire de ressources drawables-ldrtl/
. Le système peut désormais refléter automatiquement les images en activant l'attribut autoMirrored
sur une ressource drawable ou en appelant setAutoMirrored()
. Lorsqu'il est activé, Drawable
est automatiquement mis en miroir lorsque la direction de la mise en page est de droite à gauche.
Accessibilité
La classe View
vous permet désormais de déclarer des "régions en direct" pour des parties de votre UI qui se mettent à jour de manière dynamique avec un nouveau contenu textuel, en ajoutant le nouvel attribut accessibilityLiveRegion
à votre mise en page XML ou en appelant setAccessibilityLiveRegion()
. Par exemple, un écran de connexion contenant un champ de texte qui affiche une notification "mot de passe incorrect" doit être marqué en tant que zone live. Le lecteur d'écran récitera alors le message lorsqu'il changera.
Les applications qui fournissent un service d'accessibilité peuvent désormais également améliorer leurs fonctionnalités grâce à de nouvelles API qui fournissent des informations sur les collections de vues, telles que les vues de liste ou de grille à l'aide de AccessibilityNodeInfo.CollectionInfo
et AccessibilityNodeInfo.CollectionItemInfo
.
Autorisations des applications
Voici les nouvelles autorisations que votre application doit demander avec la balise <uses-permission>
pour utiliser certaines nouvelles API:
INSTALL_SHORTCUT
- Permet à une application d'installer un raccourci dans le lanceur d'applications
UNINSTALL_SHORTCUT
- Permet à une application de désinstaller un raccourci dans le lanceur d'applications
TRANSMIT_IR
- Permet à une application d'utiliser l'émetteur infrarouge de l'appareil, le cas échéant
Remarque:À partir d'Android 4.4, la plate-forme n'exige plus que votre application acquière WRITE_EXTERNAL_STORAGE
ou READ_EXTERNAL_STORAGE
lorsque vous souhaitez accéder aux régions de stockage externe spécifiques à votre application à l'aide de méthodes telles que getExternalFilesDir()
. Toutefois, les autorisations sont toujours requises si vous souhaitez accéder aux régions partageables du stockage externe, fournies par getExternalStoragePublicDirectory()
.
Fonctionnalités de l'appareil
Vous trouverez ci-dessous les nouvelles fonctionnalités d'appareil que vous pouvez déclarer avec la balise <uses-feature>
pour déclarer les exigences de votre application et activer le filtrage sur Google Play ou le vérifier au moment de l'exécution:
FEATURE_CONSUMER_IR
- L'appareil peut communiquer avec des appareils infrarouges grand public.
FEATURE_DEVICE_ADMIN
- L'appareil est compatible avec l'application des règles relatives aux appareils via des administrateurs d'appareils.
FEATURE_NFC_HOST_CARD_EMULATION
- L'appareil est compatible avec l'émulation de carte NFC basée sur l'hôte.
FEATURE_SENSOR_STEP_COUNTER
- L'appareil inclut un compteur de pas matériel.
FEATURE_SENSOR_STEP_DETECTOR
- L'appareil inclut un détecteur de pas matériel.
Pour obtenir un aperçu détaillé de toutes les modifications apportées aux API dans Android 4.4, consultez le rapport de différences des API.