Buscar..


Introducción

Este tema muestra información sobre cómo preparar su aplicación Xamarin.Android para el modo de lanzamiento y cómo optimizarla.

Preparando tu APK en el Visual Studio

Terminaste tu aplicación, la probaste en modo de depuración y está funcionando perfectamente. Ahora, desea prepararla para publicar en Google Play Store.

La documentación de Xamarin proporciona buena información aquí:

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


Manifiesto de Android

Primero, en Visual Studio, haga clic con el botón derecho en su proyecto Xamarin.Android en el Explorador de soluciones y seleccione Propiedades. Luego, vaya a la pestaña Manifiesto de Android, para ver esta pantalla:

Configuración de manifiesto de Android

A diferencia de Android Studio o Eclipse, no necesita la configuración del archivo AndroidManifest.xml al escribir; Xamarin y Visual Studio lo hacen por ti. Las actividades, BroadcastReceivers y Services se insertan en el manifiesto de Android declarando atributos específicos en sus clases .

En esta pantalla, las opciones son:

  • Nombre de la aplicación : este es el nombre de la aplicación que estará visible para el usuario.
  • Nombre del paquete : Este es el nombre del paquete. Debe ser único, lo que significa que no debe usar el mismo nombre de paquete de otras aplicaciones en Google Play Store.
  • Icono de la aplicación : este es el icono que será visible para el usuario, equivalente al @ drawable / ic_launcher utilizado en los proyectos de Android Studio o Eclipse.
  • Número de versión : Google Play utiliza el número de versión para el control de versiones. Cuando desee publicar un APK para una versión actualizada de su aplicación, debe agregar 1 a este número para cada nueva actualización.
  • Nombre de la versión : este es el nombre de la versión que se mostrará al usuario.
  • Ubicación de instalación : Esto determina dónde se instalará su APK, en el almacenamiento del dispositivo o en la tarjeta SD.
  • Permisos requeridos : Aquí usted determina qué permisos son necesarios para su aplicación.

Opciones de Android

En la pantalla de abajo, puede configurar las opciones del compilador. El uso de las opciones correctas aquí puede reducir mucho el tamaño de su APK y también evitar errores.

Configuración de opciones de Android

  • Configuración : Activa (Release) .
  • Plataforma : Activa (Cualquier CPU) . Estos son necesarios para construir tu APK para Google Play Store. Si la configuración está configurada para depurar, Google Play no la aceptará.
  • Utilizar Tiempo de ejecución compartido : falso . Si lo establece en verdadero, el APK utilizará Mono Runtime para ejecutarse. Mono Runtime se instala automáticamente cuando se realiza la depuración a través de USB, pero no en la versión Release APK. Si Mono Runtime no está instalado en el dispositivo y esta opción se establece en verdadero en la versión Release APK, la aplicación se bloqueará.
  • Genere un paquete (.apk) por ABI seleccionado : falso . Crea tu APK para tantas plataformas como sea posible, por razones de compatibilidad.
  • Habilite Multi-Dex : verdadero , pero puede configurarlo en falso si su aplicación no es muy compleja (es decir, tiene menos de 65536 métodos, consulte aquí ).
  • Habilitar Proguard : verdadero . Esto habilita la herramienta Proguard que oculta el código Java en su aplicación. Tenga en cuenta que no se aplica al código .NET; Si desea ofuscar el código .NET, debe usar Dotfuscator . Más información sobre Proguard para Xamarin.Android se puede encontrar aquí .
  • Habilitar instrumentación de desarrollador (depuración y creación de perfiles) : falso para Release APK.
  • Enlace : SDK y ensamblajes de usuarios . Esto hará que el Xamarin Linker elimine todas las clases no utilizadas del SDK y su código, reduciendo el tamaño del APK.

Importante

Xamarin.Linker a veces puede eliminar clases que su código no parece utilizar, especialmente si están en el Core del proyecto (biblioteca PCL). Para evitar eso, puede establecer el enlace a "Solo ensamblajes SDK" o usar el atributo Preservar en sus clases, por ejemplo:

PreserveAttribute.cs

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

En una clase

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;
        }
    }
}
  • Arquitecturas soportadas : Seleccionar todas , por razones de compatibilidad.

Después de configurar todo, Reconstruya el proyecto para asegurarse de que se compile correctamente.


Creando el APK para el modo Release

Has terminado de configurar tu proyecto de Android para su lanzamiento. El tutorial a continuación muestra cómo generar el APK en Visual Studio. Un tutorial completo de la documentación de Xamarin se puede encontrar aquí:

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

Para crear el archivo APK, haga clic derecho en el proyecto Xamarin.Android en el Explorador de soluciones y seleccione Archivar ...

Explorador de soluciones -> haga clic derecho en proyecto Xamarin.Android -> Archivar ...

Esto abrirá el administrador de archivos y comenzará a archivar el proyecto, preparándose para crear el archivo APK.

Proyecto de archivo

Cuando termine de archivar el proyecto, haga clic en Distribuir ... para continuar.

Distribuir...

La pantalla de Distribución le presentará dos opciones: Ad-hoc y Google Play. El primero creará un APK y lo guardará en su computadora. El segundo publicará directamente la aplicación en Google Play.

Se recomienda elegir el primero, para que pueda probar el APK en otros dispositivos si lo desea.

Canales de distribucion

En la siguiente pantalla, se necesita un Android Key Store para firmar el APK. Si ya tiene uno, puede usarlo haciendo clic en Importar ...; Si no lo hace, puede crear un nuevo Android Key Store haciendo clic en +.

Identidad de firma

Creando una nueva pantalla de Android Key Store:

Creando nuevo Android Key Store

Para crear el APK, haga clic en Guardar como. Es posible que se le solicite que escriba la contraseña del almacén de claves.

Guardar como

Guardar como -> Localizar carpeta

Introduzca la contraseña de Key Store

Cuando se complete, puede hacer clic en Abrir carpeta en la pantalla Archivos para ver su archivo APK generado.

Carpeta abierta

APK en la carpeta

Habilitando MultiDex en tu Xamarin.Android APK

MultiDex es una biblioteca en el APK de Android que permite que la aplicación tenga más de 65,536 métodos.

Los archivos APK de Android tienen archivos ejecutables Dalvik (.dex) que contienen los códigos de bytes generados compilados a partir de su código Java. Cada archivo .dex puede contener hasta 65,536 métodos (2 ^ 16).

Las versiones de Android OS antes de Android 5.0 Lollipop (API 21) usan el tiempo de ejecución de Dalvik, que solo admite un archivo .dex por APK, limitando a 65,536 métodos por APK. A partir de Android 5.0, el sistema operativo Android usa el tiempo de ejecución ART, que puede admitir más de un archivo .dex por APK, evitando el límite.

Para superar el límite de métodos de 65k en las versiones de Android por debajo de API 21, los desarrolladores deben usar la biblioteca de soporte MultiDex. El MultiDex crea archivos adicionales classes.dex (classes2.dex, classes3.dex, ...) haciendo referencia a ellos en el archivo classes.dex. Cuando la aplicación comienza a cargarse, utiliza una clase MultiDexApplication para cargar los archivos .dex adicionales.

Si su aplicación de Android apunta a una versión mínima de SDK superior o igual a API 21 (Android 5.0 Lollipop), no es necesario usar la biblioteca MultiDex, porque el sistema operativo maneja de forma nativa los archivos .dex adicionales. Sin embargo, si por razones de compatibilidad el desarrollador desea admitir el sistema operativo Android más antiguo, entonces él / ella debe usar la biblioteca MultiDex.


Cómo usar MultiDex en tu aplicación Xamarin.Android

Primero, para habilitar MultiDex en su aplicación Xamarin.Android, vaya a Propiedades del proyecto -> Opciones de Android -> Empaque -> Habilite Multi-Dex, como en la pantalla de impresión a continuación:

Habilitar la opción MultiDex

Luego, debe crear una clase MultiDexApplication en su aplicación. En la raíz del proyecto, cree una nueva clase (en el Explorador de soluciones, haga clic con el botón derecho en el proyecto, Agregar .. -> Clase o Mayús + Alt + C). En el nuevo archivo de clase, copie el siguiente código, reemplazando la muestra del espacio de nombres con el nombre de su espacio de nombres del proyecto 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); }
        }
    }
}

