Рубріки: Mobile appТеория

Просто и понятно о Xamarin: как разработать кроссплатформенное мобильное приложение. Пошаговая инструкция

Семен Гринштейн

Xamarin — это опенсорс-фреймворк для разработки кроссплатформенных мобильных приложений с использованием библиотек .NET.

Чаще всего в качестве среды разработки выбирают Microsoft Visual Studio, а в качестве языка — C#. Такое сочетание позволяет компилировать, собирать и запускать один и тот же код (общий код) для:

  • iOS (.ipa —  iOS App Store Package);
  • Android (.apk — Android Package Kit);
  • Windows (UWP — Universal Windows Platform).

В большинстве случаев созданные таким образом приложения будут работать и выглядеть на каждой из платформ как нативные (родные). 

Xamarin — это не только инструмент, это некий подход к процессу разработки. Он позволяет писать большую часть общего кода на одном языке и использовать его в других проектах. 

Преимущества Xamarin

  1. Выше я уже упомянул про общий код. Так вот, доля этого кроссплатформенного кода может достигать 80% или даже 90%. Понятно, что чудес не бывает и все зависит от специфики вашего приложения. Если, например, вы пишете хардкорный код для обработки аудио/видео в реальном времени, он будет платформо-зависимым, и доля общего кода снизится. Но если вы ограничиваетесь написанием бизнес-логики — тогда ситуация обратная.
  2. Xamarin позволяет напрямую достучаться до нативного API каждой из трех упомянутых платформ. То есть на нем можно писать и платформо-зависимый код.
  3. Так как это опенсорс-фреймворк, свой вклад в его разработку может вносить сообщество (что оно и делает). Благодаря энтузиастам появляются сторонние компоненты, а также расширяется список платформ и библиотек, которые могут поддерживать Xamarin-приложения. Так список пополнился операционными системами MacOS и Tizen, а также UI-библиотеками для WPF и GTK#.
  4. Одно из спорных преимуществ Xamarin — это тесная связь с C# и .NET. Поклонники этого языка и экосистемы .NET в целом будут считать это преимуществом, а скептики найдут, к чему придраться.

Лицензия и другие условия использования

Есть две новости — хорошая и плохая. Начнем с плохой.

Стоит предупредить, что сейчас, без машины с MacOS компилировать, собирать и отлаживать Xamarin-приложения под iOS (официально) нельзя. Возможно, ограничение получится обойти, но насколько это легально?

Теперь хорошая новость: Xamarin распространяется бесплатно — в том числе и для коммерческого использования. 

Документация и сторонние компоненты

У Xamarin довольно обширная документация. Она охватывает общие вопросы разработки кроссплатформенных приложений. Много внимания уделено библиотеке Xamarin.Forms. Кроме того, существуют отдельные большие блоки документации по специфическим вопросам разработки для Android и iOS.

На английском языке:

На русском: 

Экосистема дожила до того счастливого момента, когда для Xamarin начали пилить сторонние компоненты. Среди популярных переиспользуемых компонентов и шаблонов пользовательского интерфейса, можно выделить:

Поддержка системных требований (для Windows и для Mac)

Платформа macOS

(Visual Studio для Mac)

Windows

(Visual Studio)

Xamarin.iOS Да Да (с компьютером Mac)
Xamarin.Android Да Да
Xamarin.Forms iOS и Android Android, классические приложения Windows и UWP (iOS с компьютером Mac)
Xamarin.Mac Да Только открыть проект и компилировать

Xamarin.Mac 4.8 будет работать на macOS версии 10.9 (Mavericks) и выше.

Xamarin для Visual Studio будет работать на Visual Studio 2019 и Visual Studio 2017 (Community, Professional и Enterprise). Чтобы использовать новейшие версии SDK для Android и iOS нужна обновленная версия Visual Studio. Если хотите разрабатывать на Xamarin под UWP, вам понадобится Windows 10.

Я выбрал Windows с Visual Studio 2019 Community. Далее все примеры будут относиться именно к этой конфигурации. А собирать и запускать Xamarin-приложение я буду под Android OS.

