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:

https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application/


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:

Configuration du manifeste Android

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 des options Android

  • 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:

https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application/part_2_-_signing_the_android_application_package/

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 ...

Explorateur de solutions -> cliquez-droit sur le projet Xamarin.Android -> Archiver ...

Cela ouvrira le gestionnaire d'archives et archivera le projet, en préparant le fichier APK.

Projet d'archivage

Une fois l'archivage du projet terminé, cliquez sur Distribuer ... pour continuer.

Distribuer...

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.

Canaux de distribution

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 +.

Identité de signature

Création d'un nouvel écran Android Key Store:

Création d'un nouveau magasin de clés Android

Pour créer l'APK, cliquez sur Enregistrer sous. Vous pouvez être invité à saisir le mot de passe du magasin de clés.

Enregistrer sous

Enregistrer sous -> Localiser le dossier

Entrez 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é.

Dossier ouvert

APK dans le dossier

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:

Activer l'option MultiDex

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); }
        }
    }
}

Code source ici.

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

Source ici

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:

Activer ProGuard

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:

Définition d'une action de génération sur ProguardConfiguration

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]

Source ici

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:

Options de l'éditeur de liens

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:

  1. Définition de l'option de liaison sur None ou Sdk Assemblies uniquement;
  2. Ignorer les assemblages de liens;
  3. 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:

Ajout d'une référence de projet pour ignorer les assemblys de liaison

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:

Erreur d'affichage dans LogCat

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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow