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 explicitementandroid:exported="true"
.Cette modification ne prend effet que si vous définissez
android:targetSdkVersion
ouandroid: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'autorisationACCESS_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 dansSettings.System
qui ont été déplacés versSettings.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
etandroid:minSdkVersion
est inférieure à 17, votre application ne peut pas modifier les paramètres qui ont été déplacés versSettings.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éfinisseztargetSdkVersion
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 votreWebView
sur Android 4.2 ou version ultérieure. Si vous définisseztargetSdkVersion
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 appelerfinish()
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:
- Pour accéder à la mémoire de stockage interne, utilisez
getFilesDir()
,getCacheDir()
ouopenFileOutput()
. - Pour accéder à l'espace de stockage externe, utilisez
getExternalFilesDir()
ougetExternalStoragePublicDirectory()
.
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:
- 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 deandroid:layout_marginLeft
etandroid:layout_marginEnd
à la place deandroid:layout_marginRight
.La classe
RelativeLayout
fournit également les attributs de mise en page correspondants pour remplacer les positions gauche/droite, par exempleandroid:layout_alignParentStart
pour remplacerandroid:layout_alignParentLeft
etandroid:layout_toStartOf
au lieu deandroid:layout_toLeftOf
. - 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 dansres/layout/
et vos mises en page optimisées pour les langues qui se lisent de droite à gauche dansres/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:
Blends
Blur
Color matrix
3x3 convolve
5x5 convolve
Per-channel lookup table
Converting an Android YUV buffer to RGB
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éthodesset()
disponibles pour chaque élément intrinsèque de script pour définir les entrées et les options nécessaires. Enfin, appelez la méthodeforEach()
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 appelantaddKernel()
. Une fois que vous avez ajouté tous les scripts, créez les connexions entre eux en appelantaddConnection()
. Une fois les connexions ajoutées, appelezcreate()
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éthodesetInput(Script.KernelID, Allocation)
, et fournissez la sortieAllocation
où le résultat sera écrit et le script final à exécuter avecsetOutput()
. Enfin, appelezexecute()
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 fonctionroot()
.
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.