Поиск…


Вступление

В этом разделе представлена ​​информация о том, как подготовить приложение Xamarin.Android для режима выпуска и как его оптимизировать.

Подготовка APK в Visual Studio

Вы закончили свое приложение, протестировали его в режиме отладки и отлично работали. Теперь вы хотите подготовить его для публикации в Google Play Store.

Документация Xamarin обеспечивает хорошую информацию здесь:

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


Android Manifest

Во-первых, в Visual Studio щелкните правой кнопкой мыши проект Xamarin.Android в обозревателе решений и выберите «Свойства». Затем перейдите на вкладку манифеста Android, чтобы увидеть этот экран:

Конфигурация манифеста Android

В отличие от Android Studio или Eclipse, вам не нужно установить файл AndroidManifest.xml, написав; Xamarin и Visual Studio делают это за вас. Мероприятия, BroadcastReceivers и Services вставляются в Android Manifest путем объявления определенных атрибутов в своих классах .

На этом экране доступны следующие опции:

  • Имя приложения : это имя приложения, которое будет отображаться для пользователя.
  • Имя пакета : это имя пакета. Он должен быть уникальным, что означает, что он не должен использовать одно и то же имя пакета других приложений в Google Play Store.
  • Значок приложения : это значок, который будет отображаться для пользователя, что эквивалентно @ drawable / ic_launcher, используемому в проектах Android Studio или Eclipse.
  • Номер версии : номер версии используется Google Play для контроля версий. Если вы хотите опубликовать APK для обновленной версии вашего приложения, вы должны добавить 1 к этому номеру для каждого нового обновления.
  • Название версии : это имя версии, которое будет отображаться для пользователя.
  • Место установки : определяет, где будет установлен ваш APK, в хранилище устройств или на SD-карте.
  • Необходимые разрешения : здесь вы определяете, какие разрешения необходимы для вашего приложения.

Настройки Android

На приведенном ниже экране вы можете настроить параметры компилятора. Использование правильных параметров здесь может значительно уменьшить ваш размер APK, а также предотвратить ошибки.

Конфигурация настроек Android

  • Конфигурация : Активный (Release) .
  • Платформа : активная (любой процессор) . Это необходимо для создания APK для магазина Google Play. Если для параметра «Конфигурация» установлено значение «Отладка», он не будет принят в Google Play.
  • Использовать общий Runtime : false . Если вы установите значение true, APK будет использовать Mono Runtime для выполнения. Mono Runtime устанавливается автоматически при отладке через USB, но не в Release APK. Если Mono Runtime не установлено в устройстве, и этот параметр установлен в true в Release APK, приложение выйдет из строя.
  • Создайте один пакет (.apk) для выбранного ABI : false . Создайте APK как можно больше платформ по соображениям совместимости.
  • Включить Multi-Dex : true , но вы можете установить его в false, если ваше приложение не очень сложно (то есть имеет менее 65536 методов, см. Здесь ).
  • Включить Proguard : true . Это позволяет инструменту Proguard обмануть Java-код в вашем приложении. Обратите внимание, что это не относится к .NET-коду; если вы хотите обфускать .NET-код, вы должны использовать Dotfuscator . Более подробную информацию о Proguard для Xamarin.Android можно найти здесь .
  • Включить инструментарий разработчика (отладка и профилирование) : false для Release APK.
  • Связь : SDK и пользовательские сборки . Это заставит Xamarin Linker удалить все неиспользуемые классы из SDK и вашего кода, уменьшив размер APK.

Важный

Xamarin.Linker иногда может удалять классы, которые, похоже, не используются вашим кодом, особенно если они находятся в ядре проекта (библиотека PCL). Чтобы этого избежать, вы можете установить привязку только к «Sdk Assemblies Only» или использовать атрибут Preserve в своих классах, например:

PreserveAttribute.cs

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

В классе:

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;
        }
    }
}
  • Поддерживаемые архитектуры : выберите все по соображениям совместимости.

