API Android 4.3

Niveau d'API : 18

Android 4.3 (JELLY_BEAN_MR2) est une mise à jour de Jelly Bean 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.3 à partir de SDK Manager dès que possible. Si vous ne disposez pas d'appareil équipé d'Android 4.3 sur lequel tester votre application, utilisez l'image système Android 4.3 pour tester votre application sur Android Emulator. Créez ensuite vos applications sur la plate-forme Android 4.3 pour commencer à utiliser la API les plus récentes.

Mettre à jour votre niveau d'API cible

Pour optimiser davantage votre application pour les appareils exécutant Android 4.3, vous devez définir votre targetSdkVersion sur "18", l'installer sur une image système Android 4.3, la tester, puis publier une mise à jour avec ce changement.

Vous pouvez utiliser des API dans Android 4.3 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.

Diverses API sont également disponibles dans la bibliothèque Support Android, qui vous permettent d'implémenter de nouvelles fonctionnalités sur les anciennes versions de la 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 par les modifications apportées à Android 4.3.

Si votre application utilise des intents implicites :

Votre application risque de ne pas fonctionner correctement dans un environnement de profil limité.

Il est possible que les utilisateurs d'un environnement utilisant un profil limité disposent de toutes les applications Android standards. Par exemple, le navigateur Web et l'application Appareil photo peuvent être désactivés dans un profil restreint. Par conséquent, votre application ne doit pas faire d'hypothèses sur les applications disponibles. En effet, si vous appelez startActivity() sans vérifier si une application est disponible pour gérer Intent, votre application risque de planter dans un profil limité.

Lorsque vous utilisez un intent implicite, vous devez toujours vérifier qu'une application est disponible pour gérer l'intent en appelant resolveActivity() ou queryIntentActivities(). Exemple :

Kotlin

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

Si votre application dépend de comptes...

Il est possible que votre application ne fonctionne pas dans un environnement de profil limité.

Par défaut, les utilisateurs d'un environnement de profil limité n'ont pas accès aux comptes utilisateur. Si votre application dépend d'un Account, elle risque de planter ou de se comporter de manière inattendue lorsqu'elle est utilisée dans un profil limité.

Si vous souhaitez empêcher les profils dont l'accès est limité d'utiliser entièrement votre application, car elle dépend d'informations de compte sensibles, spécifiez l'attribut android:requiredAccountType dans l'élément <application> de votre fichier manifeste.

Pour autoriser les profils dont l'accès est limité à continuer à utiliser votre application alors qu'ils ne peuvent pas créer leurs propres comptes, vous pouvez soit désactiver les fonctionnalités de votre application qui nécessitent un compte ou autoriser les profils dont l'accès est limité à accéder aux comptes créés par l'utilisateur principal. Pour en savoir plus, consultez la section Prendre en charge les comptes dans un profil limité ci-dessous.

Si votre application utilise VideoView :

Votre vidéo peut sembler plus petite sur Android 4.3.

Dans les versions précédentes d'Android, le widget VideoView calculait de manière incorrecte la valeur "wrap_content" pour layout_height et layout_width comme étant identique à "match_parent". Ainsi, bien que l'utilisation de "wrap_content" pour la hauteur ou la largeur ait déjà fourni la mise en page vidéo souhaitée, la taille de la vidéo risque d'être beaucoup plus petite sur Android 4.3 ou version ultérieure. Pour résoudre le problème, remplacez "wrap_content" par "match_parent" et vérifiez que votre vidéo s'affiche comme prévu sur Android 4.3 et les versions antérieures.

Profils restreints

Sur les tablettes Android, les utilisateurs peuvent désormais créer des profils limités en fonction de l'utilisateur principal. Lorsque les utilisateurs créent un profil limité, ils peuvent activer des restrictions concernant, par exemple, les applications disponibles pour le profil. Un nouvel ensemble d'API dans Android 4.3 vous permet également de créer des paramètres de restriction précis pour les applications que vous développez. Par exemple, avec les nouvelles API, vous pouvez permettent aux utilisateurs de contrôler le type de contenu disponible dans votre application lorsqu'elle s'exécute dans un un environnement de profil limité.

L'interface utilisateur permettant aux utilisateurs de contrôler les restrictions que vous avez créées est gérée par l'application "Paramètres" du système. Pour que les paramètres de restriction de votre appli soient visibles par l'utilisateur, vous devez déclarer les restrictions fournies par votre application en créant un BroadcastReceiver qui reçoit l'intent ACTION_GET_RESTRICTION_ENTRIES. Le système appelle cet intent pour interroger toutes les applications pour les restrictions disponibles, puis crée l'interface utilisateur pour permettre à l'utilisateur principal de gérer les restrictions pour chaque fiche limitée.

Dans la méthode onReceive() de votre BroadcastReceiver, vous devez créer un RestrictionEntry pour chaque restriction fournie par votre application. Chaque RestrictionEntry définit un titre et une description de restriction, ainsi que l'une des types de données suivants:

  • TYPE_BOOLEAN pour une restriction vrai ou faux.
  • TYPE_CHOICE pour une restriction comportant Plusieurs choix qui s'excluent mutuellement (cases d'option)
  • TYPE_MULTI_SELECT pour une restriction comportant plusieurs choix qui ne s'excluent pas mutuellement (choix de cases à cocher).

Vous placez ensuite tous les objets RestrictionEntry dans un ArrayList et le placez dans le résultat du broadcast receiver en tant que valeur pour l'extra EXTRA_RESTRICTIONS_LIST.

