Ricerca…


introduzione

Questo argomento mostra informazioni su come preparare la tua app Xamarin.Android per la modalità di rilascio e su come ottimizzarla.

Preparazione dell'APK in Visual Studio

Hai finito la tua app, testato in modalità di debug e funziona perfettamente. Ora, vuoi prepararlo per la pubblicazione nel Google Play Store.

La documentazione di Xamarin fornisce buone informazioni qui:

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


Manifest Android

Innanzitutto, in Visual Studio, fai clic con il pulsante destro del mouse sul progetto Xamarin.Android in Esplora soluzioni e seleziona Proprietà. Quindi, vai alla scheda Manifest Android, per vedere questa schermata:

Configurazione del manifest Android

A differenza di Android Studio o Eclipse, non è necessario impostare il file AndroidManifest.xml scrivendo; Xamarin e Visual Studio lo fanno per te. Attività, BroadcastReceivers e Servizi sono inseriti in Android Manifest dichiarando attributi specifici nelle loro classi .

In questa schermata, le opzioni sono:

  • Nome dell'applicazione : questo è il nome dell'app che sarà visibile all'utente.
  • Nome del pacchetto : questo è il nome del pacchetto. Deve essere univoco, il che significa che non deve utilizzare lo stesso nome di pacchetto di altre app nel Google Play Store.
  • Icona dell'applicazione : questa è l'icona che sarà visibile all'utente, equivalente al @ drawable / ic_launcher utilizzato nei progetti Android Studio o Eclipse.
  • Numero di versione : il numero di versione è utilizzato da Google Play per il controllo della versione. Quando si desidera pubblicare un APK per una versione aggiornata della propria app, è necessario aggiungere 1 a questo numero per ogni nuovo aggiornamento.
  • Nome versione : questo è il nome della versione che verrà visualizzato all'utente.
  • Posizione di installazione : determina dove verrà installato l'APK, nella memoria del dispositivo o nella scheda SD.
  • Autorizzazioni richieste : qui puoi determinare quali autorizzazioni sono necessarie per la tua app.

Opzioni Android

Nella schermata sottostante, puoi configurare le opzioni del compilatore. L'uso delle opzioni giuste qui può ridurre molto la dimensione del tuo APK e anche prevenire errori.

Configurazione delle opzioni Android

  • Configurazione : attiva (rilascio) .
  • Piattaforma : attiva (qualsiasi CPU) . Questi sono necessari per creare il tuo APK per Google Play Store. Se la configurazione è impostata su debug, non sarà accettata da Google Play.
  • Usa runtime condiviso : falso . Se si imposta su true, l'APK utilizzerà Mono Runtime per l'esecuzione. Mono Runtime viene installato automaticamente durante il debug tramite USB, ma non nel Release APK. Se Mono Runtime non è installato nel dispositivo e questa opzione è impostata su true nell'APK di rilascio, l'app si arresta in modo anomalo.
  • Genera un pacchetto (.apk) per ogni ABI selezionato : falso . Crea il tuo APK per quante più piattaforme possibili, per ragioni di compatibilità.
  • Attiva Multi-Dex : true , ma puoi impostarlo su false se la tua app non è molto complessa (cioè ha meno di 65536 metodi, vedi qui ).
  • Abilita Proguard : vero . Ciò abilita lo strumento Proguard che nasconde il codice Java nella tua app. Si noti che non si applica al codice .NET; se vuoi offuscare il codice .NET, devi usare Dotfuscator . Maggiori informazioni su Proguard per Xamarin.Android possono essere trovate qui .
  • Abilita la strumentazione per sviluppatori (debugging e profiling) : false per Release APK.
  • Collegamento : SDK e gruppi utente . In questo modo Xamarin Linker rimuoverà tutte le classi non utilizzate dall'SDK e dal codice, riducendo la dimensione dell'APK.

Importante

Xamarin.Linker può talvolta rimuovere classi che non sembrano essere utilizzate dal codice, specialmente se si trovano nel Core del progetto (libreria PCL). Per evitare ciò, è possibile impostare il collegamento su "Solo assembly Sdk" o utilizzare l'attributo Preserve nelle classi, ad esempio:

PreserveAttribute.cs

namespace My_App_Core.Models
{
    public sealed class PreserveAttribute : System.Attribute
    {
        public bool AllMembers;
        public bool Conditional;
    }
}

In una 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;
        }
    }
}
  • Architetture supportate : seleziona tutto , per motivi di compatibilità.

