Разработка библиотеки для IOS/Android на Golang

6bd4e96d462f4fbb8fbe4331fbda8ab5.png

Кроссплатформенная разработка мобильных приложений была очень популярна в свое время. Данный подход использовали большинство компаний во время становления мобильной отрасли. Основные причины задействовать кроссплатформенную разработку были просты — отсутствие профессиональных кадров на рынке, скорость и стоимость разработки. К сожалению, в большинстве случаев, данный подход не оправдал себя.

Но почему бы не дать ему второй шанс? Технологии шагнули вперед и теоретически мы можем получить очень качественный продукт. В данной статье мы рассмотрим на практике как разработать библиотеку для IOS/Android на языке Golang и посмотрим с какими ограничениями и проблемами мы столкнулись в процессе разработки.
Наша основная задача разработать SDK для сборки логов и крашей с мобильных приложений, при этом SDK должно подключаться и работать и с Android и с iOS приложениями. В тоже время библиотека должна взаимодействовать с основным сервисом LogPacker, который агрегирует и анализирует данные.

Мы решили использовать новые возможности языка Go для создания кроссплатформенной библиотеки. Во-первых, наше основное приложение написано на Go, и для нас было проще использовать данный язык и не привлекать Java/Objective-C разработчиков. Во-вторых, мы сэкономили время на разработку и попробовали старый подход с новыми возможностями.

Что такое gomobile?


Проект gomobile предоставляет разработчикам инструменты для сборки кода под мобильные платформы Android и iOS.

Сейчас существуют два способа интеграции Go в мобильную среду:

  • Написание полноценного Go-приложения без UI.
  • Генерация Java/Objective-C/Swift кода из Go.


Данная функция поддерживается начиная с Golang версии 1.5. Новая утилита gomobile помогает компилировать Go в мобильные приложения или собирать Java/Objective-C/Swift код.

Для начала выберем один из способов реализации. Первый способ нам не подходит из-за постановки задачи — нам нужна небольшая библиотека, а не отдельное приложение. Хотя способ очень интересный и перспективный благодаря скорости работы go приложений и минимизации потребления ресурсов мобильных устройств.
Мы выберем второй способ, и cгенерируем Java/Objective-C/Swift код из Go.

Настройка окружения


Для начала подготовим окружение для разработки. Нам нужен Go версии 1.5 или выше (чем выше — тем лучше, Go-сообщество вносит постоянные улучшения в Go Mobile).

Далее устанавливаем утилиту gomobile и библиотеку Android SDK. Начнем с установки gomobile:

go get golang.org/x/mobile/cmd/gomobile


Примечание: На OS X необходимо иметь установленный Xcode Command Line Tools.

Далее инициализируем gomobile, это может быть сделано один раз в любой рабочей директории:

gomobile init


Примечание: эта команда может занять несколько минут.

Для сборки Java-кода нам необходим Android SDK и установленная Java (OpenJDK достаточно).

Скачаем и распакуем Android SDK в домашнюю директорию, например ~/android-sdk, и выполним следующую команду для установки API версий:

~/android-sdk/tools/android sdk


Далее установите переменную окружающей среды:

export ANDROID_HOME=$HOME"/android-sdk"


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

Общий Go-код для Android и iOS