Установка Xamarin в Visual Studio

1. Для Visual Studio 2019 и 2017 процесс очень похож. Это касается и Community (бесплатной версии), и Professional, и Enterprise. Возможно, какая-то из этих версий VS у вас уже установлена (она не должна быть старше 2017, но это не эйджизм). Если нет — скачать можно здесь.

2. В обоих случаях нужно начать с запуска инсталлятора (Visual Studio Installer). Его можно найти на своем компьютере, например, через меню Пуск. Если вы только скачали VS без установки, просто запустите скачанный файл.

3. Выберите рабочую нагрузку (вкладка Workloads) под названием Mobile development with .NET.

Вкладка Workloads -> Mobile development with .NET

4. Больше ничего не надо выбирать. Оставьте в покое настройку Install while downloading в списке вариантов установки и нажмите Install или Change (если VS уже была установлена).

Нажмите Install

5. Дождитесь окончания установки. 

6. Проверьте, что выбранные вами компоненты установлены. Для этого запустите Visual Studio, в главном меню выберите пункт Help и далее — About Microsoft Visual Studio:

Проверьте, что компоненты установлены

Все прошло успешно!

Как работает Xamarin?

Xamarin

Xamarin построен на базе Mono. Это опенсорс-реализация спецификации CLI (Common Language Infrastructure) с виртуальной машиной и компилятором C#.

В рамках разработки Mono также реализовано множество библиотек, совместимых с .NET Framework, а также расширяющих его функциональность. 

Xamarin включает две ключевых библиотеки для разработки приложений для мобильных платформ — Xamarin.Android и Xamarin.iOS (их названия говорят сами за себя).