Dopo aver configurato tutto, ricompilare il progetto per assicurarsi che si sviluppi correttamente.


Creazione dell'APK per la modalità di rilascio

Hai finito di configurare il tuo progetto Android per la versione. Il tutorial qui sotto mostra come generare l'APK in Visual Studio. Un tutorial completo dalla documentazione di Xamarin può essere trovato qui:

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

Per creare il file APK, fare clic con il tasto destro del mouse sul progetto Xamarin.Android in Solution Explorer e selezionare Archivia ...

Solution Explorer -> fai clic con il tasto destro del mouse su Xamarin.Android project -> Archivia ...

Questo aprirà il gestore degli archivi e inizierà l'archiviazione del progetto, preparandosi a creare il file APK.

Progetto di archiviazione

Al termine dell'archiviazione del progetto, fai clic su Distribuisci ... per procedere.

Distribuire...

La schermata Distribuisci ti presenterà due opzioni: Ad-hoc e Google Play. Il primo creerà un APK e lo salverà sul tuo computer. Il secondo pubblicherà direttamente l'app su Google Play.

La scelta del primo è consigliata, quindi puoi testare l'APK in altri dispositivi, se lo desideri.

Canali di distribuzione

Nella schermata seguente è necessario un Key Store Android per firmare l'APK. Se ne hai già uno, puoi usarlo facendo clic su Importa ...; se non lo fai, puoi creare un nuovo Key Store Android facendo clic su +.

Identità di firma

Creazione di una nuova schermata di Key Store Android:

Creazione di un nuovo Key Store Android

Per creare l'APK, fare clic su Salva con nome. Potrebbe essere richiesto di digitare la password dell'archivio chiavi.

Salva come

Salva come -> trova cartella

Inserisci la password del Key Store

Al termine, puoi fare clic su Apri cartella nella schermata Archivi per visualizzare il file APK generato.

Cartella aperta

APK nella cartella

Abilitazione di MultiDex nel tuo APK Xamarin.Android

MultiDex è una libreria nell'APK Android che consente all'app di avere più di 65.536 metodi.

Gli APK Android hanno file eseguibili Dalvik (.dex) che contengono i bytecode generati dal codice Java. Ogni file .dex può contenere fino a 65.536 metodi (2 ^ 16).

Le versioni del sistema operativo Android precedenti a Android 5.0 Lollipop (API 21) utilizzano il runtime Dalvik, che supporta solo un file .dex per APK, limitando a 65.536 metodi per APK. A partire da Android 5.0, il sistema operativo Android utilizza ART runtime, che può supportare più di un file .dex per APK, evitando il limite.

Per superare il limite dei 65k metodi nelle versioni Android sotto l'API 21, gli sviluppatori devono utilizzare la libreria di supporto MultiDex. Il MultiDex crea file classes.dex aggiuntivi (classes2.dex, classes3.dex, ...) facendoli riferimento nel file classes.dex. Quando l'app inizia il caricamento, utilizza una classe MultiDexApplication per caricare i file .dex aggiuntivi.

Se la tua app Android punta a una versione minima dell'SDK uguale o superiore all'API 21 (Android 5.0 Lollipop), non è necessario utilizzare la libreria MultiDex, poiché il sistema operativo gestisce in modo nativo i file .dex aggiuntivi. Tuttavia, se per ragioni di compatibilità lo sviluppatore vuole supportare il precedente sistema operativo Android, allora lui / lei dovrebbe usare la libreria MultiDex.


Come usare MultiDex nella tua app Xamarin.Android

Innanzitutto, per attivare MultiDex nella tua app Xamarin.Android, vai al tuo progetto Proprietà -> Opzioni Android -> Packaging -> Attiva Multi-Dex, come nella schermata di stampa qui sotto:

Abilita l'opzione MultiDex

Quindi, devi creare una classe MultiDexApplication nella tua app. Nella root del progetto, creare una nuova classe (in Esplora soluzioni, fare clic con il tasto destro del mouse nel progetto, Aggiungi .. -> Classe o Maiusc + Alt + C). Nel nuovo file di classe, copia il seguente codice, sostituendo lo spazio dei nomi Sample con il nome del tuo spazio dei nomi del progetto 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); }
        }
    }
}

Codice sorgente qui.

Se stai sviluppando in Visual Studio per Windows, c'è anche un bug negli strumenti di build dell'SDK di Android che devi correggere per creare correttamente i file classes.dex quando costruisci il tuo progetto.

