Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Important
Nous étudions actuellement l’utilisation de la liaison personnalisée sur la plateforme Xamarin. S’il vous plaît prendre cette enquête pour informer les efforts de développement futurs.
Xamarin permet aux développeurs mobiles de créer des applications mobiles natives multiplateformes à l’aide de Visual Studio et de C#. Vous pouvez utiliser les composants du KIT de développement logiciel (SDK) de la plateforme Android prêtes à l’emploi, mais dans de nombreux cas, vous souhaitez également utiliser des kits SDK tiers écrits pour cette plateforme et Xamarin vous permet de le faire via des liaisons. Pour incorporer une infrastructure Android tierce dans votre application Xamarin.Android, vous devez créer une liaison Xamarin.Android pour celle-ci avant de pouvoir l’utiliser dans vos applications.
La plateforme Android, ainsi que ses langages natifs et ses outils, sont en constante évolution, notamment l’introduction récente du langage Kotlin, qui est destiné à remplacer Java. Il existe un certain nombre de sdk tiers, qui ont déjà été migrés de Java vers Kotlin, ce qui nous pose de nouveaux défis. Même si le processus de liaison Kotlin est similaire à Java, il nécessite des étapes et des paramètres de configuration supplémentaires pour générer et exécuter correctement dans le cadre d’une application Xamarin.Android.
L’objectif de ce document est de décrire une approche de haut niveau pour traiter ce scénario et de fournir un guide détaillé pas à pas avec un exemple simple.
Arrière-plan
Kotlin a été publié en février 2016 et a été positionné comme une alternative au compilateur Java standard dans Android Studio en 2017. Plus tard en 2019, Google a annoncé que le langage de programmation Kotlin deviendra son langage préféré pour les développeurs d’applications Android. L’approche de liaison de haut niveau est similaire au processus de liaison des bibliothèques Java standard avec quelques étapes spécifiques à Kotlin importantes.
Prérequis
Pour réaliser cette procédure pas à pas, vous aurez besoin des éléments suivants :
Créer une bibliothèque native
La première étape consiste à créer une bibliothèque Kotlin native à l’aide d’Android Studio. La bibliothèque est généralement fournie par un développeur tiers ou disponible dans le dépôt Maven de Google et d’autres dépôts distants. Par exemple, dans ce tutoriel, une liaison pour la bibliothèque Kotlin du sélecteur de bulles est créée :
Téléchargez le code source à partir de GitHub pour la bibliothèque et décompressez-le dans un dossier local Bubble-Picker.
Lancez Android Studio et sélectionnez l’option de menu Ouvrir un projet Android Studio existant en choisissant le Bubble-Picker dossier local :
Vérifiez que Android Studio est à jour, y compris Gradle. Le code source peut être correctement généré sur Android Studio v3.5.3, Gradle v5.4.1. Vous trouverez ici des instructions sur la mise à jour de Gradle vers la dernière version de Gradle.
Vérifiez que le Kit de développement logiciel (SDK) Android requis est installé. Le code source nécessite le Kit de développement logiciel (SDK) Android v25. Ouvrez l’option > de menu Outils du Gestionnaire du KIT de développement logiciel (SDK) pour installer les composants du KIT de développement logiciel (SDK).
Mettez à jour et synchronisez le fichier de configuration build.gradle main situé à la racine du dossier du projet :
Définissez la version kotlin sur 1.3.10
buildscript { ext.kotlin_version = '1.3.10' }
Inscrivez le référentiel Maven de Google par défaut afin que la dépendance de bibliothèque de support puisse être résolue :
allprojects { repositories { jcenter() maven { url "https://maven.google.com" } } }
Une fois le fichier de configuration mis à jour, il est désynchronisée et Gradle affiche le bouton Synchroniser maintenant , appuyez dessus et attendez que le processus de synchronisation soit terminé :
Conseil
Le cache de dépendances de Gradle peut être endommagé, ce qui se produit parfois après un délai d’expiration de connexion réseau. Retélécharger les dépendances et synchroniser le projet (nécessite le réseau).
Conseil
L’état d’un processus de build Gradle (démon) peut être endommagé. L’arrêt de tous les démons Gradle peut résoudre ce problème. Arrêter les processus de génération Gradle (nécessite un redémarrage). Dans le cas de processus Gradle endommagés, vous pouvez également essayer de fermer l’IDE, puis de tuer tous les processus Java.
Conseil
Votre projet utilise peut-être un plug-in tiers, qui n’est pas compatible avec les autres plug-ins du projet ou la version de Gradle demandée par le projet.
Ouvrez le menu Gradle à droite, accédez au menu Tâches du bubblepicker>, exécutez la tâche de build en appuyant deux fois dessus et attendez que le processus de génération se termine :
Ouvrez le navigateur de fichiers de dossier racine et accédez au dossier de build : Bubble-Pickerer -> bubblepicker -> build -> outputs -> aar, enregistrez le fichier bubblepicker-release.aar en tant que bubblepicker-v1.0.aar. Ce fichier sera utilisé plus tard dans le processus de liaison :
Le fichier AAR est une archive Android, qui contient le code source et les ressources Kotlin compilés, requis par Android pour exécuter une application à l’aide de ce kit SDK.
Préparer les métadonnées
La deuxième étape consiste à préparer le fichier de transformation des métadonnées, qui est utilisé par Xamarin.Android pour générer les classes C# respectives. Un projet de liaison Xamarin.Android découvrira toutes les classes natives et les membres d’une archive Android donnée, générant par la suite un fichier XML avec les métadonnées appropriées. Le fichier de transformation de métadonnées créé manuellement est ensuite appliqué à la base de référence précédemment générée pour créer le fichier de définition XML final utilisé pour générer le code C#.
Les métadonnées utilisent la syntaxe XPath et sont utilisées par le générateur de liaisons pour influencer la création de l’assembly de liaison. L’article Sur les métadonnées de liaison Java fournit plus d’informations sur les transformations, qui peuvent être appliquées :
Créez un fichier Metadata.xml vide :
<?xml version="1.0" encoding="UTF-8"?> <metadata> </metadata>
Définissez les transformations xml :
La bibliothèque Kotlin native a deux dépendances, que vous ne souhaitez pas exposer au monde C#, définissez deux transformations pour les ignorer complètement. Il est important de noter que les membres natifs ne seront pas supprimés du binaire résultant, seules les classes C# ne seront pas générées. Java Decompiler peut être utilisé pour identifier les dépendances. Exécutez l’outil et ouvrez le fichier AAR créé précédemment. Par conséquent, la structure de l’archive Android s’affiche, reflétant toutes les dépendances, valeurs, ressources, manifeste et classes :
Les transformations permettant d’ignorer le traitement de ces packages sont définies à l’aide des instructions XPath :
<remove-node path="/api/package[starts-with(@name,'org.jbox2d')]" /> <remove-node path="/api/package[starts-with(@name,'org.slf4j')]" />
La classe native
BubblePicker
a deux méthodesgetBackgroundColor
etsetBackgroundColor
la transformation suivante la transforme en une propriété C#BackgroundColor
:<attr path="/api/package[@name='com.igalata.bubblepicker.rendering']/class[@name='BubblePicker']/method[@name='getBackground' and count(parameter)=0]" name="propertyName">BackgroundColor</attr> <attr path="/api/package[@name='com.igalata.bubblepicker.rendering']/class[@name='BubblePicker']/method[@name='setBackground' and count(parameter)=1 and parameter[1][@type='int']]" name="propertyName">BackgroundColor</attr>
Les types
UInt, UShort, ULong, UByte
non signés nécessitent une gestion spéciale. Pour ces types, Kotlin modifie automatiquement les noms de méthodes et les types de paramètres, ce qui se reflète dans le code généré :public open fun fooUIntMethod(value: UInt) : String { return "fooUIntMethod${value}" }
Ce code est compilé dans le code d’octet Java suivant :
@NotNull public String fooUIntMethod-WZ4Q5Ns(int value) { return "fooUIntMethod" + UInt.toString-impl(value); }
En outre, les types connexes tels que
UIntArray, UShortArray, ULongArray, UByteArray
sont également affectés par Kotlin. Le nom de la méthode est modifié pour inclure un suffixe supplémentaire et les paramètres sont modifiés en tableau d’éléments de versions signées des mêmes types. Dans l’exemple ci-dessous, un paramètre de typeUIntArray
est converti automatiquement enint[]
et le nom de la méthode est remplacé parfooUIntArrayMethod
fooUIntArrayMethod--ajY-9A
. Ce dernier est découvert par les outils Xamarin.Android et généré en tant que nom de méthode valide :public open fun fooUIntArrayMethod(value: UIntArray) : String { return "fooUIntArrayMethod${value.size}" }
Ce code est compilé dans le code d’octet Java suivant :
@NotNull public String fooUIntArrayMethod--ajY-9A(@NotNull int[] value) { Intrinsics.checkParameterIsNotNull(value, "value"); return "fooUIntArrayMethod" + UIntArray.getSize-impl(value); }
Pour lui donner un nom explicite, les métadonnées suivantes peuvent être ajoutées à la Metadata.xml, ce qui met à jour le nom pour qu’il soit défini à l’origine dans le code Kotlin :
<attr path="/api/package[@name='com.microsoft.simplekotlinlib']/class[@name='FooClass']/method[@name='fooUIntArrayMethod--ajY-9A']" name="managedName">fooUIntArrayMethod</attr>
Dans l’exemple BubblePicker, il n’y a aucun membre utilisant des types non signés. Aucune modification supplémentaire n’est donc requise.
Membres Kotlin avec des paramètres génériques par défaut transformés en paramètres de Java.
Lang.Object
Type. Par exemple, une méthode Kotlin a un paramètre <générique T> :public open fun <T>fooGenericMethod(value: T) : String { return "fooGenericMethod${value}" }
Une fois qu’une liaison Xamarin.Android est générée, la méthode est exposée à C# comme ci-dessous :
[Register ("fooGenericMethod", "(Ljava/lang/Object;)Ljava/lang/String;", "GetFooGenericMethod_Ljava_lang_Object_Handler")] [JavaTypeParameters (new string[] { "T" })] public virtual string FooGenericMethod (Java.Lang.Object value);
Les génériques Java et Kotlin ne sont pas pris en charge par les liaisons Xamarin.Android. Par conséquent, une méthode C# généralisée pour accéder à l’API générique est créée. En tant que solution de contournement, vous pouvez créer une bibliothèque Kotlin de wrapper et exposer les API requises de manière fortement typée sans génériques. Vous pouvez également créer des helpers côté C# pour résoudre le problème de la même manière via des API de type fort.
Conseil
En transformant les métadonnées, toutes les modifications peuvent être appliquées à la liaison générée. L’article Liaison de bibliothèque Java explique en détail comment les métadonnées sont générées et traitées.
Créer une bibliothèque de liaisons
L’étape suivante consiste à créer un projet de liaison Xamarin.Android à l’aide du modèle de liaison Visual Studio, à ajouter les métadonnées requises, les références natives, puis à générer le projet pour produire une bibliothèque consommable :
Ouvrez Visual Studio pour Mac et créez un projet de bibliothèque de liaison Xamarin.Android, donnez-lui un nom, dans ce cas testBubblePicker.Binding, puis terminez l’Assistant. Le modèle de liaison Xamarin.Android se trouve par le chemin suivant : Bibliothèque de liaison de bibliothèque > Android >:
Le dossier Transformations contient trois fichiers de transformation main :
- Metadata.xml : permet d’apporter des modifications à l’API finale, telles que la modification de l’espace de noms de la liaison générée.
- EnumFields.xml : contient le mappage entre les constantes int Java et les énumérations C#.
- EnumMethods.xml : permet de modifier les paramètres de méthode et de retourner des types de constantes Java int vers des énumérations C#.
Conservez les fichiers EnumFields.xml et EnumMethods.xml vides, puis mettez à jour les Metadata.xml pour définir vos transformations.
Remplacez le fichier Transformations/Metadata.xml existant par le fichier Metadata.xml créé à l’étape précédente. Dans la fenêtre propriétés, vérifiez que l’action de génération du fichier est définie sur TransformationFile :
Ajoutez le fichier bubblepicker-v1.0.aar que vous avez créé à l’étape 1 au projet de liaison en tant que référence native. Pour ajouter des références de bibliothèque native, ouvrez finder et accédez au dossier avec l’archive Android. Faites glisser et déposez l’archive dans le dossier Jars dans Explorateur de solutions. Vous pouvez également utiliser l’option de menu contextuel Ajouter dans le dossier Jars et choisir Fichiers existants.... Choisissez de copier le fichier dans le répertoire pour les besoins de cette procédure pas à pas. Veillez à vérifier que l’action de génération est définie sur LibraryProjectZip :
Ajoutez une référence au package NuGet Xamarin.Kotlin.StdLib . Ce package est une liaison pour la bibliothèque Standard Kotlin. Sans ce package, la liaison ne fonctionnera que si la bibliothèque Kotlin n’utilise aucun type spécifique à Kotlin. Sinon, tous ces membres ne seront pas exposés à C# et toute application qui tente de consommer la liaison se bloque au moment de l’exécution.
Conseil
En raison d’une limitation de Xamarin.Android, les outils de liaison ne peuvent ajouter qu’une seule archive Android (AAR) par projet de liaison. Si plusieurs fichiers AAR doivent être inclus, plusieurs projets Xamarin.Android sont requis, un par AAR. Si tel était le cas pour cette procédure pas à pas, les quatre actions précédentes de cette étape doivent être répétées pour chaque archive. En guise d’option alternative, il est possible de fusionner manuellement plusieurs archives Android sous la forme d’une seule archive, ce qui vous permet d’utiliser un seul projet de liaison Xamarin.Android.
La dernière action consiste à générer la bibliothèque et à ne pas avoir d’erreurs de compilation. En cas d’erreurs de compilation, elles peuvent être traitées et gérées à l’aide du fichier Metadata.xml que vous avez créé précédemment en ajoutant des métadonnées de transformation xml, qui ajouteront, suppriment ou renomment des membres de la bibliothèque.
Consommer la bibliothèque de liaisons
La dernière étape consiste à utiliser la bibliothèque de liaison Xamarin.Android dans une application Xamarin.Android. Créez un projet Xamarin.Android, ajoutez une référence à la bibliothèque de liaisons et affichez l’interface utilisateur du sélecteur de bulles :
Créez un projet Xamarin.Android. Utilisez l’application Android Application > Android > comme point de départ et sélectionnez l’option La plus récente et la plus grande en tant que plateformes cibles pour éviter les problèmes de compatibilité. Toutes les étapes suivantes ciblent ce projet :
Ajoutez une référence de projet au projet de liaison ou ajoutez une référence à la DLL créée précédemment :
Ajoutez une référence au package NuGet Xamarin.Kotlin.StdLib que vous avez ajouté au projet de liaison Xamarin.Android précédemment. Il ajoute la prise en charge de tous les types spécifiques kotlin qui doivent être donnés au moment de l’exécution. Sans ce package, l’application peut être compilée, mais se bloque au moment de l’exécution :
Ajoutez le
BubblePicker
contrôle à la disposition Android pourMainActivity
. Ouvrez le fichier testBubblePicker/Resources/layout/content_main.xml et ajoutez le nœud de contrôle BubblePicker comme dernier élément du contrôle RelativeLayout racine :<?xml version="1.0" encoding="utf-8"?> <RelativeLayout …> … <com.igalata.bubblepicker.rendering.BubblePicker android:id="@+id/picker" android:layout_width="match_parent" android:layout_height="match_parent" app:backgroundColor="@android:color/white" /> </RelativeLayout>
Mettez à jour le code source de l’application et ajoutez la logique d’initialisation au
MainActivity
, qui active le Kit de développement logiciel (SDK) Bubble Picker :protected override void OnCreate(Bundle savedInstanceState) { ... var picker = FindViewById<BubblePicker>(Resource.Id.picker); picker.BubbleSize = 20; picker.Adapter = new BubblePickerAdapter(); picker.Listener = new BubblePickerListener(picker); ... }
BubblePickerAdapter
etBubblePickerListener
sont deux classes à créer à partir de zéro, qui gèrent les données de bulles et contrôlent l’interaction :public class BubblePickerAdapter : Java.Lang.Object, IBubblePickerAdapter { private List<string> _bubbles = new List<string>(); public int TotalCount => _bubbles.Count; public BubblePickerAdapter() { for (int i = 0; i < 10; i++) { _bubbles.Add($"Item {i}"); } } public PickerItem GetItem(int itemIndex) { if (itemIndex < 0 || itemIndex >= _bubbles.Count) return null; var result = _bubbles[itemIndex]; var item = new PickerItem(result); return item; } } public class BubblePickerListener : Java.Lang.Object, IBubblePickerListener { public View Picker { get; } public BubblePickerListener(View picker) { Picker = picker; } public void OnBubbleDeselected(PickerItem item) { Snackbar.Make(Picker, $"Deselected: {item.Title}", Snackbar.LengthLong) .SetAction("Action", (Android.Views.View.IOnClickListener)null) .Show(); } public void OnBubbleSelected(PickerItem item) { Snackbar.Make(Picker, $"Selected: {item.Title}", Snackbar.LengthLong) .SetAction("Action", (Android.Views.View.IOnClickListener)null) .Show(); } }
Exécutez l’application, qui doit afficher l’interface utilisateur du sélecteur de bulles :
L’exemple nécessite du code supplémentaire pour afficher le style des éléments et gérer les interactions, mais le
BubblePicker
contrôle a été créé et activé avec succès.
Félicitations ! Vous avez créé une application Xamarin.Android et une bibliothèque de liaison, qui consomme une bibliothèque Kotlin.
Vous devez maintenant disposer d’une application Xamarin.Android de base qui utilise une bibliothèque Kotlin native via une bibliothèque de liaison Xamarin.Android. Cette procédure pas à pas utilise intentionnellement un exemple de base pour mieux mettre en évidence les concepts clés introduits. Dans des scénarios réels, vous devrez probablement exposer un plus grand nombre d’API et leur appliquer des transformations de métadonnées.