Xamarin Forms в действии. Medchest Assistant

в 14:59, , рубрики: C#, github, mobile, Блог компании DataArt, Программирование, разработка, разработка мобильных приложений, Разработка под android, разработка под iOS

Xamarin Forms в действии. Medchest Assistant - 1
Автор: Константин Марс

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

Мы долго колебались с выбором платформы между популярной и престижной iOS и модным, современным и приятным в разработке Android. Поэтому я предложил использовать Xamarin, который, между прочим, использует C# как основной язык разработки (и это главный язык, на котором в повседневной жизни пишет организатор нашей команды Арсений). Таким образом мы подошли к началу путешествия в мир кроссплатформенной разработки с Xamarin.

Отмечу, что Xamarin изначально базировался на фреймворке Mono, и поэтому несколько отличается от оригинального .NET-фреймворка Microsoft. Но эти отличия обсудим немного позднее.

В статье не станем обсуждать подробности хакатона и не будем углубляться в профессиональные секреты разработки с помощью Xamarin. Эта статья — базовая вводная в мир кроссплатформенной разработки с помощью Xamarin Forms. Цель материала — дать общее представление, как быстро разрабатывать с помощью Xamarin, подсказать, где в будущем искать ответы на более конкретные вопросы.

Архитектура проекта. PCL

Xamarin Forms строится вокруг общего кросс-платформенного кода, и может быть построен по одному из архитектурных подходов — PCL (Portable Class Library) или SAP (Shared Assets Project). Платформо-зависимые проекты — неотъемлемая часть солюшн Xamarin, называются соответственно и размещены в солюшне наравне с проектом общего кода.

Например, в нашем приложении мы имеем такой набор проектов:

Xamarin Forms в действии. Medchest Assistant - 2

Как видите, присутствуют проекты для Android (Droid) и iOS, отдельный проект для AndroidWear (он корректно инсталируется вместе с Android-приложением на смарт-часы, но пока не выполняет заметную полезную работу, кроме демонстрации возможностей фреймворка  Xamarin для создания AndroidWear проектов). Еще есть проект библиотеки VuforiaBindings library (Java wrapper, который был задуман как интегратор Java-библиотеки Vuforia для распознавания образов и текста). Это примеры ключевых видов проектов, наиболее часто встречающихся при разработке c помощью Xamarin.

Xamarin Forms. XAML

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

Это стало возможным благодаря тому, что каждый платформо-зависимый проект стартует код из общего проекта, осуществляя иньекцию небольшого участка кода, специфичного для Xamarin Forms.
Например, в Android-проекте это происходит в MainActivity так:

global::Xamarin.Forms.Forms.Init (this, bundle); 

В iOS проекте:

global::Xamarin.Forms.Forms.Init (); 

В то же время, если вы заглянете в MainActivity проекта для AndroidWear – вы не найдете там ничего связанного с Xamarin Forms. Это потому что проект для этой платформы пока не поддерживается Xamarin Forms и является “чистым” платформо-зависимым проектом, написанным на C#.

Разметка UI в Xamarin Forms наывается XAML. Здесь все очень похоже на “классический” .NET (WPF):

Xamarin Forms в действии. Medchest Assistant - 3

Внутри XAML выглядит тоже вполне привычно для тех, кто имеет опыт работы с .NET:

<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand">
            <Label x:Name="label" Text="List of medicines" HorizontalOptions="Center" />
            <StackLayout Orientation="Horizontal">
                <Entry x:Name="nameEntry" HorizontalOptions="FillAndExpand" />
                <DatePicker x:Name="datePicker" HorizontalOptions="End"/>
                <Button x:Name="addButton" Text="Add" Clicked="add" HorizontalOptions="End" />
                <Button x:Name="scanButton" Text="Scan" Clicked="scan" HorizontalOptions="End" />
            </StackLayout> 

Ключевой функционал Bindings работает по тем же принципам, что и биндинги в WPF:

<ListView x:Name="list" VerticalOptions="FillAndExpand">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Text="{Binding Name}" Detail="{Binding ExpireDate, StringFormat='Expires: {0:MM-dd-yy}'}">
                            <TextCell.ContextActions>
                                <MenuItem Clicked="onDelete" CommandParameter="{Binding .}" Text="Delete" IsDestructive="True" />
                            </TextCell.ContextActions>
                        </TextCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

Мы просто размещаем “{Binding <VARIABLE NAME>}” в XAML вместо хардкода значений.

Основной проблемой для разработчиков Xamarin, которые работают в Xamarin Studio (например на Mac OS) является отсутсвие адекватного визуального редактора UI. Странно, что при этом студия обеспечивает разработчикам визуальные редакторы для конкретных платформ, таких как Android и iOS, но, увы, не для Xamarin Forms.

Xamarin Forms в действии. Medchest Assistant - 4

Xamarin Forms в действии. Medchest Assistant - 5

DependecyService. Платформо-специфичные возможности и Xamarin Forms

Когда приходит время реализовать что-то специфичное для платформы (например, нотификации), нам уже не обойтись без платформо-зависимого кода.
Это неизбежно — ведь те же нотификации реализуются совсем по-разному для Android и iOS, и эта разница выражается во многих нюансах поведения функционала. Но как тогда вызывать подобный платформо-зависимый код из UI, общего для всех платформо-зависимых проектов?

Здесь нам на помощь приходит DependencyService.
Как обычно в кросс-платформенной разработке, нужно объявить интерфейс в общем проекте и реализовать его в платформо-зависимых проектах. Единственным вопросом будет «как определить, какую реализацию вызвать в каждом конкретном случае?». И тут за работу берется DependencyService, магический деятель фреймворка Xamarin. В зависимости от того, для какой платформы мы собираем проект, DependencyService подставляет необходимую реализацию вместо интерфейса.
Также стоит отметить, что для того чтобы эта магия заработала, нужно использовать аннотацию Xamarin.Forms.Dependency:

[assembly: Xamarin.Forms.Dependency (typeof (NotificationHelperImpl))]

Например, интерфейс нотификаций, объявленный в общем проекте Xamarin Forms выглядит так:

namespace MedChestAssistant
{
    public interface INotificationHelper
    {
        void notify(String message);
    }
}

А платформо-зависимая реализация в Android-проекте выглядит так:

[assembly: Xamarin.Forms.Dependency (typeof (NotificationHelperImpl))]
namespace MedChestAssistant.iOS
{
    public class NotificationHelperImpl: INotificationHelper
    {
        #region INotificationHelper implementation

        public void notify (string message)
        {
            var notification = new UILocalNotification();

            // set the fire date (the date time in which it will fire)
            notification.FireDate = NSDate.FromTimeIntervalSinceNow(5);

            // configure the alert
            notification.AlertAction = "Medical Chest Reminder";
            notification.AlertBody = "Lyrica will expire in 2 days. Don't forget renew it";

            // modify the badge
            notification.ApplicationIconBadgeNumber = 1;

            // set the sound to be the default sound
            notification.SoundName = UILocalNotification.DefaultSoundName;

            // schedule it
            UIApplication.SharedApplication.ScheduleLocalNotification(notification);
        }

        #endregion

        public NotificationHelperImpl ()
        {
        }
    }
} 


В целом все достаточно просто :).

Зависимости. Пакеты. Галерея NuGet

Xamarin имеет довольно богатую библиотеку пакетов, совместимых с поддерживаемыми платфорамами — NuGet. Например, тот, кому нужно распознавание и сканирование баркодов может воспользоваться пакетом Zxing, совместимым с Xamarin.

Xamarin Forms в действии. Medchest Assistant - 6

После добавления пакет появися в списке подключенных пакетов проекта.
Вот, например, кросс-платформенная часть пакета Zxing в нашем кросс-платформенном проекте Xamarin Forms:

Xamarin Forms в действии. Medchest Assistant - 7

Иногда (например для библиотеки Zxing library) нам нужно осуществить также некоторую специфичную для конкретных платформ инициализацию. Например, для Zxing нужно выполнить такие строки на старте платформ-специфичных приложений:

Android:

ZXing.Mobile.MobileBarcodeScanner.Initialize (Application);

iOS:

ZXing.Net.Mobile.Forms.iOS.Platform.Init();

Также платформ-специфичная инициализация бывает нужна и для стандартного функционала.
Например, нотификции в iOS требуют декларирования поддерживаемых форматов на старте приложения (это делается всегда в нативном iOS, и Xamarin просто покрывает уже существующую специфику):

if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                var notificationSettings = UIUserNotificationSettings.GetSettingsForTypes (
                    UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, null
                );

                app.RegisterUserNotificationSettings (notificationSettings);
            }

Вот и весь краткий обзор возможностей разработки с Xamarin.

Исходный код нашего проекта с хакатона вы можете посмотреть здесь: https://github.com/DataArt/MedChestAssistant.git

Заметьте, это всего лишь код, написанный за короткий отрезок времени на хакатоне. Поэтому здесь покрыты лишь некоторые основные возможности Xamarin. Вы не найдете тут сервисов, выполняющихся в бэкграунде, сложных архитектурных паттернов, юнит-тестов или dependency-injection, которые конечно же понадобятся в коммерческих проектах. Наше приложение призвано показать, как быстро и легко решать конкретные задачи в сжатые сроки с помощью отличного кросс-платформенного инструмента, называемого Xamarin.

Если вы хотите узнать больше про Xamarin, обратитесь к официальной книге от Microsoft https://developer.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/
и посетите Xamarin Portal для изучения самых актуальных рецептов кросс-платформенной разработки https://developer.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/

Удачи вам в мире кросс-платформа! И новых свершений с Xamarin! :)

Автор: DataArt

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js