Xamarin.Android
Publier votre APK Xamarin.Android
Recherche…
Introduction
Cette rubrique affiche des informations sur la préparation de votre application Xamarin.Android pour le mode de publication et son optimisation.
Préparer votre APK dans Visual Studio
Vous avez terminé votre application, testée en mode débogage et elle fonctionne parfaitement. Maintenant, vous voulez le préparer pour publier dans le Google Play Store.
La documentation de Xamarin fournit de bonnes informations ici:
Manifeste Android
Tout d'abord, dans Visual Studio, cliquez avec le bouton droit sur votre projet Xamarin.Android dans l'Explorateur de solutions et sélectionnez Propriétés. Ensuite, allez dans l'onglet Manifeste Android, pour voir cet écran:
Contrairement à Android Studio ou Eclipse, vous n'avez pas besoin de définir le fichier AndroidManifest.xml en écrivant; Xamarin et Visual Studio font cela pour vous. Activités, BroadcastReceivers et Services sont insérés dans Android Manifest en déclarant des attributs spécifiques dans leurs classes .
Dans cet écran, les options sont les suivantes:
- Nom de l'application : c'est le nom de l'application qui sera visible pour l'utilisateur.
- Nom du package : il s'agit du nom du package. Il doit être unique, ce qui signifie qu'il ne doit pas utiliser le même nom de package que les autres applications du Google Play Store.
- Icône de l'application : C'est l'icône qui sera visible pour l'utilisateur, équivalente à @ drawable / ic_launcher utilisée dans les projets Android Studio ou Eclipse.
- Numéro de version : le numéro de version est utilisé par Google Play pour le contrôle de version. Lorsque vous souhaitez publier un fichier APK pour une version mise à jour de votre application, vous devez ajouter 1 à ce numéro pour chaque nouvelle mise à niveau.
- Nom de la version : c'est le nom de la version qui sera affiché à l'utilisateur.
- Emplacement d'installation : Ceci détermine où votre APK sera installé, dans le stockage de l'appareil ou sur la carte SD.
- Autorisations requises : vous déterminez ici les autorisations nécessaires pour votre application.
Options Android
Dans l'écran ci-dessous, vous pouvez configurer les options du compilateur. L'utilisation des bonnes options ici peut réduire considérablement la taille de votre fichier APK et éviter les erreurs.
- Configuration : Active (Release) .
- Plate - forme : active (n'importe quel processeur) . Celles-ci sont nécessaires pour construire votre APK pour le Google Play Store. Si la configuration est définie sur Debug, elle ne sera pas acceptée par Google Play.
- Utiliser le runtime partagé : false . Si vous le définissez sur true, l'APK utilisera Mono Runtime pour s'exécuter. Le Mono Runtime est installé automatiquement lors du débogage via USB, mais pas dans l'APK Release. Si Mono Runtime n'est pas installé sur le périphérique et que cette option est définie sur true dans la version APK, l'application se bloque.
- Générez un package (.apk) par ABI sélectionné : false . Créez votre APK pour autant de plates-formes que possible, pour des raisons de compatibilité.
- Activez Multi-Dex : true , mais vous pouvez le définir sur false si votre application n'est pas très complexe (c'est-à-dire qu'elle contient moins de 65 536 méthodes, voir ici ).
- Activer Proguard : true . Cela active l'outil Proguard qui masque le code Java dans votre application. Notez qu'il ne s'applique pas au code .NET; Si vous voulez masquer le code .NET, vous devez utiliser Dotfuscator . Plus d'informations sur Proguard pour Xamarin.Android peuvent être trouvées ici .
- Activer l'instrumentation de développeur (débogage et profilage) : false pour Release APK.
- Liaison : SDK et assemblages d'utilisateurs . Cela rendra le Xamarin Linker pour supprimer toutes les classes inutilisées du SDK et de votre code, réduisant ainsi la taille de l'APK.
Important
Xamarin.Linker peut parfois supprimer des classes qui ne semblent pas être utilisées par votre code, surtout si elles se trouvent dans le Core du projet (bibliothèque PCL). Pour éviter cela, vous pouvez soit définir la liaison avec "Sdk Assemblies Only" ou utiliser l'attribut Preserve dans vos classes, par exemple:
PreserveAttribute.cs
namespace My_App_Core.Models
{
public sealed class PreserveAttribute : System.Attribute
{
public bool AllMembers;
public bool Conditional;
}
}
Dans une classe:
using System;
namespace My_App_Core.Models
{
[Preserve(AllMembers = true)]
public class ServiceException : Exception
{
public int errorCode;
[Preserve(AllMembers = true)]
public ServiceException() { }
[Preserve(AllMembers = true)]
public ServiceException(int errorCode)
{
this.errorCode = errorCode;
}
}
}
- Architectures prises en charge : sélectionnez tout pour des raisons de compatibilité.
Après avoir tout configuré, reconstruisez le projet pour vous assurer qu'il se construit correctement.
Création du mode APK pour Release
Vous avez fini de configurer votre projet Android pour Release. Le tutoriel ci-dessous montre comment générer l'APK dans Visual Studio. Un tutoriel complet de la documentation Xamarin peut être trouvé ici:
Pour créer le fichier APK, cliquez avec le bouton droit sur le projet Xamarin.Android dans l'Explorateur de solutions et sélectionnez Archiver ...
Cela ouvrira le gestionnaire d'archives et archivera le projet, en préparant le fichier APK.
Une fois l'archivage du projet terminé, cliquez sur Distribuer ... pour continuer.
L'écran Distribuer vous présente deux options: Ad-hoc et Google Play. Le premier va créer un APK et l'enregistrer sur votre ordinateur. La seconde publiera directement l'application dans Google Play.
Le choix du premier est recommandé, vous pouvez donc tester l'APK sur d'autres appareils si vous le souhaitez.
Dans l'écran suivant, un Key Store Android est nécessaire pour signer l'APK. Si vous en avez déjà un, vous pouvez l'utiliser en cliquant sur Importer ...; Si vous ne le faites pas, vous pouvez créer un nouveau magasin de clés Android en cliquant sur +.
Création d'un nouvel écran Android Key Store:
Pour créer l'APK, cliquez sur Enregistrer sous. Vous pouvez être invité à saisir le mot de passe du magasin de clés.
Lorsque cela est terminé, vous pouvez cliquer sur Ouvrir un dossier sur l'écran Archives pour voir le fichier APK généré.
Activation de MultiDex dans votre APK Xamarin.Android
MultiDex est une bibliothèque dans l'APK Android qui permet à l'application d'avoir plus de 65 536 méthodes.
Les APK Android ont des fichiers exécutables Dalvik (.dex) qui contiennent les bytecodes générés à partir de votre code Java. Chaque fichier .dex peut contenir jusqu'à 65 536 méthodes (2 ^ 16).
Les versions d'Android OS antérieures à Android 5.0 Lollipop (API 21) utilisent le moteur d'exécution Dalvik, qui ne prend en charge qu'un seul fichier .dex par APK, en limitant à 65 536 méthodes par APK. À partir d'Android 5.0, le système d'exploitation Android utilise ART runtime, qui peut prendre en charge plusieurs fichiers .dex par APK, en évitant la limite.
Pour dépasser la limite des méthodes 65k dans les versions Android inférieures à l'API 21, les développeurs doivent utiliser la bibliothèque de support MultiDex. Le MultiDex crée des fichiers classes.dex supplémentaires (classes2.dex, classes3.dex, ...) en les référençant dans le fichier classes.dex. Lorsque l'application commence à charger, elle utilise une classe MultiDexApplication pour charger les fichiers .dex supplémentaires.
Si votre application Android vise une version minimale du SDK au-dessus ou égale à l’API 21 (Android 5.0 Lollipop), il n’est pas nécessaire d’utiliser la bibliothèque MultiDex, car le système d’exploitation gère nativement les fichiers .dex supplémentaires. Cependant, si, pour des raisons de compatibilité, le développeur souhaite prendre en charge un ancien système d'exploitation Android, il doit alors utiliser la bibliothèque MultiDex.
Comment utiliser MultiDex dans votre application Xamarin.Android
Tout d'abord, pour activer MultiDex dans votre application Xamarin.Android, accédez à votre projet Propriétés -> Options Android -> Conditionnement -> Activer Multi-Dex, comme dans l'écran d'impression ci-dessous:
Ensuite, vous devez créer une classe MultiDexApplication dans votre application. Dans la racine du projet, créez une nouvelle classe (dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet, Ajouter .. -> Classe ou Maj + Alt + C). Dans le nouveau fichier de classe, copiez le code suivant, en remplaçant l'exemple d'espace de noms par le nom de votre espace de noms de projet Xamarin.Android.
using System;
using Android.App;
using Android.Runtime;
using Java.Interop;
namespace Sample
{
[Register("android/support/multidex/MultiDexApplication", DoNotGenerateAcw = true)]
public class MultiDexApplication : Application
{
internal static readonly JniPeerMembers _members =
new XAPeerMembers("android/support/multidex/MultiDexApplication", typeof (MultiDexApplication));
internal static IntPtr java_class_handle;
private static IntPtr id_ctor;
[Register(".ctor", "()V", "", DoNotGenerateAcw = true)]
public MultiDexApplication()
: base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
{
if (Handle != IntPtr.Zero)
return;
try
{
if (GetType() != typeof (MultiDexApplication))
{
SetHandle(
JNIEnv.StartCreateInstance(GetType(), "()V"),
JniHandleOwnership.TransferLocalRef);
JNIEnv.FinishCreateInstance(Handle, "()V");
return;
}
if (id_ctor == IntPtr.Zero)
id_ctor = JNIEnv.GetMethodID(class_ref, "<init>", "()V");
SetHandle(
JNIEnv.StartCreateInstance(class_ref, id_ctor),
JniHandleOwnership.TransferLocalRef);
JNIEnv.FinishCreateInstance(Handle, class_ref, id_ctor);
}
finally
{
}
}
protected MultiDexApplication(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
internal static IntPtr class_ref
{
get { return JNIEnv.FindClass("android/support/multidex/MultiDexApplication", ref java_class_handle); }
}
protected override IntPtr ThresholdClass
{
get { return class_ref; }
}
protected override Type ThresholdType
{
get { return typeof (MultiDexApplication); }
}
}
}
Si vous développez dans Visual Studio pour Windows, il existe également un bogue dans les outils de construction du SDK Android que vous devez corriger pour créer correctement les fichiers classes.dex lors de la construction de votre projet.
Accédez à votre dossier SDK Android, ouvrez le dossier build-tools et il y aura des dossiers avec les numéros des compilateurs du SDK Android, tels que:
C: \ android-sdk \ build-tools \ 23.0.3 \
C: \ android-sdk \ build-tools \ 24.0.1 \
C: \ android-sdk \ build-tools \ 25.0.2 \
À l'intérieur de chacun de ces dossiers, il y a un fichier appelé mainClassesDex.bat , un script de commandes utilisé pour créer les fichiers classes.dex. Ouvrez chaque fichier mainClassesDex.bat avec un éditeur de texte (Notepad ou Notepad ++) et dans son script, recherchez et remplacez le bloc:
if DEFINED output goto redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%disableKeepAnnotated%" "%tmpJar%" "%params%"
goto afterClassReferenceListBuilder
:redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%disableKeepAnnotated%" "%tmpJar%" "%params%" 1>"%output%"
:afterClassReferenceListBuilder
Avec le bloc:
SET params=%params:'=%
if DEFINED output goto redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder %disableKeepAnnotated% "%tmpJar%" %params%
goto afterClassReferenceListBuilder
:redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder %disableKeepAnnotated% "%tmpJar%" %params% 1>"%output%"
:afterClassReferenceListBuilder
Enregistrez chaque mainClassesDex.bat dans l'éditeur de texte après les modifications.
Après les étapes ci-dessus, vous devriez pouvoir créer votre application Xamarin.Android avec MultiDex.
Activation de ProGuard dans votre APK Xamarin.Android
ProGuard est un outil utilisé dans le processus de création pour optimiser et masquer le code Java de votre APK, ainsi que pour supprimer les classes inutilisées. Le résultat APK lors de l'utilisation de ProGuard aura une taille plus petite et sera plus difficile à désosser (décompilation).
ProGuard peut également être utilisé dans les applications Xamarin.Android et réduira également la taille du fichier APK et masquera le code Java. Sachez cependant que l'obfuscation de ProGuard s'applique uniquement au code Java. Pour brouiller le code .NET, le développeur doit utiliser Dotfuscator ou des outils similaires.
Comment utiliser ProGuard dans votre application Xamarin.Android
Tout d'abord, pour activer ProGuard dans votre application Xamarin.Android, accédez à votre projet Propriétés -> Options Android -> Conditionnement -> Activer ProGuard, comme dans l'écran d'impression ci-dessous:
Cela permet à ProGuard de créer votre application.
Xamarin.Android, par défaut, définit ses propres configurations pour ProGuard, qui se trouvent dans les dossiers obj/Debug/proguard
ou obj/Release/proguard
, dans les fichiers proguard_project_primary.cfg
, proguard_project_references.cfg
et proguard_xamarin.cfg
. Les trois fichiers sont combinés en tant que configurations pour ProGuard et ils sont automatiquement créés par Xamarin lors de la création.
Si le développeur souhaite personnaliser davantage les options de ProGuard, il peut créer un fichier dans la racine du projet nommé proguard.cfg
(les autres noms sont également valides, tant que l'extension est .cfg) et définir son action de génération sur ProguardConfiguration, comme dans l'image ci-dessous:
Dans le fichier, des options ProGuard personnalisées peuvent être insérées, telles que -dontwarn
, -keep class
et autres .
Important
À ce jour (avril 2017), le SDK Android généralement téléchargé possède une ancienne version de ProGuard, ce qui peut entraîner des erreurs lors de la création de l'application à l'aide de Java 1.8. Lors de la construction, la liste des erreurs affiche le message suivant:
Error
Can't read [C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v7.0\mono.android.jar]
(Can't process class [android/app/ActivityTracker.class] (Unsupported class version number [52.0] (maximum 51.0, Java 1.7))) [CREATEMULTIDEXMAINDEXCLASSLIST]
Pour résoudre ce problème, vous devez télécharger la version la plus récente de ProGuard ( ici ) et copier le contenu du fichier .zip dans android-sdk\tools\proguard\
. Cela mettra à jour ProGuard et le processus de construction devrait fonctionner sans problème.
Après cela, vous devriez être capable de créer votre application Xamarin.Android avec ProGuard.
Bugs "mystérieux" liés à ProGuard et Linker
Vous avez créé une application géniale et l'avez testée dans Debug, avec de bons résultats. Tout fonctionnait bien!
Mais alors, vous avez décidé de préparer votre application pour la publication. Vous avez configuré MultiDex, ProGuard et Linker, puis il a cessé de fonctionner.
Ce tutoriel a pour but de vous aider à identifier les problèmes courants liés à ProGuard et Linker qui peuvent causer des bogues mystérieux.
Comprendre Xamarin.Linker
Xamarin.Linker est un outil du processus de construction qui supprime le code et les classes inutilisés de votre code .NET (pas le code Java) . Dans les propriétés de votre projet -> Options Android -> Linker, il y aura une boîte de sélection Liaison avec les options:
Aucun : aucun code n'est supprimé.
Assemblages SDK uniquement : cette option permet au Xamarin.Linker de rechercher le code inutilisé uniquement dans les bibliothèques Xamarin. Cette option est sûre.
Sdk et User Assemblies : cette option permet au Xamarin.Linker de rechercher le code inutilisé dans les bibliothèques Xamarin et dans le code du projet (y compris les PCL, les composants Xamarin et les packages NuGet). Cette option n'est pas toujours sûre!
Lors de l'utilisation de l'option Sdk et User Assemblies, Xamarin.Linker peut penser que des parties du code ne sont pas utilisées lorsque, en réalité, elles sont très utilisées! Cela peut empêcher certaines bibliothèques de fonctionner correctement et causer des bogues dans votre application.
Pour que le Xamarin.Linker ne supprime pas le code, il existe 3 options:
- Définition de l'option de liaison sur None ou Sdk Assemblies uniquement;
- Ignorer les assemblages de liens;
- Utiliser l'attribut Preserve.
Exemple pour 2. Ignorer les assemblages de liaison:
Dans l'exemple ci-dessous, l'utilisation de Xamarin.Linker a provoqué un arrêt du fonctionnement de NuGet Package ( Octokit ), car il ne pouvait plus se connecter à Internet:
[0:] ERROR
[0:] SOURCE: mscorlib
[0:] MESSAGE: Object reference not set to an instance of an object.
[0:] STACK TRACE: at Octokit.PocoJsonSerializerStrategy.DeserializeObject (System.Object value, System.Type type) [0x003d8] in D:\repos\octokit.net\Octokit\SimpleJson.cs:1472
at Octokit.Internal.SimpleJsonSerializer+GitHubSerializerStrategy.DeserializeObject (System.Object value, System.Type type) [0x001c3] in D:\repos\octokit.net\Octokit\Http\SimpleJsonSerializer.cs:165
at Octokit.SimpleJson.DeserializeObject (System.String json, System.Type type, Octokit.IJsonSerializerStrategy jsonSerializerStrategy) [0x00007] in D:\repos\octokit.net\Octokit\SimpleJson.cs:583
at Octokit.SimpleJson.DeserializeObject[T] (System.String json, Octokit.IJsonSerializerStrategy jsonSerializerStrategy) [0x00000] in D:\repos\octokit.net\Octokit\SimpleJson.cs:595
at Octokit.Internal.SimpleJsonSerializer.Deserialize[T] (System.String json) [0x00000] in D:\repos\octokit.net\Octokit\Http\SimpleJsonSerializer.cs:21
at Octokit.Internal.JsonHttpPipeline.DeserializeResponse[T] (Octokit.IResponse response) [0x000a7] in D:\repos\octokit.net\Octokit\Http\JsonHttpPipeline.cs:62
at Octokit.Connection+<Run>d__54`1[T].MoveNext () [0x0009c] in D:\repos\octokit.net\Octokit\Http\Connection.cs:574
--- End of stack trace from previous location where exception was thrown ---
Pour que la bibliothèque recommence à fonctionner, il était nécessaire d'ajouter le nom de référence du package dans le champ Ignorer les assemblages de liaison, situé dans le projet -> Propriétés -> Options Android -> Linker, comme dans l'image ci-dessous:
Après cela, la bibliothèque a commencé à fonctionner sans aucun problème.
Exemple pour 3. Utilisation de l'attribut Preserve:
Xamarin.Linker perçoit comme un code inutilisé principalement le code des classes de modèle dans le noyau de votre projet.
Pour que la classe soit préservée pendant le processus de liaison, vous pouvez utiliser l'attribut Preserve.
Tout d'abord, créez dans le noyau de votre projet une classe nommée PreserveAttribute.cs , insérez le code suivant et remplacez l'espace de noms par l'espace de noms de votre projet:
PreserveAttribute.cs:
namespace My_App_Core.Models
{
public sealed class PreserveAttribute : System.Attribute
{
public bool AllMembers;
public bool Conditional;
}
}
Dans chaque classe de modèle du noyau de votre projet, insérez l'attribut Préserver comme dans l'exemple ci-dessous:
Country.cs:
using System;
using System.Collections.Generic;
namespace My_App_Core.Models
{
[Preserve(AllMembers = true)]
public class Country
{
public String name { get; set; }
public String ISOcode { get; set; }
[Preserve(AllMembers = true)]
public Country(String name, String ISOCode)
{
this.name = name;
this.ISOCode = ISOCode;
}
}
}
Après cela, le processus de liaison ne supprimera plus le code conservé.
Comprendre ProGuard
ProGuard est un outil du processus de construction qui supprime le code et les classes inutilisés de votre code Java . Il obscurcit et optimise également le code.
Cependant, ProGuard peut parfois supprimer le code qu'il considère inutilisé, alors que ce n'est pas le cas. Pour éviter cela, le développeur doit déboguer l'application (dans le moniteur de périphérique Android et dans le débogage Visual Studio) et détecter quelle classe a été supprimée, puis configurer le fichier de configuration ProGuard pour conserver la classe.
Exemple
Dans l'exemple ci-dessous, ProGuard a supprimé deux classes (Android.Support.V7.Widget.FitWindowsLinearLayout et Android.Support.Design.Widget.AppBarLayout) utilisées dans les fichiers de mise en page AXML, mais perçues comme non utilisées dans le code. La suppression a provoqué une exception ClassNotFoundException dans le code Java lors du rendu de la disposition de l'activité:
layout_activitymain.axml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activitymain_drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" <!-- ### HERE ### -->
tools:openDrawer="start">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- ### HERE ## -->
<android.support.design.widget.AppBarLayout
android:id="@+id/activitymain_appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
...
LogCat indiquant une erreur lors de la création de la mise en page dans SetContentView:
Pour corriger cette erreur, il était nécessaire d'ajouter les lignes suivantes au fichier de configuration ProGuard du projet:
-keep public class android.support.v7.widget.FitWindowsLinearLayout
-keep public class android.support.design.widget.AppBarLayout
Après cela, plus aucune erreur n'a été affichée lors de la création de la mise en page.
Avertissements ProGuard
ProGuard affiche parfois des avertissements dans la liste des erreurs après la création de votre projet. Bien qu'ils posent la question de savoir si votre application est correcte ou non, tous leurs avertissements n'indiquent pas de problèmes, en particulier si votre application est correctement créée.
Par exemple, lorsque vous utilisez la bibliothèque Picasso : lorsque vous utilisez ProGuard, cela peut afficher des avertissements tels que okio.Okio: can't find referenced class (...)
ou d’ can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [okhttp.jar:META-INF/MANIFEST.MF]) (...)
, mais l'application est construite et la bibliothèque fonctionne sans problème.