Дело в том, что код Xamarin-приложения (напоминаю: это код на C#) не может напрямую обращаться к нативному API операционной системы Android или iOS. Проблему решают эти библиотеки, которые преобразуют код в соответствующие нативные вызовы. 

Xamarin.Android использует пространства имен Android* и Java* из виртуальной среды выполнения Android Runtime (ART). Обращаться к ним позволяет специальный набор оберток Managed Callable Wrappers (MCW), который и выполняет необходимые преобразования с C#-кодом. Обратные преобразования выполняются через другой набор классов — Android Callable Wrappers (ACW). 

Xamarin.iOS занимается статической (AOT — Ahead-Of-Time) компиляцией C#-кода в нативный ARM-код. В отличие от Just-In-Time (JIT) компиляции Xamarin.Android, происходяще в процессе работы приложения, исходный код заранее преобразуется в исполняемый (в данном случае — в ассемблерный код для мобильного процессора с архитектурой ARM). Параллельно работает среда выполнения Objective C. С помощью промежуточного слоя под названием Bindings Xamarin.iOS обеспечивает преобразование вызовов C# API в вызовы Objective C и обратно (выполняет те же задачи, что и MCW / ACW в Xamarin.Android).  

На более высоком уровне абстракции находятся библиотеки Xamarin.Essentials и Xamarin.Forms, которые предоставляют кроссплатформенный API. Например, Xamarin.Forms позволяет создать единый кроссплатформенный UI (допустим, с помощью XAML), повесить на него обработчики и реализовать эту обработку (с помощью C#). Этот код можно запустить на всех трех платформах, о которых мы тут говорим. 

Xamarin.Essentials — это библиотека, предоставляющая кросс-платформенный API (обертку) для единообразного использования нативных функций (геолокация, блокировка экрана или показания датчиков устройства).

Xamarin.Forms — это библиотека для разработки UI с помощью комбинации XAML и C#. Созданные таким образом абстрактные элементы управления могут быть преобразованы в нативные контролы соответствующей платформы. В данном случае это преобразование называется рендерингом.

Кроме того, Xamarin.Forms может похвастаться такими фичами, как Databinding, Gestures, Effects и Styling

Структура проекта и разработка UI

Выше мы уже решили, что в этой статье вся практика будет опираться на конфигурация Windows с Visual Studio 2019 Community. Поэтому продолжаем с ней же.

Здесь мы рассмотрим шаблон проекта Mobile App (Xamarin Forms), потому что Xamarin в первую очередь ассоциируется с кроссплатформенной разработкой. 

Mobile App (Xamarin Forms)

Будем разбираться на практике. Для начала создадим свой проект (а точнее — Solution или «решение»):

Создаем проект

Уже понятно, какой тип проекта нужно выбрать:

Выбираем тип проекта

Назовем его HelloHighloadToday:

Называем проект

Далее выбираем набор платформ, для которых будем создавать Solution. Я не стал устанавливать инструменты разработки UWP-приложений, поэтому этот пункт у меня не активен.

А работая на MacOS в Visual Studio для Mac, вы обнаружите, что этого пункта просто не будет. Вот такое платформенное ограничение: видимо, UWP там не в почете. 

Выбираем пункт Blank (пустой), чтобы в сгенерированном коде не было ничего лишнего

Я также выбрал пункт Blank (пустой), чтобы в сгенерированном коде не было ничего лишнего. Так проще с ним разбираться.

Все, Solution создан! Посмотрим на его структуру:

Структура Solution

Так как я выбрал две платформы, то дополнительно к основному проекту (HelloHighloadToday) VS создала еще два (платформо-зависимых):

  • HelloHighloadToday.Android;
  • HelloHighloadToday.iOS.

По умолчанию жирным выделен проект HelloHighloadToday.Android, но важно понимать, что основным проектом остается HelloHighloadToday. Без этого проекта невозможно заставить один и тот же код работать на остальных двух. 

Hello, HighloadToday: как работает код

Теперь разберемся, как работает сгенерированный код. 

Посмотрим на структуру основного проекта — HelloHighloadToday. Здесь нас интересуют пять файлов: App.xaml, App.xaml.cs, MainPage.xaml, MainPage.xaml.cs и AssemblyInfo.cs.

В структуре HelloHighloadToday выбираем нужные файлы

AssemblyInfo.cs хранит настройки компиляции для Xamarin-приложения. Об этом файле — пока все.

Файлы App.xaml и App.xaml.cs

Есть более интересные файлы App.xaml и App.xaml.cs. Они отвечают за запуск приложения (для любителей английского: App — Application). Файл App.xaml — первая стартовая точка приложения. 

Файл App.xaml

По его расширению можно догадаться, что код внутри написан на XAML (язык разметки на основе XML). Этот декларативный язык обычно используется для описания пользовательского интерфейса или ресурсов. В этом файле обычно описываются глобальные ресурсы (например, стили), которые можно использовать внутри всего приложения. Нам тут пока описывать нечего, но в качестве примера можно посмотреть на такое:

<Application.Resources>

        <Style TargetType="Grid">

            <Setter Property="Background" Value="Red" />

        </Style>

    </Application.Resources>

С описанием UI мы встретимся чуть позже.

App.xaml работает в паре с файлом App.xaml.cs. Это вторая стартовая точка.

App.xaml.cs

В этом файле создается пользовательский класс App — наследник класса Application (Приложение). Полное название этого класса определяется в файле App.xaml. В нашем случае это:

x:Class = "HelloHighloadToday.App"

В конструкторе этого класса есть важный вызов метода InitializeComponent(), который отвечает за начальную инициализацию объекта нашего класса App, производного от класса Application. Там же, в конструкторе, устанавливается наша главная страница приложения (MainPage, о ней пойдет речь далее). 

Кроме того, в этом же классе Visual Studio заботливо сгенерировала пустые обработчики основных событий для типичного мобильного приложения — OnStart(), onSleep() и onResume(). Писать внутри свой код или не писать — целиком и полностью решаем мы с вами (то есть разработчики, которые используют Xamarin). Тут же можно подписаться и на другие события.

Файлы MainPage.xaml и MainPage.xaml.cs

Эта пара файлов состоит примерно в таких же отношениях, как App.xaml и App.xaml.cs: 

x:Class = "HelloHighloadToday.MainPage"

Только в MainPage.xaml описан пользовательский интерфейс. По аналогии с HTML, здесь элементы UI представлены в виде тегов (с своими индивидуальными атрибутами) и вложены в некий контейнер StackLayout (хотя возможны разные уровни вложенности и варианты контейнеров), который, в свою очередь, вложен в страницу нашего приложения ContentPage:

MainPage.xaml

Код внутри обоих файлов был автоматически сгенерирован во время создания проекта:

MainPage.xaml.cs

Видно, что код в этом файле еще проще, чем в App.xaml.cs. Здесь важно, что класс MainPage является наследником класса главной страницы ContentPage.

Выглядит сгенерированное приложение вот так:

Cгенерированное приложение

Разработка UI

Для разработки визуального интерфейса кроссплатформенных приложений используют Xamarin.Forms. UI мобильных Xamarin-приложений состоит из одной или нескольких страниц.

Наш проект пока содержит только одну страницу — MainPage. Она была добавлена автоматически при создании проекта. Мы можем и сами добавлять новые страницы. 

Добавление страниц на базе готовых шаблонов

Добавление страниц на базе шаблонов

Шаблоны подразделяются по типам страниц. Но для нас сейчас важнее заметить, что некоторые шаблоны не позволяют создать для страницы XAML-файл.

Например, при создании страницы на базе шаблона ContentPage будут созданы два файла — Page1.xaml и Page1.xaml.cs. В случае с шаблоном ContentPage (C#) будет создан только файл Page1.cs.

Из этого вытекают два подхода к разработке UI.

UI на C# 

Код, сгенерированный при создании страницы на базе шаблона ContentPage

Это код, сгенерированный при создании страницы на базе шаблона ContentPage (C#).

UI с XAML

XAML-код, сгенерированный при создании страницы на базе шаблона ContentPage

Это XAML-код, сгенерированный при создании страницы на базе шаблона ContentPage.

Сs-код, сгенерированный при создании страницы на базе шаблона ContentPage

Это cs-код, сгенерированный при создании страницы на базе шаблона ContentPage.

Здесь файл .xaml с описанием UI отделен от .cs-файла. Тогда имеет смысл договориться, что во втором файле будем писать только логику взаимодействия с визуальным интерфейсом. Такой подход считается более рациональным: c декларативным стилем XAML структура UI выглядит более наглядно, код проще понимать и поддерживать, благодаря разделению над каждым из двух файлов может работать отдельный специалист. И это явно реверанс в сторону любителей HTML.

В обоих случаях нужно вносить изменения в код ручками, потому что у Xamarin.Forms нет Дизайнера (Конструктора форм). Но если создать Solution вроде Android App (Xamarin), то там Дизайнер присутствует. Только это уже тема для другой статьи.

Хорошо, так давайте же внесем эти изменения!

Делаем свой UI с XAML и обработкой событий

Усложним сгенерированный пример. Сформулируем ТЗ на наше Xamarin-приложение HelloHighloadToday:

1. Показать приветственный экран. Он должен содержать:

  • заголовок («Знакомься с Xamarin!»);
  • развернутый призыв к действию в следующем блоке текста;
  • кнопку с надписью https://highload.today/category/teoriya;
  • кнопку с надписью CLEAR;
  • невидимый WebView.

2. По нажатию кнопки с надписью https://highload.today/category/teoriya обеспечить показ страницы по указанной ссылке: WebView должен стать видимым.

3. По нажатию кнопки с надписью CLEAR обеспечить возврат приложения к состоянию 1 (то есть спрятать WebView).

Я не буду рассказывать про сами элементы UI в расчете на то, что вы с ними знакомы или быстро сможете познакомиться. 

Перепишем сначала файл MainPage.xaml. Я, не сильно раздумывая, выбрал терпимый вариант размещения элементов визуального интерфейса. Вы можете сделать по-своему:

<?xml version="1.0" encoding="utf-8" ?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             x:Class="HelloHighloadToday.MainPage">

   <StackLayout>

        <StackLayout>

            <Frame BackgroundColor="#2196F3" CornerRadius="0">

                <Label Text="Знакомься c Xamarin!" HorizontalTextAlignment="Center" TextColor="White" FontSize="26"/>

            </Frame>

            <Label Text="Пиши свой код! Начни с проекта HelloHighloadToday. Читай эту и другие статьи в разделе «Теория»" 

                   FontSize="16" Padding="30,14,30,0"/>

            <StackLayout Padding="30,14,30,14">

                <Button x:Name="LoadWebPageButton" Text="https://highload.today/category/teoriya/" TextColor="White" 

                        BackgroundColor="#2196F3" Clicked="OnLoadWebPageButtonClicked"></Button>

                <Button x:Name="HideWebPageButton" Text="Clear" TextColor="White" BackgroundColor="#2196F3" Clicked="OnHideButtonClicked"></Button>

            </StackLayout>

        </StackLayout>

        <WebView x:Name="WebView1" VerticalOptions="FillAndExpand" />

    </StackLayout>

</ContentPage>

Теперь обработаем нажатия на кнопки:

Обрабатываем нажатия на кнопки

Вот такая нехитрая логика.

Запуск под Android

Давайте проверим, действительно ли наш код из основного проекта будет работать на Android OS без танцев с бубном. Проверять будем на настоящем смартфоне с установленной операционной системой 10-й версии. Система не самая новая, поэтому будет еще интереснее посмотреть, взлетит ли на ней проект.

Проверяем проект на смартфоне

На приведенном выше скриншоте видно, что наш основной (кроссплатформенный) проект подключен как reference, а точнее — библиотека динамической компоновки (файл HelloHighloadToday.dll). Это один из ключевых нюансов реализации кроссплатформенности. DLL-библиотека активно используется для работы Xamarin-приложения на Android OS. 

А сейчас просто посмотрим на код файла MainActivity.cs (это главный и единственный экран) из нашего проекта HelloHighloadToday.Android. Он также написан на C# — ни слова про Java, как видите. 

Отмечу, что этот код полностью сгенерирован Visual Studio. В нем подключаются и используются все необходимые пространства имен и библиотеки для работы с Android (в том числе — Xamarin.Forms и Xamarin.Essentials, описанные выше). Кроме того, MainActivity.cs использует настройки и ресурсы основного проекта (HelloHighloadToday). Ну и, конечно же, в методе OnCreate(Bundle savedInstanceState) выполняется инициализация и старт приложения.

using System;

using Android.App;

using Android.Content.PM;

using Android.Runtime;

using Android.OS;

Код, сгенерированный Visual Studio

В этом коде я не менял ничего.

Отлаживать приложение можно и в эмуляторе. Но для этого ваша машина должна поддерживать виртуализацию и работать достаточно шустро.

Посмотреть список виртуальных устройств или добавить новое можно через Tools -> Android -> Android Device Manager.

Если вы, так же, как я, запускаете приложения на реальном устройстве, то нужно выполнить несколько простых манипуляций с вашим смартфоном (или что там у вас c Android OS):

1. Подключить устройство к компьютеру по USB.

2. Зайти в Настройки -> О телефоне и щелкнуть по Номеру сборки 7 раз.

Необходимо кликнуть по Номеру сборки 7 раз

3. Зайти в Настройки -> Система и обновления и выбрать пункт Для разработчиков:

Необходимо выбрать пункт «Для разработчиков»

4. Включить сначала опцию Разрешить отладку по ADB только при зарядке, а потом опцию Отладка по USB. Первая опция вроде бы не обязательна, но без нее у меня не работало:

Включить необходимые опции

5. И еще один шаг на всякий случай. Если Visual Studio не может найти ваше устройство после всех предыдущих шагов — выполните Tools -> Android -> Restart Adb Server:

Если Visual Studio не может найти ваше устройство после всех предыдущих шагов

6. Проверьте, чтобы указанные в настройках пути вели, куда надо. Иначе Visual Studio просто не найдет нужные версии SDK и JDK.

Проверьте, чтобы указанные в настройках пути вели, куда нужно

7. Чтобы успешно скомпилировать приложение, нужно выбрать версию ОС, которая установлена на вашем устройстве (или виртуальном устройстве, если используете эмулятор). 

Выберите версию ОС, которая установлена на вашем устройстве

8. Для запуска приложения на устройстве номер версии Android OS не должен быть меньше указанного в настройках манифеста (Minimum Android version): 

Android Manifest

Попробуйте подключить старый Andorid, и увидите, что будет (спойлер: ничего не будет!).

Вернемся к нашему проекту

Нам остается только запустить Xamarin-приложение на устройстве Android. Сборка произойдет автоматически:

Запускаем запустить Xamarin-приложение

Смотрите-ка, запустилось:

Приложение запустилось

Нажав на кнопку с надписью https://highload.today/category/teoriya, получим:

Если нажать на на кнопку с надписью https://highload.today/category/teoriya

Действительно появляется WebView с соответствующим контентом.

Нажав на кнопку с надписью CLEAR, возвращаемся к первому экрану. 

Отлично, все работает в соответствии с нашим ТЗ и даже не падает, когда я закрываю приложение, смахивая его с дисплея моего смартфона. 

Публикация приложения

Чтобы загрузить приложение в Google Play, нужно иметь соответствующий аккаунт и выполнить целый ряд требований. Описание этого процесса выходит за рамки моего рассказа и превышает всякие объемы приличия. Уж простите. Если сильно нужно, то с этой статьи можно начать квест (там и для iOS, и для Android OS). Но сейчас не переключайтесь, пожалуйста. 

Потому что здесь я расскажу, как правильно скомпилировать проект для публикации, как создать ключ, подписать и собрать готовый к публикации .apk-файл.

В Visual Studio на панели инструментов под главным меню выбираем Release вместо Debug:

Под главным меню выбираем Release

В Solution Explorer выбираем Android-проект, нажимаем правую кнопку мыши и открываем его свойства (левой кнопкой на Properties):

Нажимаем левой кнопкой мыши на Properties

Далее переходим в Android.Manifest. Тут почти ничего менять не пришлось (как минимум это справедливо для Visual Studio Community 2019 16.11.0). Понадобилось только выбрать иконку приложения (Application icon). Эту иконку (точнее набор копий иконки разных размеров) Xamarin выдает по умолчанию. Можно заменить на свою в папке Resources текущего проекта:

Иконку можно заменить на свою в папке Resources

На следующей вкладке Android.Options убираем галочку с опции Enable developer instrumentation (debugging and profiling). Так безопаснее. Сегодня спонсор паранойи — корпорация Microsoft:

Убираем галочку с опции Enable developer instrumentation

Сохраняем и закрываем окно со свойствами и опять попадаем в Solution Explorer. Там последовательно выполняем два действия:

1. Очищаем проект (Clean ).

2. Пересобираем проект (Rebuild).

Очищаем и пересобираем проект

Выбираем Android-проект, нажимаем правую кнопку мыши и затем — Archive.

Выберите Android-проект, нажмите правую кнопку мыши и затем — Archive

Дожидаемся, пока сформируется файл .apk. Сформировался? Замечательно. Но пока он не подписан. Поэтому продолжаем. 

Нажмем на кнопку Distribute:

Нажмите на кнопку Distribute

В появившемся окне выберем Ad Hoc (мы ведь создаем apk без загрузки в Google Play):

Нажмите Ad Hoc

Далее нужно создать Ключ (Android Key Store), которым будем подписывать наш файл приложения:

Создаем ключ

Ниже пример заполнения полей. Нужно заполнить все поля и нажать Create.

Важно: запомните пароль, который вы придумали, так как через пару-тройку шагов вновь потребуется его ввести!

Создаем ключ

После создания Ключа нужно нажать Save As для сохранения подписанной версии файла .apk:

Нажмите Save As

Здесь можно ввести произвольное название для файла:

Вводим название файла

При сохранении потребуется ввести пароль, который мы вбили при создании Android Key Store.

Все, мы получили .apk-файл, который можно скопировать на телефон или разослать кому-то по почте. Пишите письма. Пока!

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023