Vai alla cartella Android SDK, apri la cartella build-tools e ci saranno cartelle con i numeri dei compilatori di Android SDK, come ad esempio:

C: \ android-sdk \ build-tools \ 23.0.3 \

C: \ android-sdk \ build-tools \ 24.0.1 \

C: \ android-sdk \ build-tools \ 25.0.2 \

All'interno di ciascuna di queste cartelle, c'è un file chiamato mainClassesDex.bat , uno script batch utilizzato per creare i file classes.dex. Apri ogni file mainClassesDex.bat con un editor di testo (Notepad o Notepad ++) e, nel suo script, trova e sostituisce il blocco:

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

Con il blocco:

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

Fonte qui.

Salva ogni mainClassesDex.bat nell'editor di testo dopo le modifiche.

Dopo i passaggi precedenti, dovresti essere in grado di creare con successo la tua app Xamarin.Android con MultiDex.

Abilitazione di ProGuard nel tuo APK Xamarin.Android

ProGuard è uno strumento utilizzato nel processo di costruzione per ottimizzare e offuscare il codice Java del tuo APK e rimuovere anche le classi non utilizzate. L'APK risultante quando si utilizza ProGuard avrà una dimensione inferiore e sarà più difficile da decodificare (decompilazione).

ProGuard può essere utilizzato anche in Xamarin.App Android e ridurrà anche la dimensione del file APK e offuscerà il codice Java. Essere consapevoli, tuttavia, che l'offuscamento di ProGuard si applica solo al codice Java. Per offuscare il codice .NET, lo sviluppatore dovrebbe usare Dotfuscator o strumenti simili.


Come usare ProGuard nella tua app Xamarin.Android

Innanzitutto, per abilitare ProGuard nella tua app Xamarin.Android, vai al tuo progetto Proprietà -> Opzioni Android -> Packaging -> Abilita ProGuard, come nella seguente schermata di stampa:

Abilita ProGuard

Ciò consente a ProGuard di creare la tua app.

Xamarin.Android, per impostazione predefinita, imposta le proprie configurazioni per ProGuard, che possono essere trovate all'interno delle cartelle obj/Debug/proguard o obj/Release/proguard , nei file proguard_project_primary.cfg , proguard_project_references.cfg e proguard_xamarin.cfg . I tre file sono combinati come configurazioni per ProGuard e vengono creati automaticamente da Xamarin durante la creazione.

Se lo sviluppatore desidera personalizzare ulteriormente le opzioni di ProGuard, può creare un file nella radice del progetto denominato proguard.cfg (anche gli altri nomi sono validi, purché l'estensione sia .cfg) e impostando la relativa azione di compilazione su ProguardConfiguration, come nella foto qui sotto:

Impostazione di Build Action su ProguardConfiguration

Nel file, è possibile inserire opzioni personalizzate di ProGuard, come -dontwarn , -dontwarn -keep class e altri .

Importante

A partire da ora (aprile / 2017), l'SDK di Android che viene solitamente scaricato ha una vecchia versione di ProGuard, che può causare errori durante la creazione dell'app utilizzando Java 1.8. Durante la creazione, l'Elenco errori mostra il seguente messaggio:

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]

Fonte qui.

Per risolvere questo problema, è necessario scaricare la versione più recente di ProGuard ( qui ) e copiare il contenuto del file .zip in android-sdk\tools\proguard\ . Questo aggiornerà ProGuard e il processo di costruzione dovrebbe funzionare senza problemi.

Dopodiché, dovresti essere in grado di creare con successo la tua app Xamarin.Android con ProGuard.

Bug "Misteriosi" relativi a ProGuard e Linker

Hai realizzato un'ottima app e l'hai testata in Debug, con buoni risultati. Tutto stava funzionando bene!

Ma poi, hai deciso di preparare la tua app per il rilascio. Hai configurato MultiDex, ProGuard e Linker, e poi ha smesso di funzionare.

Questo tutorial ha lo scopo di aiutarti a scoprire problemi comuni relativi a ProGuard e Linker che possono causare bug misteriosi.


Capire Xamarin.Linker

Xamarin.Linker è uno strumento nel processo di costruzione che rimuove codice e classi non utilizzati dal codice .NET (non dal codice Java) . Nelle Proprietà del tuo progetto -> Opzioni Android -> Linker, ci sarà una casella di selezione Collegamento con le opzioni:

Opzioni del linker

Nessuno : nessun codice rimosso.

Solo assembly Sdk : questa opzione consente a Xamarin.Linker di verificare la presenza di codice non utilizzato solo nelle librerie Xamarin. Questa opzione è sicura.