После настройки всего, перестройте проект, чтобы убедиться, что он успешно работает.


Создание режима APK для выпуска

Вы закончили настройку своего Android-проекта для выпуска. В следующем уроке показано, как сгенерировать APK в Visual Studio. Полный учебник по документации Xamarin можно найти здесь:

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

Чтобы создать файл APK, щелкните правой кнопкой мыши проект Xamarin.Android в обозревателе решений и выберите Archive ...

Solution Explorer -> щелкните правой кнопкой мыши проект Xamarin.Android -> Архив ...

Это откроет диспетчер архива и начнет архивирование проекта, готовясь к созданию файла APK.

Проект архивирования

Когда он завершит архивирование проекта, нажмите «Распространять» ... чтобы продолжить.

Распределить ...

На экране «Распределить» будут представлены два варианта: «Ad-hoc» и «Google Play». Первый создаст APK и сохранит его на вашем компьютере. Второй будет публиковать приложение прямо в Google Play.

Рекомендуется выбрать первый, поэтому вы можете протестировать APK на других устройствах, если хотите.

Каналы распределения

На следующем экране для подписывания APK необходим магазин Android Key. Если у вас уже есть, вы можете использовать его, нажав «Импортировать ...»; если вы этого не сделаете, вы можете создать новый Android Key Store, нажав +.

Идентификация подписи

Создание нового экрана Android Key Store:

Создание нового хранилища ключей Android

Чтобы создать APK, нажмите «Сохранить как». Возможно, вам будет предложено ввести пароль хранилища ключей.

Сохранить как

Сохранить как -> Найти папку

Введите пароль к хранилищу ключей

По завершении нажмите «Открыть папку» на экране «Архивы», чтобы увидеть сгенерированный файл APK.

Открыть папку

APK в папке

Включение MultiDex в вашем Xamarin.Android APK

MultiDex - это библиотека в Android APK, которая позволяет приложению иметь более 65 536 методов.

В Android APK есть исполняемые файлы Dalvik (.dex), которые содержат сгенерированные байт-коды, скомпилированные из вашего Java-кода. Каждый файл .dex может содержать до 65 536 методов (2 ^ 16).

В версиях ОС Android до Android 5.0 Lollipop (API 21) используется среда исполнения Dalvik, которая поддерживает только один файл .dex на APK, ограничивая 65 536 методов на APK. Начиная с Android 5.0, ОС Android использует время выполнения ART, которое может поддерживать более одного файла .dex на APK, избегая ограничений.

Чтобы превзойти предел 65k-методов в версиях Android ниже API 21, разработчики должны использовать библиотеку поддержки MultiDex. MultiDex создает дополнительные файлы classes.dex (classes2.dex, classes3.dex, ...), ссылаясь на них в файле classes.dex. Когда приложение начинает загрузку, он использует класс MultiDexApplication для загрузки дополнительных файлов .dex.

Если ваше приложение для Android нацелено на минимальную версию SDK выше или равную API 21 (Android 5.0 Lollipop), нет необходимости использовать библиотеку MultiDex, потому что ОС обрабатывает изначально дополнительные файлы .dex. Однако, если по соображениям совместимости разработчик хочет поддерживать устаревшую ОС Android, он должен использовать библиотеку MultiDex.


Как использовать MultiDex в приложении Xamarin.Android

Во-первых, чтобы включить MultiDex в приложении Xamarin.Android, перейдите в свой проект «Свойства» -> «Настройки Android» -> «Упаковка» -> «Включить многоэкранный режим», как на экране печати ниже:

Включить опцию MultiDex

Затем вы должны создать класс MultiDexApplication в своем приложении. В корне проекта создайте новый класс (в обозревателе решений щелкните правой кнопкой мыши в проекте Add .. -> Class или Shift + Alt + C). В новом файле класса скопируйте следующий код, заменив пространство имен Sample на имя пространства имен проектов 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); }
        }
    }
}

Источник кода здесь.

