API Android 4.4

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:

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:

  1. Spécifiez le ViewGroup contenant les composants d'interface utilisateur que vous souhaitez modifier.
  2. Spécifiez la mise en page représentant le résultat final de la modification (la scène suivante).
  3. Spécifiez le type de transition qui doit animer le changement de mise en page.
  4. 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 dans DocumentsContract.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 dans DocumentsContract.Document.
queryDocument()
Doit renvoyer un Cursor qui décrit le fichier spécifié, à l'aide des colonnes définies dans DocumentsContract.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 appelant openFileDescriptor().

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.