Sdk e gruppi utente : questa opzione consente a Xamarin.Linker di verificare la presenza di codice inutilizzato nelle librerie Xamarin e nel codice del progetto (inclusi PCL, componenti Xamarin e pacchetti NuGet). Questa opzione non è sempre sicura!

Quando si utilizza l'opzione Sdk e User Assembly, Xamarin.Linker potrebbe pensare che parti del codice non siano utilizzate quando effettivamente sono molto utilizzate! Ciò potrebbe causare il blocco corretto di alcune librerie e causare errori nella tua app.

Per fare in modo che Xamarin.Linker non rimuova il codice, ci sono 3 opzioni:

  1. Impostazione dell'opzione di collegamento su Nessuno o Solo gruppi Sdk;
  2. Salta il collegamento di assiemi;
  3. Utilizzo dell'attributo Preserve.

Esempio per 2. Salta il collegamento degli assiemi:

Nell'esempio seguente, l'uso di Xamarin.Linker ha causato un pacchetto NuGet ( Octokit ) che funziona correttamente per non funzionare più, perché non potrebbe più connettersi a 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 ---

Per far funzionare nuovamente la libreria, è stato necessario aggiungere il nome di riferimento del pacchetto nel campo Ignora collegamenti assiemi, situato in progetto -> Proprietà -> Opzioni Android -> Linker, come nella seguente immagine:

Aggiunta del riferimento al progetto per saltare i collegamenti degli assiemi

Successivamente, la libreria ha iniziato a funzionare senza problemi.

Esempio per 3. Uso dell'attributo Preserve:

Xamarin.Linker percepisce come codice inutilizzato principalmente codice dalle classi di modelli nel nucleo del progetto.

Per mantenere la classe preservata durante il processo di collegamento, è possibile utilizzare l'attributo Preserve.

Innanzitutto, crea nella classe del tuo progetto una classe denominata PreserveAttribute.cs , inserisci il seguente codice e sostituisci lo spazio dei nomi con lo spazio dei nomi del tuo progetto:

PreserveAttribute.cs:

namespace My_App_Core.Models
{
    public sealed class PreserveAttribute : System.Attribute
    {
        public bool AllMembers;
        public bool Conditional;
    }
}

In ogni classe di modello del core del progetto, inserisci l'attributo Preserve come nell'esempio seguente:

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

Successivamente, il processo di collegamento non rimuoverà più il codice conservato.


Capire ProGuard

ProGuard è uno strumento nel processo di costruzione che rimuove codice inutilizzato e classi dal tuo codice Java . Inoltre offusca e ottimizza il codice.

Tuttavia, a volte ProGuard può rimuovere il codice che percepisce come non utilizzato, quando non lo è. Per evitare ciò, lo sviluppatore deve eseguire il debug dell'applicazione (in Monitoraggio dispositivi Android e nel Debug di Visual Studio) e rilevare quale classe è stata rimossa, per poi configurare il file di configurazione di ProGuard per mantenere la classe.

Esempio

Nell'esempio seguente, ProGuard ha rimosso due classi (Android.Support.V7.Widget.FitWindowsLinearLayout e Android.Support.Design.Widget.AppBarLayout) utilizzate nei file di layout AXML, ma che erano state percepite come non utilizzate nel codice. La rimozione ha causato ClassNotFoundException nel codice Java durante il rendering del layout dell'attività:

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 che mostra errore durante la creazione del layout in SetContentView:

Errore visualizzato in LogCat

Per correggere questo errore, è stato necessario aggiungere le seguenti righe al file di configurazione di ProGuard del progetto:

-keep public class android.support.v7.widget.FitWindowsLinearLayout
-keep public class android.support.design.widget.AppBarLayout

Successivamente, non sono stati più visualizzati errori durante la creazione del layout.

Avvertenze ProGuard

A volte ProGuard mostra avvisi nella Lista degli errori dopo aver creato il tuo progetto. Anche se sollevano una domanda se la tua app è OK o no, non tutti i loro avvertimenti indicano problemi, specialmente se la tua app ha successo.

Un esempio è quando si utilizza la libreria Picasso : quando si utilizza ProGuard, è possibile che okio.Okio: can't find referenced class (...) visualizzati avvisi come okio.Okio: can't find referenced class (...) o can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [okhttp.jar:META-INF/MANIFEST.MF]) (...) , ma l'app si costruisce e la libreria funziona senza problemi.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow