API Android 4.2

Niveau d'API: 17

Android 4.2 (JELLY_BEAN_MR1) est une mise à jour de la version Jelly Bean qui offre de nouvelles fonctionnalités aux utilisateurs et aux développeurs d'applications. Ce document présente les nouvelles API les plus importantes et les plus utiles pour les développeurs.

En tant que développeur d'applications, vous devez télécharger l'image système Android 4.2 et la plate-forme SDK à partir de SDK Manager dès que possible. Si vous ne disposez pas d'un appareil exécutant Android 4.2 sur lequel tester votre application, utilisez l'image système Android 4.2 pour tester votre application sur Android Emulator. Créez ensuite vos applications sur la plate-forme Android 4.2 pour commencer à utiliser les dernières API.

Afin d'optimiser votre application pour les appareils équipés d'Android 4.2, vous devez définir targetSdkVersion sur "17", l'installer sur une image système Android 4.2, la tester, puis publier une mise à jour avec cette modification.

Vous pouvez utiliser des API dans Android 4.2 tout en prenant en charge les anciennes versions en ajoutant à votre code des conditions qui vérifient le niveau d'API du système avant d'exécuter des API non compatibles avec votre minSdkVersion. Pour en savoir plus sur le maintien de la rétrocompatibilité, consultez la page Créer des interfaces utilisateur rétrocompatibles.

Pour en savoir plus sur le fonctionnement des niveaux d'API, consultez Qu'est-ce que le niveau d'API ?

Changements de comportement importants

Si vous avez déjà publié une application pour Android, tenez compte des modifications suivantes qui peuvent affecter son comportement:

  • Les fournisseurs de contenu ne sont plus exportés par défaut. C'est-à-dire que la valeur par défaut de l'attribut android:exported est désormais “false". S'il est important que d'autres applications puissent accéder à votre fournisseur de contenu, vous devez maintenant définir explicitement android:exported="true".

    Cette modification ne prend effet que si vous définissez android:targetSdkVersion ou android:minSdkVersion sur 17 ou une valeur supérieure. Sinon, la valeur par défaut est toujours “true", même sur Android 4.2 ou version ultérieure.

  • Par rapport aux versions précédentes d'Android, les résultats de localisation de l'utilisateur peuvent être moins précis si votre application demande l'autorisation ACCESS_COARSE_LOCATION, mais pas l'autorisation ACCESS_FINE_LOCATION.

    Pour répondre aux attentes des utilisateurs en termes de confidentialité lorsque votre application demande l'autorisation d'accéder à une position approximative (et non précise), le système ne fournit pas d'estimation de la position de l'utilisateur plus précise qu'un pâté de maisons.

  • Certains paramètres d'appareil définis par Settings.System sont désormais en lecture seule. Si votre application tente d'écrire des modifications apportées aux paramètres définis dans Settings.System qui ont été déplacés vers Settings.Global, l'opération d'écriture échouera en mode silencieux sur Android 4.2 ou version ultérieure.

    Même si votre valeur pour android:targetSdkVersion et android:minSdkVersion est inférieure à 17, votre application ne peut pas modifier les paramètres qui ont été déplacés vers Settings.Global lorsqu'elle est exécutée sur Android 4.2 ou version ultérieure.

  • Si votre application utilise WebView, Android 4.2 ajoute une couche de sécurité supplémentaire pour vous permettre de lier JavaScript à votre code Android de manière plus sécurisée. Si vous définissez targetSdkVersion sur 17 ou plus, vous devez maintenant ajouter l'annotation @JavascriptInterface à toutes les méthodes que vous souhaitez rendre disponibles pour votre JavaScript (la méthode doit également être publique). Si vous ne fournissez pas l'annotation, la méthode n'est pas accessible par une page Web dans votre WebView sur Android 4.2 ou version ultérieure. Si vous définissez targetSdkVersion sur 16 ou une valeur inférieure, l'annotation n'est pas obligatoire, mais nous vous recommandons de mettre à jour votre version cible et d'ajouter l'annotation pour plus de sécurité.

    En savoir plus sur la liaison de code JavaScript au code Android

Daydream

Daydream est un nouveau mode économiseur d'écran interactif pour les appareils Android. Il s'active automatiquement lorsque l'appareil est inséré dans une station d'accueil ou lorsqu'il est laissé inactif alors qu'il est branché à un chargeur (au lieu d'éteindre l'écran). Daydream affiche un seul rêve à la fois. Il peut s'agir d'un affichage passif purement visuel qui se ferme au toucher, ou d'un écran interactif et réactif à la suite complète d'événements d'entrée. Vos rêves s'exécutent dans le processus de votre application et bénéficient d'un accès complet au kit UI Android, y compris aux vues, aux mises en page et aux animations. Ils sont donc plus flexibles et puissants que les fonds d'écran animés ou les widgets d'application.