Если вы разрабатываете Visual Studio для Windows, также есть ошибка в инструментах сборки Android SDK, которые необходимо исправить, чтобы правильно создавать файлы classes.dex при создании проекта.

Перейдите в папку Android SDK, откройте папку с инструментами создания и установите папки с номерами компиляторов Android SDK, например:

C: \ Android-SDK \ сборки-инструменты \ 23.0.3 \

C: \ Android-SDK \ сборки-инструменты \ 24.0.1 \

C: \ Android-SDK \ сборки-инструменты \ 25.0.2 \

Внутри каждой из этих папок есть файл mainClassesDex.bat , пакетный скрипт, используемый для создания файлов classes.dex. Откройте каждый файл mainClassesDex.bat с помощью текстового редактора (Notepad или Notepad ++) и в его скрипте найдите и замените блок:

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

С блоком:

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

Источник здесь.

Сохраните каждый mainClassesDex.bat в текстовом редакторе после изменений.

После описанных выше шагов вы сможете успешно создать приложение Xamarin.Android с помощью MultiDex.

Включение ProGuard в ваш Xamarin.Android APK

ProGuard - это инструмент, используемый в процессе построения для оптимизации и обфускации кода Java вашего APK, а также удаления неиспользуемых классов. Полученный APK при использовании ProGuard будет иметь меньший размер и будет сложнее перепроектировать (декомпиляция).

ProGuard можно использовать также в приложениях Xamarin.Android, а также уменьшит размер файла APK и запутывает Java-код. Однако имейте в виду, что обфускация ProGuard применяется только к Java-коду. Чтобы запутать .NET-код, разработчику следует использовать Dotfuscator или аналогичные инструменты.


Как использовать ProGuard в приложении Xamarin.Android

Во-первых, чтобы включить ProGuard в вашем приложении Xamarin.Android, перейдите в свой проект Properties -> Android Options -> Packaging -> Включите ProGuard, как на экране печати ниже:

Включить ProGuard

Это позволяет ProGuard при создании приложения.

Xamarin.Android по умолчанию устанавливает свои собственные конфигурации для ProGuard, которые можно найти внутри папок obj/Debug/proguard или obj/Release/proguard в файлах proguard_project_primary.cfg , proguard_project_references.cfg и proguard_xamarin.cfg . Эти три файла объединены в качестве конфигураций для ProGuard, и они автоматически создаются Xamarin при построении.

Если разработчик хочет дополнительно настроить параметры ProGuard, он может создать файл в корне проекта с именем proguard.cfg (другие имена также действительны, если расширение является .cfg) и устанавливают его действие Build на ProguardConfiguration, как на рисунке ниже:

Настройка действия сборки для ProguardConfiguration

В файле могут быть вставлены пользовательские параметры ProGuard, такие как -dontwarn , -keep class и другие .

Важный

Как и сейчас (апрель / 2017), Android SDK, который обычно загружается, имеет старую версию ProGuard, которая может вызвать ошибки при создании приложения с использованием Java 1.8. При построении в списке ошибок отображается следующее сообщение:

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]

Источник здесь.

Чтобы устранить эту проблему, вы должны загрузить последнюю версию ProGuard ( здесь ) и скопировать содержимое .zip-файла в android-sdk\tools\proguard\ . Это позволит обновить ProGuard, и процесс сборки должен работать без проблем.

После этого вы сможете успешно создать приложение Xamarin.Android с помощью ProGuard.

«Таинственные» ошибки, связанные с ProGuard и Linker

Вы сделали отличное приложение и протестировали его в Debug с хорошими результатами. Все работает нормально!

Но тогда вы решили подготовить свое приложение для выпуска. Вы создали MultiDex, ProGuard и Linker, а затем перестали работать.

Этот учебник призван помочь вам найти общие проблемы, связанные с ProGuard и Linker, которые могут вызвать загадочные ошибки.


Понимание Xamarin.Linker

