Development for iOS
C++
May 2014 13

Разработка мобильных приложений в Embarcadero FireMonkey (FMX 6)

Никому не нравится писать один и тот же код несколько раз, но именно это и приходится делать, если мобильное приложение должно быть реализовано для нескольких платформ сразу. Досадно, что программистам компании, в каждом случае, требуются применять различные инструменты, навыки и подходы. Разумеется, возникает желание, чтобы, перенося приложение, как минимум, не приходилось менять язык программирования.

Вот и в этот раз, размышляя о сложностях разработки приложений для мобильных, мы не устояли перед соблазном примерить на себя древнюю Русскую мечту, и, подобно герою сказки «По щучьему веленью», покататься на печи. Забегая вперед, скажем, что «печь» поехала, хотя и с некоторым скрипом.

Итак, как известно, существует несколько подходов, применяемых в кросс-платформенной разработке мобильных приложений. Каждое из этих решений имеет свои недостатки, и, возможно, сравнительный анализ различных подходов мы изложим в одной из следующих публикаций. Здесь же речь пойдёт лишь об одном таком инструменте, который, как нам кажется, несколько обойдён вниманием аудитории, хотя и обладает рядом уникальных особенностей.

FireMonkey — это продукт небезызвестной компании Embarcadero. FireMonkey входит в состав среды разработки RAD Studio. Лежащий в его основе движок FMX был когда-то разработан нашим соотечественником, и представляет собой похожий на Flash или WPF, кросс-платформенный фреймворк для построения пользовательских интерфейсов. При этом, как и упомянутые продукты, FMX использует векторную графику и аппаратную акселерацию. Продукт появился всего несколько лет назад, но за это время вышло уже 5 обновлений. Хочется верить, что продукт не постигнет участь печально известного Delphi .NET.

Приложения компилируется напрямую в машинный код, и это является одной из главных отличительных особенностей рассматриваемого решения. В связи с этими замечательным обстоятельством, Embarcadero, в теории, обещает нам общую производительность на уровне нативных приложений. Будучи встроенным в Delphi и в С++ Builder, FireMonkey позволяет реализовывать логику приложений на Pascal и C++. Один и тот же код приложения FireMonkey (FM) может быть скомпилирован для работы в Windows, iOS и Android. Нас привлекла возможность вести разработку на C++, так как в штате компании имелось большое количество программистов по этому направлению. Поэтому для проверки работоспособности был установлена именно C++ Builder версия RAD Studio XE6, хотя редакция Delphi не должна отличаться ничем, кроме используемого языка программирования.

Сборка приложений


Имея за своей спиной бурное прошлое, связанное с созданием компиляторов, производитель снарядил FireMonkey нативными компиляторами С++ для x86 и ARMv7. Это позволяет выполнять компиляцию непосредственно на компьютере, где запущена среда разработки. Именно наличие собственных компиляторов и дает нам возможность программировать на C++ или даже Pascal, получая необходимый машинный код ARM на выходе. Однако для сборки приложения (link), подписывания, запуска на устройствах и отладки по-прежнему используется оригинальный инструментарий из средств разработки (SDK) мобильных платформ. Таким образом, перед началом работы вам всё равно потребуется выполнить следующие действия:

iOS Android
Иметь Mac ---
Зарегистрироваться в iOS Developer Program Зарегистрироваться на сайте Android Developer
Получить сертификаты (developer, provisioning) Сгенерировать ключ для подписи приложений
Скачать и установить iOS SDK Скачать и установить Android SDK и NDK
Скачать и установить PAServer на Mac ---
Настроить соединение между RAD Studio и PAServer ---

Поскольку и RAD Studio и инструментарий Android работают на PC, то для разработки под Android требуется несколько меньше телодвижений, чем для iOS. Для сборки iOS приложений требуется Mac OS (так как только для неё Apple выпускает SDK). Таким образом, если разработка приложения проходит на PC, они должны как-то связываться. Из приведенный ниже диаграммы видно, как при помощи поставляемого Embarcadero PAServer (Platform Assistant Server) осуществляется сборка приложений iOS через PC:



Пример


В рамках пробы FireMonkey мы разработали простое приложение (на уровне Hello world), на примере которого хотелось проверить работоспособность предлагаемой технологии.

Ниже приведен скриншот версии этого приложения для Windows и небольшой видеоролик, чтобы можно было увидеть его нехитрую работу в динамике:

image


Наше приложение почти не содержит кода. Тем не менее, расскажем, что именно мы делали.

В данном случае нас интересовала мутация пользовательского интерфейса на разных платформах, а также производительность, но в «житейском» её понимании. То есть пользователю важно не количество операций с плавающей точкой в секунду, а насколько мягко и быстро откликается приложение на его действия.

Приложение состоит из нескольких стандартных элементов управления и содержит пару обработчиков действий пользователя. В верхней части экрана расположена «крутилка», двигая которую, можно поворачивать картинку слева. Эта часть теста была нужна для проверки способности FMX к рисованию двухмерной графики, точнее выполнения растровых операций.

Расположенный чуть ниже прогресс индикатор отображает текущее значение угла, на которое выставлено колесо. Он нужен для проверки взаимодействий в UI потоке и, также, чтобы посмотреть на стиль этого элемента на разных платформах.

Обработчик поворота колеса:
//---------------------------------------------------------------------------
void __fastcall TForm1::DialAngleChange(TObject *Sender)
{
	// Every time the angle dialer is spinned, assign
	// its current value to the Image control...
	imgLogo->RotationAngle = 360 - DialAngle->Value;

	// The progress bar will get updated with a normalized angle value
	pbAngle->Value = (int)fabs(DialAngle->Value)%360;
}
//---------------------------------------------------------------------------

Как видно, это обычный C++, но немного «запачканный» наследием Delphi.

Ниже расположена традиционная кнопка (которая, впрочем, не так уж и похожа на кнопку) со следующим HW обработчиком:
//---------------------------------------------------------------------------
void __fastcall TForm1::btnHelloClick(TObject *Sender)
{
	// A simple HW assignment
	btnHello->Text = "Hello world!";
}
//---------------------------------------------------------------------------


Правее виднеется поле для выбора даты (DateTimePicker). Нас интересовал, прежде всего, его внешний вид на мобильных ОС: будет ли в каждом случае использован нативный элемент управления или что-то рисованное. По этой же причине ниже следует ползунок и переключатель ВКЛ./ВЫКЛ. Этот переключатель, однако, обрел еще одну функцию: он включает один из стандартных визуальных эффектов FMX (радиальное размытие): нам хотелось посмотреть, рисует ли FMX элементы управления сам или делегирует эту работу мобильной ОС. Ниже мы еще вернемся к этому вопросу, так как результат оказался не очевидным.

В самом низу размещена таблица с двумя колонками. Таблица имеет отчетливые черты desktop приложения, хотя и с инерционной прокруткой. Нам хотелось посмотреть: каково будет ей пользоваться на мобильном телефоне. Таблица заполняется на старте приложения, просто, чтобы глазу было за что цепляться:
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	// Initialize the string grid with a bit of texts
	// Define the number of items
	gdDemo->RowCount = 1000;

	// Generate the texts for every Row and Column
	for(int r = 0; r < gdDemo->RowCount; r++)
	{
		gdDemo->Cells[0][r] = "iResearchFX";
		gdDemo->Cells[1][r] = IntToStr(r+1);
	}
}
//---------------------------------------------------------------------------


Компиляция



Компиляция проходит весьма неспешно — по своему обыкновению C++ Builder делает это как-то натужно. Всё же, долгие годы не сделали их компилятор C++ ни чуть не быстрее.

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

Переключения платформы осуществляется без особых усилий — в IDE этот аспект интерфейса сделан нарочито и бескомпромиссно. Вы должны выбрать: Debug или Release компиляцию, целевую платформу, симулятор или устройство, и отдельно пометить осуществляется ли сборка для внутренних нужд или для публикации. В последнем случае от вас потребуются сертификаты для подписывания. Сертификаты Android, если у вас их еще нет, вам тут же любезно предложат генерировать прямо из среды разработки; ну, а iOS профили должны стоять на том Mac, где будет выполняться заключительный этап сборки.

Легко видеть, что в разделе Android перечислены все симуляторы, настроенные в Android SDK, а так же все подключенные устройства.

В разделе iOS опции в точности повторяют набор из XCode — это и не удивительно, учитывая, что сборка и запуск симулятора будут выполнены на удаленной машине Mac OS.



Слева показано, как выглядит приложения на основных мобильных платформах.

Как нетрудно заметить — и это отрадно — внешний вид почти не изменился, точнее, напротив: приложение непостижимым образом изменилось, но выглядит оно теперь точно так же, как если бы мы делали его интерфейс с нуля для каждой из платформ. В этом и состоит тот соблазн, ради которого мы хотели проверить FMX. Походит на восторг от первого использования Qt!

Видно, что это по-прежнему то же самое приложение, но все элементы управления сменились на «родные» для каждой из платформ. Именно это, по нашему мнению, и можно было бы назвать подлинно кросс-платформенной разработкой GUI приложений.

Мобильное приложение уже готово! Предлагаем вам посмотреть на его работу в живую на примере экранного видео, сделанного на физическом Android устройстве (HTC One). Видео почти идентичны, мы сделали два ролика для статистики.

На видео заметны некоторые аспекты работы нашего приложения.
  1. Время запуска. Считается, что все приложения на Android-e запускаются не очень быстро, если мы говорим о «холодном» запуске. Здесь же прекрасно видно, что мы теряем около 2 секунд на старте (черный экран в самом начале видео). Много это или нет — решать Вам, но, по нашему мнению, это сильно зависит от типа приложения.
  2. Скорость работы. Тут особых нареканий нет — интерфейс работает вполне ладно.
  3. Элементы управления. Все элементы заменены на нативные и производят вполне Андройдовское впечатление.
  4. Grid. Выглядит интересно для мобильной платформы и, вполне, рабочий — есть даже inplace редактирование ячеек.


Post-mortem



Давайте посмотрим, что собой представляет изнутри наше свежесобранное приложение Android.

APK архив имеет весьма ощутимый размер в 6 Мб. Видимо, по старой традиции Delphi, в него затянули всю runtime библиотеку.

Внутри APK архива мы видим следующую структуру папок (показано справа). В глаза бросается наличие динамических библиотек (so), как бы намекающее нам на то, для чего именно использовался родной компилятор ARMv7 и NDK.

Обратим внимание на то, что папка lib содержит вложенные папки с названием архитектуры, и в каждой из них лежит наше приложение, названное отчего-то libProject1.so. Так вот, только в папке armeabi-v7a оно настоящее, и имеет размер порядка 21 Мб (в распакованном виде). Остальные же файлы библиотек представляют собой готовые хлопушки-заглушки, которые выстреливают в лицо пользователю сообщением, если его архитектура отличается от ARMv7. В этом производитель честно признается и не оставляет нам пока ничего иного.

Файл classes.dex содержит совсем не наше приложение, а Java загрузчик для основного FMX приложения-библиотеки и реализацию оберток для нативных элементов управления Android. Именно этот фрагмент и позволяет приложению взаимодействовать с ОС и «прикидываться» обычным приложением Android.

Степень нативности


Как становится заметным на видео, эффекты FMX продолжают прекрасно действовать и на «родные» элементы управления Android, вмешиваясь в их отрисовку (например, мы даже включали свечение контуров у элементов управления, а это означает, что FMX работает с Android элементами управления не просто как с картинками, а очень даже плотно).

Себастьян Гингтер (SEBASTIAN P.R. GINGTER) в своей широко известной статье по FMX отзывается о фреймворке очень нелестно, критикуя, как раз, то, что пользовательский интерфейс рисуется независимым образом и не выглядит нативно ни на одной из платформ. По всей видимости, в какой-то момент, это было именно так, но сейчас такую критику нельзя считать справедливой. Автор отрицает саму идею кроссплатформенных GUI приложений, без оглядки на конкретные реализации, отрицая потенциальные преимущества такого подхода.

Заключение


Рассмотренный инструмент, безусловно, является продолжателем всех традиций VCL: славных и бесславных. Мы убедились в том, что технология сборки по-настоящему кросплатформенных мобильных приложений работает и показывает очень хорошую производительность. Для определенного класса приложений FMX будет хорошим подспорьем.

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

Использованные материалы:


  1. Документация Embarcadero
  2. Описание процесса разработки в FM
  3. ARM заглушки в XE6
  4. Критика не нативного интерфейса
+11
29.7k 102
Comments 10
Top of the day