Vous pouvez créer un rêve pour Daydream en implémentant une sous-classe de DreamService. Les API DreamService sont conçues pour être semblables à celles de Activity. Pour spécifier l'interface utilisateur de votre rêve, transmettez un ID de ressource de mise en page ou View à setContentView() à tout moment après avoir créé une fenêtre, par exemple à partir du rappel onAttachedToWindow().

La classe DreamService fournit d'autres méthodes de rappel de cycle de vie importantes en plus des API Service de base, telles que onDreamingStarted(), onDreamingStopped() et onDetachedFromWindow(). Vous ne pouvez pas lancer un DreamService à partir de votre application. Il est lancé automatiquement par le système.

Si votre rêve est interactif, vous pouvez démarrer une activité à partir de votre rêve afin de rediriger l'utilisateur vers l'interface utilisateur complète de votre application pour plus de détails ou de contrôle. Vous pouvez utiliser finish() pour mettre fin au rêve afin que l'utilisateur puisse voir la nouvelle activité.

Pour rendre l'écran de veille interactif disponible pour le système, déclarez votre DreamService avec un élément <service> dans votre fichier manifeste. Vous devez ensuite inclure un filtre d'intent avec l'action "android.service.dreams.DreamService". Par exemple :

<service android:name=".MyDream" android:exported="true"
    android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

Veuillez noter d'autres méthodes utiles dans DreamService:

  • setInteractive(boolean) détermine si le rêve reçoit ou sort des événements d'entrée immédiatement après l'entrée de l'utilisateur. Si le rêve est interactif, l'utilisateur peut utiliser les boutons Retour ou Accueil pour le quitter, ou vous pouvez appeler finish() pour l'arrêter.
  • Si vous souhaitez un affichage totalement immersif, vous pouvez appeler setFullscreen() pour masquer la barre d'état.
  • Avant le démarrage de l'application Daydream, l'écran s'assombrit pour signaler à l'utilisateur que le délai d'inactivité approche. Appeler setScreenBright(true) vous permet de régler l'écran à sa luminosité habituelle.

Pour en savoir plus, consultez la documentation DreamService.

Écrans secondaires

Android permet désormais à votre application d'afficher un contenu unique sur des écrans supplémentaires connectés à l'appareil de l'utilisateur via une connexion filaire ou Wi-Fi. Pour créer un contenu unique pour un écran secondaire, étendez la classe Presentation et implémentez le rappel onCreate(). Dans onCreate(), spécifiez votre UI pour l'écran secondaire en appelant setContentView(). En tant qu'extension de la classe Dialog, la classe Presentation fournit la région dans laquelle votre application peut afficher une UI unique sur l'écran secondaire.

Pour détecter les écrans secondaires sur lesquels vous pouvez afficher votre Presentation, utilisez l'API DisplayManager ou MediaRouter. Bien que les API DisplayManager vous permettent d'énumérer plusieurs écrans pouvant être connectés en même temps, vous devez généralement utiliser MediaRouter pour accéder rapidement à l'écran par défaut du système pour les présentations.

Pour obtenir l'affichage par défaut de votre présentation, appelez MediaRouter.getSelectedRoute() et transmettez-lui ROUTE_TYPE_LIVE_VIDEO. Cette opération renvoie un objet MediaRouter.RouteInfo qui décrit l'itinéraire actuellement sélectionné par le système pour les présentations vidéo. Si MediaRouter.RouteInfo n'est pas nul, appelez getPresentationDisplay() pour obtenir le Display représentant l'écran connecté.

Vous pouvez ensuite afficher votre présentation en transmettant l'objet Display à un constructeur pour votre classe Presentation. Votre présentation va maintenant apparaître sur l'écran secondaire.

Pour détecter au moment de l'exécution lorsqu'un nouvel écran a été connecté, créez une instance de MediaRouter.SimpleCallback dans laquelle vous implémentez la méthode de rappel onRoutePresentationDisplayChanged(), que le système appelle lorsqu'un nouvel écran de présentation est connecté. Ensuite, enregistrez le MediaRouter.SimpleCallback en le transmettant à MediaRouter.addCallback() avec le type de route ROUTE_TYPE_LIVE_VIDEO. Lorsque vous recevez un appel à onRoutePresentationDisplayChanged(), appelez simplement MediaRouter.getSelectedRoute() comme indiqué ci-dessus.