Один и тот же код может быть использован для дальнейшей компиляции под Android и iOS. Написание такого кроссплатформенного Go-кода имеет свои ограничения. В настоящее время мы можем использовать только некоторый набор типов данных. Разрабатывая приложение на Go, это необходимо учитывать. Рассмотрим более подробно поддерживаемые типы:

  • int и float;
  • string и boolean;
  • byte[]. Текущая реализация не позволяет использовать []byte в качестве аргумента функции (https://golang.org/issues/12113);
  • функция должна возвращать только поддерживаемые типы, может не возвращать результат, возвращать один тип или два типа, при том, что второй тип должен быть обязательно error;
  • интерфейсы могут быть использованы, если при экспорте они будут использовать поддерживаемый тип;
  • тип struct, только когда все поля соответствуют ограничениям.


Поэтому если тип не поддерживается командой gomobile bind, вы увидите подобную ошибку:

panic: unsupported basic seqType: uint64


Бесспорно набор поддерживаемых типов сильно ограничен, но для реализации нашего SDK этого вполне достаточно.

Сборка и импорт в Java/Objective-C/Swift


Gobind генерирует эквивалентный Go-коду код Java, Objective-C или Swift. К сожалению, gomobile не работает для Windows Phone и это нужно учитывать на этапе планирования.

Обычно gobind не используется напрямую, вместо этого код генерируется автоматически и оборачивается в пакет командой `gomobile bind`. Более подробно это описано тут golang.org/x/mobile/cmd/gomobile.

Рассмотрим некоторые команды и особенности процесса компиляции для каждой платформы.

Начнем с флага -target, который определяет платформу для генерации. Пример для Android:

gomobile bind --target=android .


Эта команда сгенерирует из текущего кода .aar файл. Импортировать данный файл в Android Studio очень просто:

  • File > New > New Module > Import .JAR or .AAR package
  • File > Project Structure > app → Dependencies → Add Module Dependency
  • Добавить импорт: import go.logpackermobilesdk.Logpackermobilesdk

91947b3371cf4658978a92e1f9a2ba51.png

6fcd3c12157a476b8d4cff0066f4522b.png

Примечание: В Java название пакета для импорта всегда начинается с go.

Похожая команда используется для сборки Objective-C/Swift кода:

gomobile bind --target=ios .


Будет создана папка .framework в текущей директории.

Это работает как для Objective-C так и для Swift. Переместите .framework папку в файловый браузер Xcode и добавьте импорт в проект:

#import "Logpackermobilesdk/Logpackermobilesdk.h"


ca8c1377d82c4aa4addaecefa0118ac0.png

Примечание: Go позволяет создавать не только SDK, но и компилировать само приложение в apk/ipa файлы из main.go файла, правда без поддержки нативного мобильного UI. Бесспорно это является очень интересным экспериментом Go-сообщества.

Использование подключенных пакетов


Gomobile bind автоматически создает функции getSomething (), setSomething (). Также все экспортируемые функции будут доступны публично.

Для примера использование нашей библиотеки в Android Studio:

import go.logpackermobilesdk.Logpackermobilesdk;
// ...
try {
    client = Logpackermobilesdk.NewClient("https://logpacker.mywebsite.com", "dev", android.os.Build.MODEL);

    msg = client.NewMessage();
    msg.setMessage("Crash is here!");
    // Use another optional setters for msg object

    client.Send(msg); // Send will return Cluster response
} catch (Exception e) {
    // Cannot connect to Cluster or validation error
}


Она же для Objective-C:

#import "ViewController.h"
#import "Logpackermobilesdk/Logpackermobilesdk.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    GoLogpackermobilesdkClient *client;
    NSError *error;
    GoLogpackermobilesdkNewClient(@"https://logpacker.mywebsite.com", @"dev", [[UIDevice currentDevice] systemVersion], &client, &error);
    GoLogpackermobilesdkMessage *msg;
    msg = client.newMessage;
    msg.message = @"Crash is here!";
    // Use another optional setters for msg object
    GoLogpackermobilesdkResult *result;
    [client send:(msg) ret0_:(&result) error:(&error)];
}


Как видно из примеров выше, в итоге мы получили стандартные библиотеки. Конфигурация библиотек в приложении предельна проста и знакома разработчикам.

Заключение


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

  • Минимальные ресурсы на разработку.
  • Скорость разработки.
  • Простая поддержка решения в дальнейшем.


Минусом является то, что мы не смогли собрать библиотеку под Windows Phone, но об этом мы знали заранее.
Мы надеемся, что в скором времени появится простой способ написания полноценных приложений и SDK на языке Golang.

Вы можете ознакомиться с нашими наработками, склонировав наш репозиторий.

© Habrahabr.ru