Le système crée l'interface utilisateur pour les restrictions de votre appli dans l'appli Paramètres et enregistre chacune d'elles avec la clé unique que vous avez fournie pour chaque RestrictionEntry . Lorsque l'utilisateur ouvre votre application, vous pouvez interroger les restrictions actuelles : Appel de getApplicationRestrictions() en cours. Cela renvoie un Bundle contenant les paires clé/valeur pour chaque restriction. que vous avez défini avec les objets RestrictionEntry.

Si vous souhaitez fournir des restrictions plus spécifiques qui ne peuvent pas être gérées par une valeur booléenne, un seul choix et choix multiples, vous pouvez créer une activité dans laquelle l'utilisateur peut spécifier des restrictions et autoriser les utilisateurs à ouvrir cette activité à partir des paramètres de restriction. Dans votre broadcast receiver, incluez l'extra EXTRA_RESTRICTIONS_INTENT dans le résultat Bundle. Cet extra doit spécifier un Intent indiquant la classe Activity à lancer (utilisez putParcelable() pour transmettre EXTRA_RESTRICTIONS_INTENT avec l'intent). Lorsque l'utilisateur principal entre dans votre activité pour définir des restrictions personnalisées, votre activité doit ensuite renvoyer un résultat contenant les valeurs de restriction dans un extra en utilisant soit la clé EXTRA_RESTRICTIONS_LIST ou EXTRA_RESTRICTIONS_BUNDLE, selon que vous spécifiez ou non des objets RestrictionEntry ou des paires clé/valeur, respectivement.

Prise en charge des comptes dans un profil limité

Tous les comptes ajoutés à l'utilisateur principal sont disponibles pour un profil limité, mais ils ne sont pas accessibles à partir des API AccountManager par défaut. Si vous tentez d'ajouter un compte avec AccountManager alors que vous êtes dans un vous n'obtiendrez pas un résultat. En raison de ces restrictions, vous disposez des éléments suivants : trois options:

  • Autoriser l'accès aux comptes du propriétaire à partir d'un profil limité

    Pour accéder à un compte à partir d'un profil limité, vous devez ajouter l'attribut android:restrictedAccountType à la balise <application>:

    <application ...
        android:restrictedAccountType="com.example.account.type" >

    Attention : L'activation de cet attribut permet à votre application d'accéder aux comptes de l'utilisateur principal à partir de profils dont l'accès est limité. Vous ne devez donc autoriser cette fonctionnalité que si les informations affichées par votre application ne révèlent pas d'informations permettant d'identifier personnellement l'utilisateur considérées comme sensibles. Les paramètres système informent que votre application accorde des profils limités à son compte, ce qui doit être clair pour l'utilisateur. cet accès au compte est important pour le fonctionnement de votre application. Si possible, vous devez également fournir à l'utilisateur principal des contrôles de restriction adéquats qui définissent le niveau d'accès au compte ; est autorisé dans votre application.

  • Désactiver certaines fonctionnalités lorsque vous ne pouvez pas modifier de comptes

    Si vous souhaitez utiliser des comptes, mais que vous n'en avez pas réellement besoin pour l'accès , vous pouvez vérifier la disponibilité d'un compte et désactiver certaines fonctionnalités lorsqu'elles ne le sont pas. Vous devez d'abord vérifier si un compte existe. Si ce n'est pas le cas, vérifiez s'il est possible de créer un compte en appelant getUserRestrictions() et vérifiez l'extra DISALLOW_MODIFY_ACCOUNTS dans le résultat. Si la valeur est true, vous devez désactiver toute fonctionnalité de votre application qui nécessite l'accès aux comptes. Exemple :

    Kotlin

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    Java

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    Remarque:Dans ce scénario, vous ne devez pas déclarer tout nouvel attribut dans votre fichier manifeste.

  • Désactivez votre application lorsque vous ne pouvez pas accéder à des comptes privés.

    Si vous souhaitez que votre application ne soit pas disponible pour les profils dont l'accès est limité, car elle dépend d'informations personnelles sensibles dans un compte (et parce que les profils dont l'accès est limité ne peuvent pas ajouter de comptes pour le moment), ajoutez l'attribut android:requiredAccountType à la balise <application> :

    <application ...
        android:requiredAccountType="com.example.account.type" >

    Par exemple, l'application Gmail utilise cet attribut pour se désactiver pour les profils dont l'accès est limité, car l'adresse e-mail personnelle du propriétaire ne doit pas être disponible pour les profils dont l'accès est limité.

  • Sans fil et connectivité

    Bluetooth Low Energy (Smart Ready)

    Android est désormais compatible avec le Bluetooth à basse consommation (LE) avec de nouvelles API dans android.bluetooth. Grâce aux nouvelles API, vous pouvez créer des applications Android qui communiquent avec la technologie Bluetooth Low Energy. les périphériques tels que les cardiofréquencemètres et les podomètres.

    La technologie Bluetooth LE étant une fonctionnalité matérielle qui n'est pas Appareils Android, vous devez déclarer un <uses-feature> dans le fichier manifeste pour "android.hardware.bluetooth_le":

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

    Si vous connaissez déjà les API Bluetooth classiques d'Android, notez que l'utilisation des API Bluetooth LE présente quelques différences. Plus important encore, vous disposez désormais d'une classe BluetoothManager que vous devez utiliser pour certaines opérations de haut niveau. comme l'acquisition d'un BluetoothAdapter, l'obtention d'une liste appareils et vérifier l'état d'un appareil. Par exemple, voici comment obtenir BluetoothAdapter:

    Kotlin

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter

    Java

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();

    Pour détecter les périphériques Bluetooth LE, appelez startLeScan() sur le BluetoothAdapter, en lui transmettant une implémentation de l'interface BluetoothAdapter.LeScanCallback. Lorsque l'adaptateur Bluetooth détecte un périphérique Bluetooth LE, votre implémentation de BluetoothAdapter.LeScanCallback reçoit un appel à la méthode onLeScan(). Cette méthode vous fournit un objet BluetoothDevice représentant l'appareil détecté, la valeur RSSI de l'appareil et un tableau d'octets contenant l'enregistrement de l'annonce de l'appareil.

    Si vous ne souhaitez rechercher que des types de périphériques spécifiques, vous pouvez appeler startLeScan() et inclure un tableau d'objets UUID qui spécifient les services GATT compatibles avec votre application.

    Remarque : Vous ne pouvez rechercher que des appareils Bluetooth LE ou des appareils Bluetooth classiques à l'aide des API précédentes. Vous ne pouvez pas rechercher simultanément des appareils Bluetooth LE et classiques.

    Pour vous connecter ensuite à un périphérique Bluetooth LE, appelez connectGatt() sur l'objet BluetoothDevice correspondant, en lui transmettant une implémentation de BluetoothGattCallback. Votre implémentation de BluetoothGattCallback reçoit des rappels concernant la connectivité. avec l'appareil et d'autres événements. C'est lors du rappel onConnectionStateChange() que vous pouvez commencer à communiquer avec l'appareil si la méthode transmet STATE_CONNECTED comme nouvel état.

    Pour accéder aux fonctionnalités Bluetooth d'un appareil, votre application doit également demander certaines autorisations utilisateur Bluetooth. Pour en savoir plus, consultez le guide de l'API Bluetooth Low Energy.

    Mode recherche Wi-Fi uniquement

    Lors d'une tentative d'identification de la position de l'utilisateur, Android peut utiliser le Wi-Fi pour déterminer l'emplacement en scannant les points d'accès à proximité. Toutefois, les utilisateurs désactivent souvent le Wi-Fi pour économiser la batterie, ce qui entraîne des données de localisation moins précises. Android inclut désormais un mode de numérisation uniquement qui permet au Wi-Fi de l'appareil de numériser les points d'accès pour obtenir la position sans se connecter à un point d'accès, ce qui réduit considérablement l'utilisation de la batterie.

    Si vous souhaitez obtenir la position de l'utilisateur, mais que le Wi-Fi est actuellement désactivé, vous pouvez demander à l'utilisateur d'activer le mode de recherche Wi-Fi uniquement en appelant startActivity() avec l'action ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE.

    Configuration Wi-Fi

    Les nouvelles API WifiEnterpriseConfig permettent aux services d'entreprise de d'automatiser la configuration Wi-Fi pour les appareils gérés.

    Réponse rapide aux appels entrants

    Depuis Android 4.0, une fonction appelée « Réponse rapide » permet aux utilisateurs de répondre vous recevez immédiatement un SMS sans avoir à répondre à l'appel ni à déverrouiller l'appareil. Jusqu'à présent, ces messages rapides étaient toujours gérés par l'application de chat par défaut. Désormais toutes les applis peut déclarer sa capacité à gérer ces messages en créant un Service. avec un filtre d'intent pour ACTION_RESPOND_VIA_MESSAGE.

    Lorsque l'utilisateur répond à un appel entrant avec une réponse rapide, l'application Téléphone envoie l'intent ACTION_RESPOND_VIA_MESSAGE avec un URI décrivant le destinataire (l'appelant) et l'extra EXTRA_TEXT avec le message que l'utilisateur souhaite envoyer. Lorsque votre service reçoit l'intent, il doit transmettre le message et s'arrêter immédiatement (votre application ne doit pas afficher d'activité).

    Pour recevoir cet intent, vous devez déclarer l'autorisation SEND_RESPOND_VIA_MESSAGE.

    Multimédia

    Améliorations apportées à MediaExtractor et MediaCodec

    Android vous permet désormais d'écrire plus facilement vos propres lecteurs de streaming adaptatif dynamique sur HTTP (DASH) conformément à la norme ISO/CEI 23009-1, à l'aide des API existantes dans MediaCodec et MediaExtractor. Le framework sur lequel reposent ces API a été mis à jour pour prendre en charge l'analyse des fichiers MP4 fragmentés, mais votre application est toujours responsable de l'analyse des métadonnées de la description de la présentation du média. et transmettre les flux individuels à MediaExtractor.

    Si vous souhaitez utiliser DASH avec du contenu chiffré, notez que la méthode getSampleCryptoInfo() renvoie les métadonnées MediaCodec.CryptoInfo décrivant la structure de chaque contenu multimédia chiffré. échantillon. De plus, la méthode getPsshInfo() a été ajoutée à MediaExtractor afin d'accéder aux métadonnées PSSH de votre contenu multimédia DASH. Cette méthode renvoie un mappage d'objets UUID en octets, avec les UUID spécifiant le schéma de chiffrement et les octets correspondant aux données à ce schéma.

    Media DRM

    La nouvelle classe MediaDrm fournit une solution modulaire pour la gestion des droits numériques (DRM) avec vos contenus multimédias en séparant les problèmes DRM de la lecture multimédia. Pour cette séparation des API vous permet de lire du contenu chiffré Widevine sans avoir pour utiliser le format multimédia Widevine. Cette solution DRM est aussi compatible avec le chiffrement commun DASH. vous pouvez utiliser différents schémas DRM pour votre contenu en streaming.

    Vous pouvez utiliser MediaDrm pour obtenir des messages de requête de clé opaques et traiter des messages de réponse clé du serveur pour l'acquisition et le provisionnement des licences. Votre application est responsable de la gestion de la communication réseau avec les serveurs. La classe MediaDrm ne permet que de générer et de traiter les messages.

    Les API MediaDrm sont destinées à être utilisées avec les API MediaCodec introduites dans Android 4.1 (niveau d'API 16) y compris MediaCodec pour encoder et décoder votre contenu, MediaCrypto pour gérer le contenu chiffré et MediaExtractor pour extraire et démuxer votre contenu.

    Vous devez d'abord créer des objets MediaExtractor et MediaCodec. Vous pouvez ensuite accéder à l'outil d'identification UUID, généralement à partir des métadonnées du contenu, et l'utiliser pour créer une une instance d'un objet MediaDrm avec son constructeur.

    Encodage vidéo depuis une surface

    Android 4.1 (niveau d'API 16) a ajouté la classe MediaCodec pour l'encodage et le décodage de contenu multimédia de bas niveau. Lors de l'encodage vidéo, Android 4.1 vous obligeait à fournir au contenu multimédia un tableau ByteBuffer, mais Android 4.3 vous permet désormais d'utiliser un Surface comme entrée d'un encodeur. Par exemple, cela vous permet d'encoder l'entrée à partir d'un fichier vidéo existant ou à l'aide de frames générés à partir d'OpenGL ES.

    Pour utiliser un Surface comme entrée de votre encodeur, appelez d'abord configure() pour votre MediaCodec. Appelez ensuite createInputSurface() pour recevoir le Surface sur lequel vous pouvez diffuser vos contenus multimédias.

    Par exemple, vous pouvez utiliser le Surface donné comme fenêtre pour un OpenGL le contexte en le transmettant à eglCreateWindowSurface(). Ensuite, lors du rendu de la surface, appelez eglSwapBuffers() pour transmettre le cadre à MediaCodec.

    Pour commencer l'encodage, appelez start() sur MediaCodec. Lorsque vous avez terminé, appelez signalEndOfInputStream() pour terminer l'encodage et appeler release() sur la Surface

    Muxage multimédia

    La nouvelle classe MediaMuxer permet le multiplexage entre un flux audio et un flux vidéo. Ces API servent d'équivalent à MediaExtractor ajoutée dans Android 4.2 pour le démultiplexage des contenus multimédias.

    Les formats de sortie acceptés sont définis dans MediaMuxer.OutputFormat. Actuellement, le MP4 est le seul format de sortie compatible, et MediaMuxer n'accepte qu'un seul flux audio et/ou un seul flux vidéo à la fois.

    MediaMuxer est principalement conçu pour fonctionner avec MediaCodec Vous pouvez donc traiter la vidéo via MediaCodec, puis enregistrer dans un fichier MP4 via MediaMuxer. Vous pouvez également utiliser MediaMuxer en combinaison avec MediaExtractor pour effectuer sans code ni décodage.

    Progression de la lecture et barre de lecture pour RemoteControlClient

    Dans Android 4.0 (niveau d'API 14), RemoteControlClient a été ajouté pour activer les commandes de lecture multimédia à partir de clients de télécommande, comme les commandes disponibles sur l'écran de verrouillage. Android 4.3 permet désormais à ces manettes d'afficher la lecture et les commandes de lecture. Si vous avez activé la télécommande pour votre application multimédia avec les API RemoteControlClient, vous pouvez autoriser la lecture en utilisant deux nouvelles interfaces.

    Tout d'abord, vous devez activer l'option FLAG_KEY_MEDIA_POSITION_UPDATE en la transmettant à setTransportControlsFlags()

    Implémentez ensuite les deux nouvelles interfaces suivantes :

    RemoteControlClient.OnGetPlaybackPositionListener
    Cela inclut le rappel onGetPlaybackPosition(), qui demande la position actuelle. de vos contenus multimédias lorsque la télécommande doit mettre à jour la progression dans son interface utilisateur.
    RemoteControlClient.OnPlaybackPositionUpdateListener
    Cela inclut le rappel onPlaybackPositionUpdate(), qui indique à votre application le nouveau code temporel de votre contenu multimédia lorsque l'utilisateur effectue un scrubbing de la lecture avec l'interface utilisateur de la télécommande.

    Une fois que vous avez mis à jour la lecture avec la nouvelle position, appelez setPlaybackState() pour indiquer le nouvel état, la nouvelle position et la nouvelle vitesse de lecture.

    Une fois ces interfaces définies, vous pouvez les définir pour votre RemoteControlClient en appelant setOnGetPlaybackPositionListener() et setPlaybackPositionUpdateListener(), respectivement.

    Graphiques

    Compatibilité avec OpenGL ES 3.0

    Android 4.3 ajoute des interfaces Java et la prise en charge native d'OpenGL ES 3.0. Nouvelles fonctionnalités clés fournies dans OpenGL ES 3.0 incluent:

    • Accélération des effets visuels avancés
    • Compression de texture ETC2/EAC de haute qualité en tant que fonctionnalité standard
    • Nouvelle version du langage d'ombrage GLSL ES compatible avec les entiers et la virgule flottante 32 bits
    • Rendu de texture avancé
    • Standardisation plus large de la taille des textures et des formats de tampon de rendu

    L'interface Java pour OpenGL ES 3.0 sur Android est fournie avec GLES30. Lorsque vous utilisez OpenGL ES 3.0, veillez à le déclarer dans votre fichier manifeste à l'aide de la balise <uses-feature> et de l'attribut android:glEsVersion. Exemple :

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>

    Et n'oubliez pas de spécifier le contexte OpenGL ES en appelant setEGLContextClientVersion(), en transmettant 3 comme version.

    Pour en savoir plus sur l'utilisation d'OpenGL ES, y compris sur la façon de vérifier la compatibilité de l'appareil Version d'OpenGL ES au moment de l'exécution. Consultez le guide de l'API OpenGL ES.

    Mappage de mip pour les drawables

    L'utilisation d'un mipmap comme source pour votre bitmap ou drawable est un moyen simple de fournir un de qualité et différentes échelles d'affichage, ce qui peut s'avérer particulièrement utile mise à l'échelle pendant une animation.

    Android 4.2 (niveau d'API 17) a ajouté la prise en charge des mipmap dans la classe Bitmap. Android échange les images mip dans votre Bitmap lorsque vous avez fourni une source mipmap et activé setHasMipMap(). Avec Android 4.3, vous pouvez également activer les mipmap pour un objet BitmapDrawable en fournissant un élément mipmap et en définissant l'attribut android:mipMap dans un fichier de ressources bitmap ou en appelant hasMipMap().

    Interface utilisateur

    Afficher les superpositions

    La nouvelle classe ViewOverlay fournit une couche transparente au-dessus d'un View sur lequel vous pouvez ajouter du contenu visuel et qui n'affecte pas la hiérarchie de mise en page. Vous pouvez obtenir un ViewOverlay pour n'importe quel View en appelant getOverlay(). La superposition a toujours la même taille et la même position que la vue hôte (la vue à partir de laquelle la création a été créée) ; vous permettant d'ajouter du contenu qui apparaît devant la vue de l'hôte, mais qui ne peut pas s'étendre les limites de cette vue hôte.

    L'utilisation d'un ViewOverlay est particulièrement utile lorsque vous souhaitez créer des animations, par exemple en faisant glisser une vue en dehors de son conteneur ou en déplaçant des éléments sur l'écran sans affecter la hiérarchie des vues. Toutefois, comme la zone utilisable d'une superposition est limitée à la même zone que sa vue hôte, si vous souhaitez animer une vue qui se déplace en dehors de sa position dans la mise en page, vous devez utiliser une superposition à partir d'une vue parente qui possède les limites de mise en page souhaitées.

    Lorsque vous créez une superposition pour une vue de widget telle qu'une Button, vous vous pouvez ajouter des objets Drawable à la superposition en appelant add(Drawable) Si vous appelez getOverlay() pour une vue de mise en page, telle que RelativeLayout, l'objet renvoyé est un ViewGroupOverlay. La La classe ViewGroupOverlay est une sous-classe de ViewOverlay, qui vous permet aussi d'ajouter View en appelant add(View).

    Remarque:Tous les drawables et les vues que vous ajoutez à une superposition ne sont que visuels. Ils ne peuvent pas recevoir d'événements de sélection ni d'entrée.

    Par exemple, le code suivant anime une vue glissant vers la droite en la plaçant dans la superposition de la vue parent, puis exécuter une animation de traduction sur cette vue:

    Kotlin

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }

    Java

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();

    Mise en page avec contours optiques

    Pour les vues contenant des images de fond nine-patch, vous pouvez désormais spécifier qu'elles doivent être alignées sur les vues voisines en fonction des limites "optique" de l'image de fond plutôt que des limites "clip" de la vue.

    Par exemple, les figures 1 et 2 montrent chacune la même mise en page, mais la version de la figure 1 utilise des limites de découpe (comportement par défaut), tandis que la figure 2 utilise des limites optiques. En effet, les images Nine-Patch utilisés pour le bouton et le cadre photo incluent une marge intérieure autour des bords, elles ne semblent pas alignées les unes avec les autres ni avec le texte lorsque vous utilisez des limites de rognage.

    Remarque:Sur les captures d'écran des figures 1 et 2, de la mise en page. paramètre pour les développeurs activé. Pour chaque vue, les lignes rouges indiquent le côté optique les limites, les lignes bleues indiquent les limites du clip et le rose indique les marges.

    Figure 1 : Mise en page utilisant des limites de découpage (par défaut).

    Figure 2. Mise en page à l'aide de limites optiques.

    Pour aligner les vues en fonction de leurs limites optiques, définissez l'attribut android:layoutMode sur "opticalBounds" dans l'une des mises en page parentes. Exemple :

    <LinearLayout android:layoutMode="opticalBounds" ... >

    Figure 3. Vue zoomée du bouton Holo 9-patch avec les limites optiques.

    Pour que cela fonctionne, les images neuf-patch appliquées à l'arrière-plan de vos vues doivent spécifier les limites optiques à l'aide de lignes rouges en bas et à droite du fichier Nine-Patch (comme comme illustré dans la figure 3). Les lignes rouges indiquent la région à soustraire de les limites du clip, en conservant les limites optiques de l'image.

    Lorsque vous activez les limites optiques pour une ViewGroup dans votre mise en page, toutes Les vues descendantes héritent du mode de mise en page avec limites optiques, sauf si vous le remplacez par un élément "Grouper par" en définissant android:layoutMode sur "clipBounds". Tous les éléments de mise en page respectent également les les limites optiques des vues de leur enfant, en adaptant leurs propres limites sur la base des limites optiques les vues qu'ils contiennent. Toutefois, les éléments de mise en page (sous-classes de ViewGroup) ne sont actuellement pas compatibles avec les limites optiques des images Nine-Patch appliquées à leur propre arrière-plan.

    Si vous créez une vue personnalisée en sous-classant View, ViewGroup ou l'une de leurs sous-classes, votre vue héritera de ces comportements liés aux limites optiques.

    Remarque : Tous les widgets compatibles avec le thème Holo ont été mis à jour avec des limites optiques, y compris Button, Spinner, EditText et d'autres. Vous pouvez donc immédiatement définir l'attribut android:layoutMode sur "opticalBounds" si votre application applique un thème Holo (Theme.Holo, Theme.Holo.Light, etc.).

    Pour spécifier des limites optiques pour vos propres images Nine-Patch à l'aide de l'outil Draw 9-patch, maintenez la touche Ctrl enfoncée lorsque je clique sur les pixels de bordure.

    Animation pour les valeurs Rect

    Vous pouvez désormais animer entre deux valeurs Rect avec la nouvelle RectEvaluator. Cette nouvelle classe est une implémentation de TypeEvaluator que vous pouvez transmettre à ValueAnimator.setEvaluator().

    Écouteur d'attachement et de focus de fenêtre

    Auparavant, si vous vouliez savoir à quel moment votre vue était associée/dissociée à la fenêtre ou lorsque son objectif changeait, vous deviez remplacer la classe View par implémenter onAttachedToWindow() et onDetachedFromWindow(), ou onWindowFocusChanged(), respectivement.

    Pour recevoir des événements d'association et de dissociation, vous pouvez désormais implémenter ViewTreeObserver.OnWindowAttachListener et le définir sur une vue avec addOnWindowAttachListener(). Pour recevoir des événements de sélection, vous pouvez implémenter ViewTreeObserver.OnWindowFocusChangeListener et le définir sur une vue avec addOnWindowFocusChangeListener().

    Compatibilité avec le surbalayage TV

    Pour vous assurer que votre application remplit l'intégralité de l'écran sur chaque téléviseur, vous pouvez désormais activer le surbalayage pour la mise en page de votre application. Le mode surbalayage est déterminé par l'indicateur FLAG_LAYOUT_IN_OVERSCAN, que vous pouvez activer avec les thèmes de plate-forme tels que Theme_DeviceDefault_NoActionBar_Overscan ou en activant Style windowOverscan dans un thème personnalisé.

    Orientation de l'écran

    L'attribut screenOrientation de la balise <activity> accepte désormais des valeurs supplémentaires pour respecter la préférence de l'utilisateur concernant la rotation automatique :

    "userLandscape"
    Se comporte de la même manière que "sensorLandscape", sauf si l'utilisateur désactive la rotation automatique. Dans ce cas, l'orientation paysage normale est verrouillée et ne s'inverse pas.
    "userPortrait"
    Comportement identique à celui de "sensorPortrait", sauf si l'utilisateur désactive la rotation automatique elle se verrouille en mode portrait normal et ne se retourne pas.
    "fullUser"
    Se comporte de la même manière que "fullSensor" et permet la rotation dans les quatre directions, sauf si l'utilisateur désactive la rotation automatique, auquel cas l'orientation préférée de l'utilisateur est verrouillée.

    De plus, vous pouvez désormais déclarer "locked" pour verrouiller l'orientation de votre application sur l'orientation actuelle de l'écran.

    Animations de rotation

    Le nouveau champ rotationAnimation dans WindowManager vous permet de choisir entre l'une des trois animations que vous à utiliser lorsque le système change d'orientation d'écran. Les trois animations sont les suivantes:

    Remarque : Ces animations ne sont disponibles que si vous avez défini votre activité pour qu'elle utilise le mode "plein écran", que vous pouvez activer avec des thèmes tels que Theme.Holo.NoActionBar.Fullscreen.

    Par exemple, voici comment activer l'animation "Fondu" :

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }

    Java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }

    Entrée utilisateur

    Nouveaux types de capteurs

    Le nouveau capteur TYPE_GAME_ROTATION_VECTOR vous permet de détecter les rotations de l'appareil sans vous soucier des interférences magnétiques. Contrairement au capteur TYPE_ROTATION_VECTOR, le TYPE_GAME_ROTATION_VECTOR n'est pas basé sur le nord magnétique.

    Les nouveaux capteurs TYPE_GYROSCOPE_UNCALIBRATED et TYPE_MAGNETIC_FIELD_UNCALIBRATED fournissent des données brutes sans tenir compte des estimations de biais. Autrement dit, les éléments TYPE_GYROSCOPE et TYPE_MAGNETIC_FIELD existants les capteurs fournissent des données qui prennent en compte le biais estimé dû à la dérive gyroscopique et au fer dur sur l'appareil, respectivement. Au contraire, la nouvelle métrique "non calibrée" de ces capteurs fournissent les données brutes du capteur et les valeurs de biais estimées séparément. Ces capteurs permettent vous pouvez effectuer un étalonnage personnalisé des données du capteur en améliorant l'estimation du biais avec des données externes.

    Écouteur des notifications

    Android 4.3 ajoute une nouvelle classe de service, NotificationListenerService, qui permet à votre application de recevoir des informations sur les nouvelles notifications lorsqu'elles sont publiées par le système.

    Si votre application utilise actuellement les API des services d'accessibilité pour accéder aux notifications système, vous devez la mettre à jour pour qu'elle utilise ces API à la place.

    Contacts Provider

    Requête pour "contactables"

    La nouvelle requête du fournisseur de contacts, Contactables.CONTENT_URI, permet d'obtenir de manière efficace un Cursor contenant toutes les adresses e-mail et tous les numéros de téléphone appartenant à tous les contacts correspondant à la requête spécifiée.

    Interroger les deltas de contacts

    De nouvelles API ont été ajoutées à Contacts Provider. Elles vous permettent d'interroger efficacement les dernières modifications apportées aux données des contacts. Auparavant, votre application pouvait recevoir une notification lorsqu'un élément des données de contacts avait changé, mais vous ne saviez pas exactement ce qui avait changé et vous deviez récupérer tous les contacts, puis les parcourir pour découvrir la modification.

    Pour suivre les modifications apportées aux insertions et aux mises à jour, vous pouvez désormais inclure le paramètre CONTACT_LAST_UPDATED_TIMESTAMP avec votre sélection afin de n'interroger que les contacts qui ont changé depuis la dernière fois que vous avez interrogé le fournisseur.

    Pour savoir quels contacts ont été supprimés, le nouveau tableau ContactsContract.DeletedContacts fournit un journal des contacts qui ont été supprimés (mais chaque contact supprimé est conservé dans ce tableau pendant une durée limitée). Comme pour CONTACT_LAST_UPDATED_TIMESTAMP, vous pouvez utiliser le nouveau paramètre de sélection, CONTACT_DELETED_TIMESTAMP, pour vérifier quels contacts ont été supprimés depuis la dernière fois que vous avez interrogé le fournisseur. La table contient également la constante DAYS_KEPT_MILLISECONDS, qui indique le nombre de jours (en millisecondes) pendant lesquels le journal sera conservé.

    De plus, le fournisseur de contacts diffuse désormais l'action CONTACTS_DATABASE_CREATED lorsque l'utilisateur efface le stockage des contacts via le menu des paramètres système, recréant ainsi Base de données des fournisseurs de contacts. Elle sert à signaler aux applis qu'elles doivent supprimer tous les contacts des informations stockées et l'actualiser avec une nouvelle requête.

    Pour obtenir un exemple de code utilisant ces API pour vérifier les modifications apportées aux contacts, consultez l'exemple ApiDemos disponible dans le téléchargement des exemples de SDK.

    Localisation

    Meilleure compatibilité avec le texte bidirectionnel

    Les versions précédentes d'Android sont compatibles avec les langues et la mise en page de droite à gauche (RTL), mais ne gèrent parfois pas correctement le texte à sens mixte. C'est pourquoi Android 4.3 ajoute les API BidiFormatter qui vous aident à mettre en forme correctement du texte dans le sens opposé. sans en brouiller une partie.

    Par exemple, lorsque vous souhaitez créer une phrase avec une variable de chaîne, telle que "Vous voulez peut-être 15 Bay Street, Laurel, CA ?", vous transmettez normalement une ressource de chaîne localisée et la variable à String.format() :

    Kotlin

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)

    Java

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);

    Cependant, si les paramètres régionaux sont l'hébreu, la chaîne mise en forme se présente comme suit:

    Continuer à faire le 15 Bay Street, Laurel, CA ?

    C'est faux parce que le « 15 » doit se trouver à gauche de "Bay Street". La solution consiste à utiliser BidiFormatter et sa méthode unicodeWrap(). Par exemple, le code ci-dessus devient:

    Kotlin

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )

    Java

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));

    Par défaut, unicodeWrap() utilise le l'heuristique d'estimation de l'orientation du premier fort, qui peut être inexacte si la première l'orientation du texte ne représente pas l'orientation appropriée du contenu dans son ensemble. Si nécessaire, vous pouvez spécifier une heuristique différente en transmettant l'une des constantes TextDirectionHeuristic de TextDirectionHeuristics à unicodeWrap().

    Remarque : Ces nouvelles API sont également disponibles pour les versions précédentes d'Android via la bibliothèque d'assistance Android, avec la classe BidiFormatter et les API associées.

    Services d'accessibilité

    Gérer les événements clés

    Un AccessibilityService peut désormais recevoir un rappel pour les événements d'entrée de touche avec la méthode de rappel onKeyEvent(). Cela permet à votre service d'accessibilité de gérer l'entrée pour les périphériques d'entrée basés sur des touches, tels qu'un clavier, et de traduire ces événements en actions spéciales qui n'étaient auparavant possibles qu'avec une entrée tactile ou le pavé directionnel de l'appareil.

    Sélectionner du texte et le copier/coller

    AccessibilityNodeInfo fournit désormais des API qui permettent Un élément AccessibilityService pour sélectionner, couper, copier et coller dans un nœud.

    Pour spécifier la sélection de texte à couper ou à copier, votre service d'accessibilité peut utiliser la nouvelle action ACTION_SET_SELECTION, en transmettant les positions de début et de fin de la sélection avec ACTION_ARGUMENT_SELECTION_START_INT et ACTION_ARGUMENT_SELECTION_END_INT. Vous pouvez également sélectionner du texte en manipulant la position du curseur à l'aide de l'action existante, ACTION_NEXT_AT_MOVEMENT_GRANULARITY (auparavant réservée au déplacement du curseur) et en ajoutant l'argument ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN.

    Vous pouvez ensuite couper ou copier avec ACTION_CUT, ACTION_COPY, puis coller avec ACTION_PASTE.

    Remarque : Ces nouvelles API sont également disponibles pour les versions précédentes d'Android via la bibliothèque d'assistance Android, avec la classe AccessibilityNodeInfoCompat.

    Déclarer les fonctionnalités d'accessibilité

    À partir d'Android 4.3, un service d'accessibilité doit déclarer les fonctionnalités d'accessibilité dans son fichier de métadonnées pour pouvoir utiliser certaines fonctionnalités d'accessibilité. Si la capacité n'est pas demandée dans le fichier de métadonnées, il s'agit d'une opération no-op. Pour déclarer le paramètre fonctionnalités d'accessibilité, vous devez utiliser des attributs XML correspondant aux différents "capacité" constantes dans AccessibilityServiceInfo .

    Par exemple, si un service ne demande pas la capacité flagRequestFilterKeyEvents, il ne recevra pas d'événements clés.

    Tester et déboguer

    Tests automatisés de l'interface utilisateur

    La nouvelle classe UiAutomation fournit des API qui vous permettent de simuler des utilisateurs pour l'automatisation des tests. En utilisant les API AccessibilityService de la plate-forme, les API UiAutomation vous permettent d'inspecter le contenu de l'écran et d'injecter des événements de clavier et tactiles arbitraires.

    Pour obtenir une instance de UiAutomation, appelez Instrumentation.getUiAutomation(). Pour que cela fonctionne, vous devez fournir l'option -w avec la commande instrument lorsque vous exécutez votre InstrumentationTestCase à partir de adb shell.

    Avec l'instance UiAutomation, vous pouvez exécuter des événements arbitraires pour tester votre application en appelant executeAndWaitForEvent(), en lui transmettant un Runnable à effectuer, un délai avant expiration la durée de l'opération, et une implémentation de l'interface UiAutomation.AccessibilityEventFilter. C'est dans votre implémentation UiAutomation.AccessibilityEventFilter que vous recevrez un appel qui vous permet de filtrer les événements qui vous intéressent pour déterminer l'échec d'un scénario de test donné.

    Pour observer tous les événements pendant un test, créez une implémentation de UiAutomation.OnAccessibilityEventListener et transmettez-la à setOnAccessibilityEventListener(). Votre interface d'écouteur reçoit ensuite un appel à onAccessibilityEvent(). chaque fois qu'un événement se produit, la réception d'un objet AccessibilityEvent décrivant l'événement.

    Les API UiAutomation exposent plusieurs autres opérations. à un niveau très bas pour encourager le développement d'outils de test d'interface utilisateur tels que uiautomator. Par exemple, UiAutomation peut également :

    • Injecter des événements d'entrée
    • Modifier l'orientation de l'écran
    • Réaliser des captures d'écran

    Et surtout, pour les outils de test de l'interface utilisateur, les API UiAutomation fonctionnent au-delà des limites de l'application, contrairement à Instrumentation.

    Événements Systrace pour les applications

    Android 4.3 ajoute la classe Trace avec deux méthodes statiques, beginSection() et endSection(), qui vous permettent de définir des blocs de code à inclure avec le rapport systrace. En créant de code traçables dans votre appli, les journaux Systrace vous fournissent une analyse des endroits où le ralentissement se produit dans votre application.

    Pour en savoir plus sur l'utilisation de l'outil Systrace, consultez Analyser l'affichage et les performances avec Systrace.

    Sécurité

    Android Keystore pour les clés privées de l'application

    Android propose désormais un fournisseur de solutions de sécurité Java personnalisé dans l'installation KeyStore, appelé Android Keystore, qui vous permet de générer et d'enregistrer des clés privées qui ne peuvent être vues et utilisées que par votre application. Pour charger Android Keystore, transmettez "AndroidKeyStore" à KeyStore.getInstance().

    Pour gérer les identifiants privés de votre application dans le Key Store Android, générez une clé avec KeyPairGenerator avec KeyPairGeneratorSpec. Tout d'abord Obtenez une instance de KeyPairGenerator en appelant getInstance(). Appelez ensuite initialize() en lui transmettant une instance de KeyPairGeneratorSpec, que vous pouvez obtenir à l'aide de KeyPairGeneratorSpec.Builder. Enfin, obtenez votre KeyPair en appelant generateKeyPair().

    Stockage des identifiants matériels

    Android est désormais également compatible avec le stockage basé sur le matériel pour vos identifiants KeyChain, ce qui offre une sécurité accrue en rendant les clés non disponibles à l'extraction. Autrement dit, une fois les clés dans un magasin de clés basé sur du matériel (composant sécurisé, TPM ou TrustZone), elles peuvent être utilisées pour des opérations cryptographiques, mais le matériel de clé privée ne peut pas être exporté. Même le noyau OS ne peuvent pas accéder à ce matériel de clé. Bien que tous les appareils Android ne soient pas compatibles avec le stockage sur matériel, vous pouvez vérifier au moment de l'exécution si le stockage basé sur du matériel est disponible en appelant KeyChain.IsBoundKeyAlgorithm().

    Déclarations dans le fichier manifeste

    Fonctionnalités obligatoires pouvant être déclarées

    Les valeurs suivantes sont désormais compatibles avec l'élément <uses-feature>. Vous pouvez ainsi vous assurer que votre application n'est installée que sur les appareils qui fournissent les fonctionnalités dont elle a besoin.

    FEATURE_APP_WIDGETS
    Déclare que votre application fournit un widget d'application et ne doit être installée que sur des appareils dotés d'un écran d'accueil ou d'un emplacement similaire, où les utilisateurs peuvent intégrer des widgets d'application. Exemple :
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    FEATURE_HOME_SCREEN
    Déclare que votre application se comporte comme un remplacement de l'écran d'accueil et ne doit être installée que sur des appareils compatibles avec des applications d'écran d'accueil tierces. Exemple :
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    FEATURE_INPUT_METHODS
    Déclare que votre application fournit un mode de saisie personnalisé (un clavier créé avec InputMethodService) et ne doit être installée que sur les appareils compatibles avec les modes de saisie tiers. Exemple :
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    FEATURE_BLUETOOTH_LE
    Déclare que votre application utilise des API Bluetooth à basse consommation et ne doit être installée que sur des appareils capables de communiquer avec d'autres appareils via Bluetooth à basse consommation. Exemple :
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />

    Autorisations utilisateur

    Les valeurs suivantes sont désormais compatibles avec <uses-permission> pour déclarer les autorisations dont votre application a besoin pour accéder à certaines API.

    BIND_NOTIFICATION_LISTENER_SERVICE
    Requis pour utiliser les nouvelles API NotificationListenerService.
    SEND_RESPOND_VIA_MESSAGE
    Obligatoire pour recevoir l'intent ACTION_RESPOND_VIA_MESSAGE.

    Pour obtenir une vue détaillée de toutes les modifications apportées aux API dans Android 4.3, consultez la Rapport sur les différences de l'API