Pour optimiser davantage l'interface utilisateur de votre Presentation pour les écrans secondaires, vous pouvez appliquer un thème différent en spécifiant l'attribut android:presentationTheme dans le <style> que vous avez appliqué à votre application ou à votre activité.

N'oubliez pas que les écrans connectés à l'appareil de l'utilisateur ont souvent une taille d'écran plus grande et probablement une densité d'écran différente. Étant donné que les caractéristiques d'écran peuvent varier, vous devez fournir des ressources optimisées spécifiquement pour ces grands écrans. Si vous devez demander des ressources supplémentaires à votre Presentation, appelez getContext().getResources() pour obtenir l'objet Resources correspondant à l'affichage. Vous obtiendrez ainsi les ressources de votre application les plus adaptées à la taille et à la densité de l'écran de l'écran secondaire.

Pour en savoir plus et obtenir des exemples de code, consultez la documentation de la classe Presentation.

Widgets pour l'écran de verrouillage

Android permet désormais aux utilisateurs d'ajouter des widgets d'application à l'écran de verrouillage. Pour que votre widget d'application soit disponible sur l'écran de verrouillage, ajoutez l'attribut android:widgetCategory qui spécifie le AppWidgetProviderInfo à votre fichier XML. Cet attribut accepte deux valeurs: home_screen et keyguard. Par défaut, l'attribut est défini sur home_screen afin que les utilisateurs puissent ajouter votre widget d'application à l'écran d'accueil. Si vous souhaitez que le widget d'application soit également disponible sur l'écran de verrouillage, ajoutez la valeur keyguard:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:widgetCategory="keyguard|home_screen">
</appwidget-provider>

Vous devez également spécifier une mise en page initiale pour votre widget d'application lorsque vous êtes sur l'écran de verrouillage avec l'attribut android:initialKeyguardLayout. Cela fonctionne de la même manière que android:initialLayout, en ce sens qu'il fournit une mise en page qui peut apparaître immédiatement jusqu'à ce que le widget de votre application soit initialisé et en mesure de mettre à jour la mise en page.

Pour en savoir plus sur la création de widgets d'application pour l'écran de verrouillage, y compris sur la taille appropriée de votre widget d'application lorsque l'écran de verrouillage est activé, consultez le guide Widgets d'application.

Fonctionnalité multi-utilisateur

Android permet désormais de disposer de plusieurs espaces utilisateur sur des appareils partageables, tels que des tablettes. Chaque utilisateur d'un appareil possède son propre ensemble de comptes, d'applications, de paramètres système, de fichiers et de toutes les autres données associées à l'utilisateur.

En tant que développeur d'applications, vous n'avez rien de différent pour que votre application fonctionne correctement avec plusieurs utilisateurs sur un même appareil. Quel que soit le nombre d'utilisateurs pouvant exister sur un appareil, les données que votre application enregistre pour un utilisateur donné sont conservées séparément de celles que votre application enregistre pour les autres utilisateurs. Le système effectue le suivi des données utilisateur qui appartiennent au processus utilisateur dans lequel votre application s'exécute. Il ne fournit à votre application qu'un accès aux données de cet utilisateur et n'autorise pas l'accès aux données des autres utilisateurs.

Enregistrer des données dans un environnement multi-utilisateur

Chaque fois que votre application enregistre les préférences utilisateur, crée une base de données ou écrit un fichier dans l'espace de stockage interne ou externe de l'utilisateur, ces données ne sont accessibles que lorsqu'elles sont exécutées sous le nom de cet utilisateur.

Pour vous assurer que votre application se comporte correctement dans un environnement multi-utilisateur, ne faites pas référence à votre répertoire interne d'application ni à votre emplacement de stockage externe à l'aide de chemins codés en dur. Utilisez plutôt les API appropriées:

Quelles que soient les API que vous utilisez pour enregistrer les données d'un utilisateur donné, celles-ci ne seront pas accessibles lorsque vous utiliserez un autre utilisateur. Du point de vue de votre application, chaque utilisateur s'exécute sur un appareil complètement distinct.

Identifier les utilisateurs dans un environnement multi-utilisateurs

Si votre application souhaite identifier des utilisateurs uniques par exemple pour collecter des données analytiques ou créer d'autres associations de comptes, vous devez suivre les pratiques recommandées pour identifier les installations uniques. En créant un UUID lorsque votre application démarre pour la première fois, vous êtes certain d'obtenir un ID unique pour suivre chaque utilisateur, quel que soit le nombre d'utilisateurs qui installent votre application sur un appareil. Vous pouvez également enregistrer un jeton local récupéré à partir de votre serveur ou utiliser l'ID d'enregistrement fourni par Google Cloud Messaging.

Sachez que si votre application demande l'un des identifiants d'appareil (tels que l'adresse MAC Wi-Fi ou le numéro SERIAL), la même valeur est fournie pour chaque utilisateur, car ces identifiants sont liés au matériel et non à l'utilisateur. Sans parler des autres problèmes introduits par ces identifiants, comme indiqué dans l'article de blog Identifier les installations d'applications.

Nouveaux paramètres généraux

Les paramètres système ont été mis à jour pour permettre l'utilisation de plusieurs utilisateurs grâce à l'ajout de Settings.Global. Cet ensemble de paramètres est semblable aux paramètres Settings.Secure, car ils sont en lecture seule, mais s'applique globalement à tous les espaces utilisateur de l'appareil.

Plusieurs paramètres existants ont été déplacés ici de Settings.System ou Settings.Secure. Si votre application modifie actuellement des paramètres précédemment définis dans Settings.System (tels que AIRPLANE_MODE_ON), attendez-vous à ce que cela ne fonctionne plus sur un appareil équipé d'Android 4.2 ou version ultérieure si ces paramètres ont été déplacés vers Settings.Global. Vous pouvez continuer à lire les paramètres qui se trouvent dans Settings.Global. Toutefois, comme les paramètres ne sont plus considérés comme sûrs et ne peuvent plus être modifiés par les applications, toute tentative de modification échouera en mode silencieux et le système écrira un avertissement dans le journal système lors de l'exécution de votre application sur Android 4.2 ou version ultérieure.

Prise en charge de la mise en page de droite à gauche

Android propose désormais plusieurs API qui vous permettent de créer des interfaces utilisateur qui transforment de manière optimale l'orientation de la mise en page afin de prendre en charge les langues qui utilisent des interfaces utilisateur de droite à gauche et une direction de lecture, comme l'arabe et l'hébreu.

Pour commencer à accepter les mises en page de droite à gauche dans votre application, définissez l'attribut android:supportsRtl sur l'élément <application> dans votre fichier manifeste, puis définissez-le sur “true". Une fois cette option activée, le système activera diverses API de lecture de droite à gauche pour afficher votre application avec des mises en page qui se lisent de droite à gauche. Par exemple, la barre d'action affiche l'icône et le titre sur le côté droit et les boutons d'action à gauche. Les mises en page que vous avez créées avec les classes View fournies par le framework sont également inversées.

Si vous devez optimiser davantage l'apparence de votre application lorsqu'elle est affichée de droite à gauche, il existe deux niveaux d'optimisation de base:

  1. Convertissez les propriétés de mise en page orientées vers la gauche et la droite en propriétés de mise en page orientées de début et de fin.

    Par exemple, utilisez android:layout_marginStart à la place de android:layout_marginLeft et android:layout_marginEnd à la place de android:layout_marginRight.

    La classe RelativeLayout fournit également les attributs de mise en page correspondants pour remplacer les positions gauche/droite, par exemple android:layout_alignParentStart pour remplacer android:layout_alignParentLeft et android:layout_toStartOf au lieu de android:layout_toLeftOf.

  2. Pour optimiser complètement les mises en page de droite à gauche, vous pouvez également fournir des fichiers de mise en page entièrement distincts à l'aide du qualificatif de ressource ldrtl (ldrtl signifie "layout-direction-right-to-left}"). Par exemple, vous pouvez enregistrer vos fichiers de mise en page par défaut dans res/layout/ et vos mises en page optimisées pour les langues qui se lisent de droite à gauche dans res/layout-ldrtl/.

    Le qualificatif ldrtl est idéal pour les ressources drawables, car il vous permet de fournir des graphiques orientés dans la direction correspondant à la direction de lecture.

Diverses autres API sont disponibles dans le framework pour prendre en charge les mises en page de droite à gauche, par exemple dans la classe View afin que vous puissiez implémenter les comportements appropriés pour les vues personnalisées, et dans Configuration pour interroger la direction actuelle de la mise en page.

Remarque : Si vous utilisez SQLite et que les noms de tables ou de colonnes ne contiennent que des chiffres, soyez prudent. Si vous utilisez String.format(String, Object...), des erreurs peuvent se produire lorsque les nombres ont été convertis dans leur équivalent en arabe si votre appareil a été configuré avec les paramètres régionaux arabes. Vous devez utiliser String.format(Locale,String,Object...) pour vous assurer que les nombres sont conservés au format ASCII. Utilisez également String.format("%d", int) au lieu de String.valueOf(int) pour mettre en forme les nombres.

Fragments imbriqués

Vous pouvez désormais intégrer des fragments à l'intérieur de fragments. Cela est utile dans diverses situations où vous souhaitez placer des composants d'interface utilisateur dynamiques et réutilisables dans un composant d'interface utilisateur qui est lui-même dynamique et réutilisable. Par exemple, si vous utilisez ViewPager pour créer des fragments qui balayent l'écran vers la gauche et vers la droite, et qui occupent la majeure partie de l'espace à l'écran, vous pouvez désormais insérer des fragments dans chaque page de fragment.

Pour imbriquer un fragment, il vous suffit d'appeler getChildFragmentManager() au niveau de l'élément Fragment dans lequel vous souhaitez ajouter un fragment. Cela renvoie un FragmentManager que vous pouvez utiliser comme vous le faites habituellement à partir de l'activité de premier niveau pour créer des transactions de fragment. Par exemple, voici du code qui ajoute un fragment à partir d'une classe Fragment existante:

Kotlin

val videoFragment = VideoPlayerFragment()
childFragmentManager.beginTransaction().apply {
    add(R.id.video_fragment, videoFragment)
    commit()
}

Java

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

À partir d'un fragment imbriqué, vous pouvez obtenir une référence au fragment parent en appelant getParentFragment().

La bibliothèque Android Support est désormais compatible avec les fragments imbriqués. Vous pouvez donc implémenter des conceptions de fragments imbriqués sur Android 1.6 ou version ultérieure.

Remarque:Vous ne pouvez pas gonfler une mise en page dans un fragment lorsque cette mise en page inclut un <fragment>. Les fragments imbriqués ne sont acceptés que lorsqu'ils sont ajoutés à un fragment de manière dynamique.

RenderScript

La fonctionnalité de calcul de Renderscript a été améliorée avec les fonctionnalités suivantes:

Fonctionnalités intrinsèques du script

Vous pouvez utiliser les fonctionnalités intrinsèques de script de Renderscript qui implémentent des opérations courantes pour vous, telles que:

Pour utiliser une fonctionnalité intrinsèque de script, appelez la méthode statique create() de chaque intrinsèque afin de créer une instance du script. Vous appelez ensuite les méthodes set() disponibles pour chaque élément intrinsèque de script pour définir les entrées et les options nécessaires. Enfin, appelez la méthode forEach() pour exécuter le script.

Groupes de scripts

Les ScriptGroup vous permettent d'associer des scripts Renderscript associés et de les exécuter en un seul appel.

Utilisez un ScriptGroup.Builder pour ajouter tous les scripts au groupe en appelant addKernel(). Une fois que vous avez ajouté tous les scripts, créez les connexions entre eux en appelant addConnection(). Une fois les connexions ajoutées, appelez create() pour créer le groupe de scripts. Avant d'exécuter le groupe de scripts, spécifiez l'Allocation d'entrée et le script initial à exécuter avec la méthode setInput(Script.KernelID, Allocation), et fournissez la sortie Allocation où le résultat sera écrit et le script final à exécuter avec setOutput(). Enfin, appelez execute() pour exécuter le groupe de scripts.

Script de filtrage

Filterscript définit des contraintes sur les API Renderscript existantes qui permettent au code obtenu de s'exécuter sur une plus grande variété de processeurs (processeurs, GPU et DSP). Pour créer des fichiers Filterscript, créez des fichiers .fs au lieu de fichiers .rs, puis spécifiez #pragma rs_fp_relaxed pour indiquer à l'environnement d'exécution Renderscript que vos scripts ne nécessitent pas de précision à virgule flottante IEEE 754-2008 stricte. Cette précision permet un flush-to-zéro pour les limites et un round-to-zero. En outre, vos scripts FilterScript ne doivent pas utiliser de types intégrés 32 bits. Ils doivent spécifier une fonction racine personnalisée à l'aide de l'attribut __attribute__((kernel)), car Filterscript n'est pas compatible avec les pointeurs, qui sont définis par la signature par défaut de la fonction root().

Remarque:Bien que Filterscript soit pris en charge par la plate-forme, l'assistance pour les développeurs sera disponible dans la version 21.0.1 de SDK Tools.

Pour obtenir une vue détaillée de toutes les modifications apportées aux API dans Android 4.2, consultez le rapport sur les différences entre les API.