Código fuente aquí.

Si está desarrollando en Visual Studio para Windows, también hay un error en las herramientas de compilación del SDK de Android que debe corregir para crear correctamente los archivos classes.dex al crear su proyecto.

Vaya a su carpeta SDK de Android, abra la carpeta de herramientas de construcción y habrá carpetas con los números de los compiladores del SDK de Android, como:

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

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

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

Dentro de cada una de esas carpetas, hay un archivo llamado mainClassesDex.bat , un script por lotes que se utiliza para crear los archivos classes.dex. Abra cada archivo mainClassesDex.bat con un editor de texto (Notepad o Notepad ++) y, en su script, busque y reemplace el bloque:

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 el bloque:

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

Fuente aquí.

Guarde cada mainClassesDex.bat en el editor de texto después de los cambios.

Después de los pasos anteriores, debería poder construir con éxito su aplicación Xamarin.Android con MultiDex.

Habilitando ProGuard en tu Xamarin.Android APK

ProGuard es una herramienta que se utiliza en el proceso de construcción para optimizar y ofuscar el código Java de tu APK y también para eliminar las clases no utilizadas. El APK resultante cuando se usa ProGuard tendrá un tamaño más pequeño y será más difícil realizar ingeniería inversa (descompilación).

ProGuard se puede usar también en las aplicaciones de Xamarin.Android, y también reducirá el tamaño del archivo APK y ofuscará el código de Java. Sin embargo, tenga en cuenta que la ofuscación de ProGuard solo se aplica al código Java. Para ofuscar el código .NET, el desarrollador debe usar Dotfuscator o herramientas similares.


Cómo usar ProGuard en tu aplicación Xamarin.Android

Primero, para habilitar ProGuard en su aplicación Xamarin.Android, vaya a Propiedades del proyecto -> Opciones de Android -> Empaque -> Habilite ProGuard, como en la pantalla de impresión a continuación:

Habilitar ProGuard

Esto permite ProGuard al construir su aplicación.

Xamarin.Android, por defecto, establece sus propias configuraciones para ProGuard, que se pueden encontrar dentro de las carpetas obj/Debug/proguard u obj/Release/proguard , en los archivos proguard_project_primary.cfg , proguard_project_references.cfg y proguard_xamarin.cfg . Los tres archivos se combinan como configuraciones para ProGuard y Xamarin los crea automáticamente al construirlos.

Si el desarrollador desea personalizar aún más las opciones de ProGuard, él / ella puede crear un archivo en la raíz del proyecto llamada proguard.cfg (otros nombres también son válidos, siempre y cuando la extensión sea .cfg) y configurar su Acción de compilación en ProguardConfiguration, como en la imagen de abajo:

Configuración de la acción de compilación a la configuración de progreso

En el archivo, se pueden insertar opciones personalizadas de ProGuard, como -dontwarn , -keep class y otras .

Importante

A fecha de hoy (abril / 2017), el SDK de Android que generalmente se descarga tiene una versión antigua de ProGuard, que puede causar errores al crear la aplicación con Java 1.8. Al construir, la lista de errores muestra el siguiente mensaje:

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]

Fuente aquí.

Para solucionar este problema, debe descargar la versión más reciente de ProGuard ( aquí ) y copiar el contenido del archivo .zip en android-sdk\tools\proguard\ . Eso actualizará ProGuard y el proceso de construcción debería ejecutarse sin problemas.

Después de eso, debería poder construir con éxito su aplicación Xamarin.Android con ProGuard.

Errores "misteriosos" relacionados con ProGuard y Linker

Hiciste una gran aplicación y la probaste en Debug, con buenos resultados. ¡Todo funcionaba bien!

Pero entonces, decidiste preparar tu aplicación para el lanzamiento. Configuró MultiDex, ProGuard y Linker, y luego, dejó de funcionar.

Este tutorial tiene como objetivo ayudarlo a encontrar problemas comunes relacionados con ProGuard y Linker que pueden causar errores misteriosos.


Entendiendo Xamarin.Linker

Xamarin.Linker es una herramienta en el proceso de construcción que elimina el código y las clases no utilizadas de su código .NET (no el código Java) . En las Propiedades de su proyecto -> Opciones de Android -> Vinculador, habrá un cuadro de selección Vincular con las opciones:

Opciones de enlace

Ninguno : no se elimina ningún código.

Solo ensamblajes Sdk : esta opción hace que Xamarin.Linker compruebe el código no utilizado solo en las bibliotecas de Xamarin. Esta opción es segura.

Conjuntos de usuarios y SDK : esta opción hace que Xamarin.Linker compruebe el código no utilizado en las bibliotecas de Xamarin y en el código del proyecto (incluidos los PCL, los componentes de Xamarin y los paquetes de NuGet). ¡Esta opción no siempre es segura!

Cuando se usa la opción Sdk and User Assemblies, Xamarin.Linker puede pensar que partes del código no se usan cuando en realidad se usan mucho. Esto puede hacer que algunas bibliotecas dejen de funcionar correctamente y causen errores en su aplicación.

Para hacer que el código Xamarin.Linker no elimine, hay 3 opciones:

  1. Estableciendo la opción de Enlace en Ninguno o Solo Ensambles SDK;
  2. Saltar los conjuntos de enlace;
  3. Usando el atributo Preservar.

Ejemplo para 2. Saltar ensamblajes de enlace:

En el ejemplo a continuación, el uso de Xamarin.Linker provocó que un paquete NuGet ( Octokit ) funcionara bien para dejar de funcionar, porque ya no podía conectarse 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 ---

Para hacer que la biblioteca vuelva a funcionar, fue necesario agregar el nombre de referencia del paquete en el campo Omitir conjuntos de enlaces, ubicado en proyecto -> Propiedades -> Opciones de Android -> Enlace, como se muestra en la siguiente imagen:

Agregando referencia de proyecto para saltar ensamblajes de enlace

Después de eso, la biblioteca comenzó a trabajar sin ningún problema.

Ejemplo para 3. Usando el atributo Preservar:

Xamarin.Linker percibe como código no utilizado principalmente código de clases modelo en el núcleo de su proyecto.

Para hacer que la clase se mantenga durante el proceso de vinculación, puede usar el atributo Conservar.

Primero, cree en el núcleo de su proyecto una clase llamada PreserveAttribute.cs , inserte el siguiente código y reemplace el espacio de nombres con el espacio de nombres de su proyecto:

PreserveAttribute.cs:

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

En cada clase de modelo del núcleo de su proyecto, inserte el atributo Preservar como se muestra en el siguiente ejemplo:

País.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;
        }
    }
}

Después de eso, el proceso de vinculación ya no eliminará el código preservado.


Entendiendo ProGuard

ProGuard es una herramienta en el proceso de construcción que elimina el código y las clases no utilizadas de su código Java . También confunde y optimiza el código.

Sin embargo, ProGuard a veces puede eliminar el código que percibe como no utilizado, cuando no lo está. Para evitar eso, el desarrollador debe depurar la aplicación (en Android Device Monitor y en Visual Studio Debug) y detectar qué clase se eliminó, para luego configurar el archivo de configuración ProGuard para mantener la clase.

Ejemplo

En el siguiente ejemplo, ProGuard eliminó dos clases (Android.Support.V7.Widget.FitWindowsLinearLayout y Android.Support.Design.Widget.AppBarLayout) utilizadas en los archivos de diseño AXML, pero que se percibieron como no utilizadas en el código. La eliminación causó la excepción ClassNotFoundException en el código Java al representar el diseño de la actividad:

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 muestra un error al crear el diseño en SetContentView:

Error que se muestra en LogCat

Para corregir este error, fue necesario agregar las siguientes líneas al archivo de configuración ProGuard del proyecto:

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

Después de eso, no se mostraron más errores al crear el diseño.

Advertencias ProGuard

ProGuard a veces muestra advertencias en la Lista de errores después de construir su proyecto. Aunque plantean la pregunta de si su aplicación está bien o no, no todas sus advertencias indican problemas, especialmente si su aplicación se construye con éxito.

Un ejemplo de esto es cuando se usa la biblioteca Picasso : cuando se usa ProGuard, esto puede mostrar advertencias como 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]) (...) , pero la aplicación se compila y la biblioteca funciona sin problemas.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow