Сентябрь 2016

Том 31 номер 9

Xamarin - Эффективная кросс-платформенная работа в Xamarin

Кевин Эшли | Сентябрь 2016

Продукты и технологии:

Xamarin, Android, iOS и Windows

В статье рассматриваются:

  • дизайнерские аспекты кросс-платформенных приложений, создаваемых в Xamarin;
  • специфичный для устройств код и Xamarin;
  • доступ к облаку из Xamarin;
  • расширения, компоненты и плагины;
  • поддержка носимых устройств (wearables);
  • компиляция XAML.

Если вы побываете в настоящее время в Кремниевой долине, то заметите, что инвесторы и разработчики в большинстве своем настроены весьма консервативно в отношении используемых технологий. Большинство компаний сначала нанимают разработчика под iOS, затем (если у них есть достаточные средства) разработчика под Android и/или Windows. Однако такой подход крайне неэффективен и ведет к переписыванию больших объемов кода: iOS-разработчики применяют Objective-C, Android-разработчики — Java, а Windows-разработчики — C#. Они редко общаются друг с другом, еще реже обмениваются кодом, и это приводит к появлению приложений, несогласованных между платформами, а значит, и к растрате миллионов долларов на поддержку полностью раздельных ветвей и технологий разработки. Если вам нужна эффективная и согласованная технологическая стратегия, ключом к продуктивной работе является использование кросс-платформенной технологии вроде Xamarin. А с появлением «родных» технологий заблаговременной компиляции (ahead-of-time [AOT] compilation), которые транслируют код, написанный на высокоуровневых языках наподобие C#, в статический код, «родной» для конкретных платформ, модель программирования, где нужны отдельные разработчики под Android, iOS и Windows, уходит в прошлое.

Это новое направление для традиционных приложений, но уже весьма успешное в других областях, например в игровой индустрии. Так, более половины всех трехмерных игр для iOS, Android и Windows создаются в Unity. Создавая игры в Unity, вы в основном пишете код на C# в подмножестве Mono, и это весьма похоже на использование C# с Xamarin. Unity-игры выполняются на более чем 20 платформах, в том числе Windows, Android, iOS, OS X, Xbox, PlayStation и др. Это отличный вариант и в разработке неигровых приложений, поэтому Xamarin предоставляет для него превосходную платформу.

Можно ли тот же подход применить для других приложений — не только для игр? С помощью Xamarin — можно: я использовал его при создании Active Fitness, облачной платформы для фитнеса и соответствующих мобильных приложений с более чем двумя миллионами пользователей по всему миру (activefitness.co). Я начал использовать Xamarin еще на раннем цикле разработки и смог создать кросс-платформенное решение для Windows, iOS и Android на основе облака Microsoft Azure. Могу похвастаться тем, что Active Fitness, показанное на рис. 1, имеет более 90% общего кода в своих «родных» приложениях для iOS, Windows и Android. Это само по себе является выигрышем в продуктивности труда. В дополнение большая часть Xamarin, включая Xamarin.Forms (bit.ly/2a8Yo4g), имеет открытый исходный код; платформа активно поддерживается сообществом, и производительность идентична «родному» коду благодаря поддержке AOT во встраиваемых системах. Более того, Xamarin включается в Visual Studio без дополнительной платы, в том числе в Community Edition.

Active Fitness в действии; демонстрируются трехмерные карты и богатый UI
Рис. 1. Active Fitness в действии; демонстрируются трехмерные карты и богатый UI

Дизайнерские аспекты кросс-платформенных приложений, создаваемых в Xamarin

Несколько лет назад дизайн мобильных приложений был поразительно разным на каждой платформе. Например, приложение iOS по дизайну вообще ничем не напоминало приложение Android или Windows. Этого больше нет. Сегодня большинство современных приложений для Windows, Android и iOS используют похожие концепции и парадигмы дизайна. Что случилось? Microsoft создала язык дизайна Modern, применяемый в приложениях Universal Windows Platform (UWP), Google представила дизайн Material, а Apple ввела более современно выглядящий дизайн ОС. Все эти изменения сделали приложения в iOS, Android и Windows выглядящими и действующими подобно друг другу, упростив задачи разработчикам (рис. 2). Разработчики даже прибегли к иконическим шрифтам (iconic fonts), таким как Font Awesome, которые используют сходные концепции символов для одинаковых действий на разных платформах. Конечно, платформы все еще имеют визуальные отличия, например Windows включает активные плитки (live tiles). Возможно, вас это удивит, но, как только вы создадите кросс-платформенное приложение, эти детали легко добавить.

Active Fitness в Windows (слева), Android (в середине) и iOS (справа)
Рис. 2. Active Fitness в Windows (слева), Android (в середине) и iOS (справа)

При разработке с помощью Xamarin у вас есть возможность создавать красивый UI для каждой платформы непосредственно из Visual Studio. Это подразумевает применение iOS Storyboards, Android XML и Windows XAML с доступом к каждому элементу управления или виджету и огромному количеству пользовательских элементов управления от соответствующих поставщиков. Более того, Xamarin обеспечивает стопроцентный доступ полностью из C# к API для каждой платформы.

С помощью библиотеки Xamarin.Forms, которая предоставляет абстракцию API для создания общего UI, многие концепции дизайна через пользовательские рендеры (custom renderers) Xamarin автоматически транслируются в наборы «родных» для каждой платформы элементов управления; это дает вам возможность адаптировать кросс-платформенный элемент управления в его «родное» представление на каждой платформе. Так что вы получаете выигрыш в производительности от истинно кросс-платформенного приложения плюс неограниченные возможности в настройке!

Одно из колоссальных преимуществ применения Xamarin.Forms заключается в том, что это просто надстройка (add-on) — библиотека, добавляемая вами в проект. В отношении продуктивности труда и управления жизненным циклом приложения она бесценна, поскольку вы можете писать код, не особо зависимый от циклов выпуска версий платформ, которые обычно намного длиннее. Xamarin всегда день в день обеспечивала совместимость с основными выпусками iOS, Android и Windows, а теперь, когда она стала системой с открытым кодом, вы можете при необходимости самостоятельно добавить какой-либо элемент управления в Xamarin.Forms, изучив исходный код из репозитария на GitHub для Xamarin.Forms. Кроме того, Xamarin предлагает практически неограниченные возможности расширения через пользовательские рендеры элементов управления для «родных» платформ. Если у вас уже есть какое-то XAML-приложение, вам повезло, потому что Xamarin.Forms — это просто другой диалект XAML, а если ваше приложение использует Silverlight, UWP или XAML, вы можете легко добавить некий кросс-платформенный компонент в iOS или Android.

Создание средств навигации «основное/подробное представление» в Xamarin

Давайте рассмотрим преимущества использования Xamarin, сосредоточившись на одном примере: типичном приложении в iOS, Android и Windows, содержащем шаблон навигации master-detail (основное/подробное представление) (или «гамбургер»). Это приложение мы возьмем из репозитария примеров для Xamarin с открытым исходным кодом (bit.ly/29Tk9VJ). Если бы вы писали это приложение так, как это традиционно делают разработчики для iOS, Android или Windows, вы получили бы в итоге три проекта (на Objective-C, Java и C#), и вам пришлось бы использовать разные элементы управления для каждого из них: SplitView в Windows и аналогичные шаблоны в iOS и Android. Вместо этого вы можете использовать единственный экземпляр Xamarin.Forms, который возьмет на себя всю трудную работу для всех платформ (рис. 3).

Проект Xamarin Master-Detail с ориентацией на Android, iOS и Windows
Рис. 3. Проект Xamarin Master-Detail с ориентацией на Android, iOS и Windows

В файле App.cs портируемого (portable) проекта я создаю экземпляр корневой страницы приложения:

public App ()
{
  MainPage =
    new MasterDetailPageNavigation.
    MainPage ();
}

Заметьте, что большая часть кода находится в портируемом проекте, общем для всех операционных систем, и что в Xamarin.Forms можно использовать XAML. Например, XAML на рис. 4 выглядит довольно просто, если вы знакомы с «родным» элементом управления SplitView в UWP.

Рис. 4. Создание страницы «основное/подробное представление» с помощью XAML

<?xml version="1.0" encoding="UTF-8"?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MasterDetailPageNavigation;
assembly=MasterDetailPageNavigation"
x:Class="MasterDetailPageNavigation.MainPage">
  <MasterDetailPage.Master>
    <local:MasterPage x:Name="masterPage" />
  </MasterDetailPage.Master>
    <MasterDetailPage.Detail>
      <NavigationPage>
        <x:Arguments>
        <local:ContactsPage />
        </x:Arguments>
      </NavigationPage>
    </MasterDetailPage.Detail>
</MasterDetailPage>

Xamarin обеспечивает высокую гибкость в отношении того, что разработчики могут делать с условной компиляцией и выбором платформы. Следующий код меняет значок основной страницы (master page), если платформой является Windows:

if (Device.OS == TargetPlatform.Windows)
{
  Master.Icon = "hamburger.png";
}

Специфичный для устройств код и Xamarin

Пока все неплохо, но действительно ли я могу получить практически полный доступ к физической платформе в своем коде Xamarin? Иначе говоря, могу ли я разграничить код, созданный для разных типов устройств? К счастью, Xamarin — одна из немногих кросс-платформенных технологий, которая поддерживает кодирование под «родную» среду и обеспечивает доступ к API. Аналогично UWP-приложениям, позволяющим разграничивать семейства устройств (смартфоны, планшеты или настольные ПК), Xamarin содержит очень полезный селектор Device.Idiom, как показано на рис. 5.

Рис. 5. Применение Device.Idiom для выбора платформы

switch (Device.Idiom)
  {
  case TargetIdiom.Phone:
    heading.Text += " Phone ";
    break;
  case TargetIdiom.Tablet:
    heading.Text += " Tablet ";
    break;
  case TargetIdiom.Desktop:
    heading.Text += " Desktop ";
    break;
  default:
    heading.Text += " unknown ";
    break;
  }

На рис. 6 представлен другой очень полезный селектор, Device.OnPlatform, который можно использовать как в отделенном коде (codebehind), так и в XAML для выполнения различных операций в зависимости от целевой ОС.

Рис. 6. Применение Device.OnPlatform к разным целевым платформам

// Device.OnPlatform (Action)
//
var box = new BoxView {
  Color = Color.Green,
  WidthRequest = Device.OnPlatform (30, 40, 50),
  HorizontalOptions = LayoutOptions.Center
};
Device.OnPlatform(
  iOS: () =>{
    box.Color = box.Color.MultiplyAlpha(0.5);
    heading.TextColor = Color.Blue;
  },
  Android: () =>{
    box.Color = box.Color.AddLuminosity(0.3);
    heading.TextColor = Color.FromRgb(115, 129, 130);
  },
  WinPhone: () =>{
    box.Color = box.Color.AddLuminosity(0.3);
    heading.TextColor = Color.Accent;
  },
  Default: () =>{
    heading.Text = "what platform is this?!" + Device.OS;
  }
);

Xamarin добавляет в XAML теги OnPlatform, поддерживающие разные платформы, например:

<Button Text="Start Timer"
  Clicked="TimerClicked"
  BackgroundColor="Gray"
  HorizontalOptions="Center">
  <Button.WidthRequest>
    <OnPlatform x:TypeArguments="x:Double"
      iOS="200"
      Android="300"
      WinPhone="100" />
  </Button.WidthRequest>
</Button>

А как быть, если я хочу адаптировать элемент управления, предоставляемый Xamarin.Forms на конкретной платформе? Я уже упоминал о такой функции Xamarin, как пользовательские рендеры, которые обеспечивают эту возможность. Пользовательские рендеры — это классы, которые можно наследовать от встроенных объектов и которые предоставляют функциональность в специфичных для платформ реализациях. Допустим, я хочу создать свой элемент управления CustomMap:

public class CustomMap : Map
  {
    public List<CustomPin> CustomPins { get; set; }
  }

На «родной» платформе сигнатура моего объекта будет включать следующее:

[assembly:ExportRenderer (typeof(CustomMap),
  typeof(CustomMapRenderer))]

Поэтому в Android, iOS и Windows я всегда могу настроить то, как выглядит мой элемент управления Map. Любопытно, что оболочка для элемента управления Xamarin Map обертывает элемент управления Windows Maps в Windows, элемент управления Google Maps в Android и «родной» элемент управления iOS Maps в iOS. Что еще можно адаптировать с помощью пользовательских рендеров? Почти любой элемент управления! Элемент управления Map — довольно сложный пример, но можно адаптировать кнопки, надписи, ползунки или любой элемент управления, доступный в Xamarin.Forms.

Благодаря Xamarin.Forms 2.2 теперь Xamarin включает «родное» встраивание (native embedding), что позволяет добавлять любой «родной» элемент управления в приложение Xamarin.Forms (bit.ly/29IEvxH).

Доступ к облаку из Xamarin

Azure всегда была дружественна к кросс-платформенным решениям, предоставляя разнообразные SDK для многих платформ, в том числе iOS, Android и специализированных кросс-платформенных примеров, а также поддержки для Xamarin. За счет этого мое приложение Active Fitness удалось масштабировать под два миллиона пользователей. Благодаря Azure — ее надежности, поддержке и производительности — пользователи могут отслеживать свои данные при ежедневных пробежках, разминках и выполнении различных спортивных упражнений, и каждую минуту подключаются тысяч устройств. Вы найдете несколько отличных руководств по Xamarin на веб-сайте Azure, которые помогут вам узнать о наиболее подходящих для ваших приложений облачных сервисах Microsoft (bit.ly/2a5kciF). Между тем, я хотел бы отметить несколько распространенных областей, где облако очень полезно для мобильных приложений.

Аутентификация Если вам нужно аутентифицировать или идентифицировать пользователей, то скорее всего в вашем приложении Xamarin понадобятся облачные сервисы (подробнее см. по ссылке bit.ly/29HlDD3).

Добавление всплывающих уведомлений в ваши приложения Всплывающие уведомления (push notifications) не только предоставляют механизм взаимодействия для приложений, но и помогают обновлять специфичные для платформы средства, такие как плитки (подробнее см. по ссылке bit.ly/29HlDD3).

Автономная синхронизация Мобильные приложения при повседневном использовании не всегда находятся в онлайновом режиме, однако данные нужно как-то синхронизировать, даже когда устройство отключается от серверной части. О периодически отсоединяемых наборах данных см. мою статью в «MSDN Magazine» msdn.com/magazine/dn890372, а также краткое руководство по созданию приложений Xamarin на bit.ly/29QkXqT.

Azure Mobile Apps — отличная отправная точка для интеграции многих облачных сервисов, включая хранилище, уведомления и аутентификацию. Обратитесь к учебному пособию на bit.ly/29K3IHi, которое посвящено приложениям Xamarin.

Расширения, компоненты и плагины

Xamarin завоевал популярность и развивался за счет значительной поддержке через компоненты, плагины и расширения. Многие расширения доступны на GitHub или через NuGet. Некоторые библиотеки, например Android Support Libraries, клиентские библиотеки Google Play Services, Facebook SDK и такие библиотеки для создания диаграмм событий, как OxyPlot, поддерживаются Xamarin или ее сообществом. Плагины являются уникальными предложениями, которые позволяют разработчикам обращаться к «родной» функциональности из общего кода. То есть, если вы хотите обратиться к функциональности GPS, вам больше не придется писать код по три раза для каждой платформы — вы просто скачиваете NuGet-пакет и обращаетесь к GPS прямо из общего кода. Некоторые плагины имеют открытый исходный код и поддерживаются их разработчиками. Так, Джеймс Монтемагно (James Montemagno) разработал большое количество плагинов для Xamarin, например Connectivity, Settings, Media и другие (bit.ly/2a2mM7J).

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

Табл. 1. Расширения Xamarin

Название Описание NuGet-ссылка Документация и исходный код на GitHub
Battery Status Собирает информацию об уровне заряда аккумулятора, состоянии зарядки и типе bit.ly/2a4gbZ6 bit.ly/2a5Ofqm
Barcode Scanner Сканирует и создает штрих-коды с помощью ZXing.NET.Mobile bit.ly/2a5Ofqm bit.ly/29QykY9
Compass Позволяет обращаться к направлению компаса на устройстве bit.ly/2a32UAZ bit.ly/29KfcKV
Connectivity Получает информацию о сетевых подключениях, такую как тип и доступность соединения bit.ly/29QDplO bit.ly/2a33PBr
Cryptography PCL Crypto предоставляет согласованный, портируемый набор криптографических API bit.ly/29Qz5AE bit.ly/29PzwAb
Device Info Получает характеристики устройства, например ОС, модель, версия и идентификатор bit.ly/29PzPeg bit.ly/29QzSBq
Device Motion Обеспечивает доступ к акселерометру, гироскопу, магнитометру и компасу bit.ly/2a6SzTk bit.ly/2a35maG
Embedded Resource Распаковывает встроенный ресурс для кросс-платформенного использования bit.ly/29J6Wf3 bit.ly/29J6z46
External Maps Запускает внешние карты по долготе-широте или по адресу bit.ly/29KgNR0 bit.ly/2abuJbI
File System PCL Storage предлагает кросс-платформенные API хранилища bit.ly/29LEOru bit.ly/28Ju1AB
Geolocator Обнаруживает GPS-координаты устройства bit.ly/2a70ekG bit.ly/29Tpuvd
Local Notifications Показывает локальные уведомления bit.ly/2arOGYf bit.ly/29TpSd7
Media Позволяет принимать или выбирать фотоснимки и видеозаписи bit.ly/2a6rpxi bit.ly/29TqlMm
Messaging Позволяет выдавать телефонный звонок, отправлять SMS или сообщение по электронной почте bit.ly/2a8Uie5 bit.ly/29SEdDm
Permissions Проверяет и запрашивает разрешения в период выполнения bit.ly/29Tnvo8 bit.ly/29S6ZKv
Akavache key-value store Асинхронное, постоянное (с записью на диск) хранилище пар «ключ-значение» bit.ly/29Tou7I bit.ly/2arPSLf
Push Notifications Кросс-платформенные всплывающие уведомления для iOS и Android bit.ly/29ToDs5 bit.ly/2aex4CR
Settings Простой, согласованный кросс-платформенный API настроек bit.ly/29ToTXT bit.ly/2a6tn0Q
Share Позволяет легко обмениваться текстом, ссылками или открывать браузер bit.ly/2aa2R51 bit.ly/2aa3sUk
Sockets TCP- и UDP-слушатели и клиенты плюс групповая рассылка по UDP bit.ly/1rQIyyR bit.ly/1y1UHPb
Text to Speech Позволяет обращаться к механизму синтеза речи из общего кода bit.ly/29S7Yud bit.ly/29MMA3S
User Dialogs Поддерживает диалоги в стиле окон сообщений bit.ly/2aa4dMV bit.ly/29Tqzkd
Version Tracking Отслеживает, какие версии вашего приложения устанавливал пользователь bit.ly/29S8YhH bit.ly/2a74lNW

Например, для проверки сетевых подключений с помощью плагина Connectivity в кросс-платформенном решении достаточно одной строки кода вместо специфичного для платформы кода, который нужно раздельно реализовать в iOS, Android и Windows:

public static bool IsOnline
  {
    get
    {
      return Plugin.Connectivity.CrossConnectivity.Current.IsConnected;
    }
  }

Еще больше плагинов и расширений доступно по ссылке bit.ly/29XZ3VM.

Поддержка устройств: Android Wear, WatchKit и Microsoft Band

Xamarin всегда быстро реагировала на появление любых видов устройств и аппаратных платформ на рыке. Я имел удовольствие работать с группой Microsoft Band, и на конференции Build 2016 мы совместно объявили о некоторой весьма интересной функциональности для Active Fitness, в которое была добавлена поддержка более 50 видов фитнеса, в том числе катание на лыжах, сноуборде и др. Кроме того, Active Fitness теперь поддерживает Android Wear (рис. 7). Если вы устанавливаете Active Fitness на устройство Android, то получаете полную поддержку циферблата часов.

Циферблат Android Wear для приложения Active Fitness
Рис. 7. Циферблат Android Wear для приложения Active Fitness

С помощью Xamarin можно добавлять приложения и поддержку гаджетов и устройств, используя следующее.

  • Android Wear: Xamarin включает примеры кода и поддержку, в том числе для создания циферблатов на C#.
  • Apple WatchKit: Поддержку Xamarin см. в документации по ссылке bit.ly/29XZ3VM.
  • Microsoft Band: Помимо Microsoft Band SDK, существует фантастическая оболочка Microsoft Band для кросс-платформенных приложений на Xamarin; она доступна на GitHub (bit.ly/29WeDli) и через NuGet (bit.ly/29SOoLA).

Производительность и компиляция XAML

Xamarin.Forms использует комбинацию логики в XAML и в отделенном коде. При желании можно использовать только код для создания экземпляров UI-объектов и управления ими. По сути, ничто не мешает вам кодировать большую часть UI, кроме эффективности (декларативная природа XAML делает его очень эффективным в написании и управлении). Но если вы действительно хотите этого, то можете наследовать свой Page от ContentPage и писать всю логику в коде, без XAML, как показано на рис. 8.

Рис. 8. Наследование Page от ContentPage без XAML

class ButtonCodePage : ContentPage
{
  int count = 0;

  public ButtonCodePage()
  {
    Button button = new Button
    {
      Text = String.Format("Tap for click count!")
    };
    button.Clicked += (sender, args) =>
    {
      count++;
      button.Text =
        String.Format("{0} click{1}!", count,
        count == 1 ? "" : "s");
    };

    this.Content = button;
  }
}

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

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace MyApp

или на уровне класса:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MyPage

Заключение

Разрабатывая в Xamarin, я научился концентрироваться на продуктивности труда и использовать широчайшие возможности сообщества открытого исходного кода Microsoft. Как уже отмечалось, Xamarin очень быстро реагирует на тенденции в мире исходного кода и на появление новых устройств: Android Wear, Apple Watch, Microsoft Band и новейших версий Android, iOS и Windows. Ниже перечислено несколько значимых новых добавлений в Xamarin, которые делают его поистине потрясающей платформой.

  • Страницы данных Упрощают связывание с данными и еще больше облегчают создание сложных многостраничных приложений (bit.ly/29SRtLk).
  • Localization and Multilingual App Toolkit Полностью поддерживает проекты Xamarin, добавляя соответствующую отраслевым стандартам поддержку XLIFF в ваши проекты (bit.ly/2a5Uzwx).
  • Native Control Embedding Сильно упрощает добавление «родных» элементов управления в приложения Xamarin (bit.ly/29IEvxH).
  • Эффекты Добавляет в приложения Xamarin специфичные для платформ эффекты (bit.ly/29RDrbD).

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


Кевин Эшли (Kevin Ashley) — архитектор-идеолог в Microsoft. Соавтор книги «Professional Windows 8 Programming» (Wrox, 2012) и разработчик топовых приложений и игр, из которых самым известным является Active Fitness (activefitness.co). Часто выступает с презентациями технологий на различных мероприятиях, отраслевых выставках и принимает участие в веб-кастах. По роду своей деятельности работает с начинающими компаниями и партнерами, консультируя по дизайну программного обеспечения, стратегии бизнеса, технологиям, архитектуре и разработке. Следите за его блогом на kevinashley.com и в Twitter (@kashleytwit).

Выражаю благодарность за рецензирование статьи эксперту Microsoft Джеймсу Монтемагно (James Montemagno)