Xamarin.Linker - это инструмент в процессе построения, который удаляет неиспользуемый код и классы из вашего кода .NET (а не кода Java) . В свойствах вашего проекта -> Настройки Android -> Линкера появится окно выбора. Ссылка на параметры:

Параметры компоновщика

Нет : код не удаляется.

Sdk Assemblies Only : этот параметр позволяет Xamarin.Linker проверять неиспользуемый код только в библиотеках Xamarin. Этот параметр безопасен.

Sdk и User Assemblies : этот параметр позволяет Xamarin.Linker проверять неиспользуемый код в библиотеках Xamarin и в коде проекта (включая PCL, компоненты Xamarin и пакеты NuGet). Этот вариант не всегда безопасен!

При использовании опций Sdk и User Assemblies Xamarin.Linker может думать, что части кода не используются, когда на самом деле они очень используются! Это может привести к тому, что некоторые библиотеки перестанут работать должным образом и вызывают ошибки в вашем приложении.

Чтобы Xamarin.Linker не удалял код, есть 3 варианта:

  1. Установка параметра «Связывание» на «Нет» или «Только Sdk»;
  2. Пропустить соединительные сборки;
  3. Использование атрибута Preserve.

Пример для 2. Пропустить соединительные сборки:

В приведенном ниже примере использование Xamarin.Linker вызвало пакет NuGet ( Octokit ), который отлично работает, чтобы перестать работать, потому что он больше не может подключаться к Интернету:

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

Чтобы библиотека снова начала работать, необходимо было добавить имя ссылки пакета в поле «Связывание сборок», расположенное в проекте -> «Свойства» -> «Настройки Android» -> «Линкер», как показано на рисунке ниже:

Добавление ссылки на проект для пропусков связующих сборок

После этого библиотека начала работать без каких-либо проблем.

Пример для 3. Использование атрибута Preserve:

Xamarin.Linker воспринимает как неиспользуемый код, в основном, код классов моделей в ядре вашего проекта.

Чтобы класс сохранялся в процессе связывания, вы можете использовать атрибут Preserve.

Во-первых, создайте в своем ядре проекта класс PreserveAttribute.cs , вставьте следующий код и замените пространство имен пространством имен вашего проекта:

PreserveAttribute.cs:

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

В каждом модельном классе ядра вашего проекта вставьте атрибут Preserve, как в приведенном ниже примере:

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

После этого процесс связывания больше не удалит сохраненный код.


Понимание ProGuard

ProGuard - это инструмент в процессе построения, который удаляет неиспользуемый код и классы из вашего Java-кода . Он также запутывает и оптимизирует код.

Однако ProGuard иногда может удалить код, который он воспринимает как неиспользуемый, когда это не так. Чтобы этого избежать, разработчик должен отладить приложение (в Android Device Monitor и Visual Studio Debug) и определить, какой класс был удален, а затем настроить конфигурационный файл ProGuard для сохранения класса.

пример

В приведенном ниже примере ProGuard удалил два класса (Android.Support.V7.Widget.FitWindowsLinearLayout и Android.Support.Design.Widget.AppBarLayout), используемые в файлах макетов AXML, но которые были восприняты как неиспользуемые в коде. При удалении вызвало ClassNotFoundException в коде Java при отображении макета активности:

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 показывает ошибку при создании макета в SetContentView:

Ошибка в LogCat

Чтобы исправить эту ошибку, необходимо было добавить следующие строки в файл конфигурации ProGuard проекта:

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

После этого при создании макета больше не было ошибок.

Предупреждения ProGuard

ProGuard иногда показывает предупреждения в списке ошибок после создания вашего проекта. Хотя они поднимают вопрос о том, хорошо ли ваше приложение или нет, не все их предупреждения указывают на проблемы, особенно если ваше приложение успешно создает.

Одним из примеров этого является использование библиотеки Picasso : при использовании ProGuard это может показывать предупреждения, такие как okio.Okio: can't find referenced class (...) или can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [okhttp.jar:META-INF/MANIFEST.MF]) (...) , но приложение работает, и библиотека работает без проблем.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow