Возможно, вы уже знакомы с Skip как с инструментом для переноса ваших Swift-приложений на Android. В Skip используется новый подход к транспиляции, когда мы интегрируемся с системой сборки Xcode для преобразования вашего Swift-кода в Kotlin. Это позволяет нам создавать Android-библиотеку для каждой сборки вашего пакета Swift или запускать Android-версию вашего приложения SwiftUI при каждом запуске Xcode.
Мы уже обсуждали преимущества стратегии, основанной на транспиляции. Но несмотря на то, что Android — это Java/Kotlin-ориентированная платформа, компилированный код также имеет значительные преимущества. Skip уже давно поддерживает интеграцию с кодом на C как на Android, так и на iOS. Логично, что наш транспилированный Swift-код также должен интегрироваться с компилированным Swift-кодом.
И вот мы с радостью объявляем о первом технологическом превью нативного инструментария и драйвера Swift для Android! Этот набор инструментов позволяет разработчикам создавать и запускать исполняемые файлы Swift и тестовые примеры на подключенном устройстве или эмуляторе Android.
Начало работы
На машине с macOS с установленными Xcode и Homebrew вы можете установить инструментарий Swift 5.10 для Android, открыв терминал и выполнив команду:
brew install skiptools/skip/swift-android-toolchain@5.10.1
Это позволит загрузить Swift Android SDK вместе со всеми зависимостями, необходимыми для сборки, запуска и тестирования пакетов Swift на Android.
Если вы уже являетесь пользователем Skip, не забудьте также обновить свою копию:
skip upgrade
Установка эмулятора Android
Если у вас под рукой нет Android-устройства, вам придется установить эмулятор Android, чтобы запускать исполняемые файлы и тестовые примеры в симулированной среде Android. Самый простой способ сделать это — скачать и установить Android Studio, затем запустить ее и открыть «Virtual Device Manager» из меню «More Actions» (или многоточия) в диалоговом окне «Welcome to Android Studio». В открывшемся окне «Device Manager» выберите «Create virtual device».
На экране «Select Hardware» выберите устройство (например, «Pixel 6»), затем на экране «Select a system image» выберите один из рекомендуемых образов (например, «UpsideDownCake», он же API 34), а на следующем экране назовите устройство и выберите «Finish». Когда вы вернетесь на экран «Device Manager», вы увидите новое устройство (например, «Pixel 6 API 34»), которое вы можете запустить с помощью треугольной кнопки воспроизведения. Появится небольшое окно с названием «Android Emulator», и загрузится операционная система.
Запуск «Hello World»на Swift на Android
Теперь, когда вы все настроили и запустили эмулятор Android (или подключили физическое Android-устройство с включенным режимом разработчика), пришло время запустить немного Swift!
Откройте терминал и создайте новый исполняемый Swift-файл для командной строки под названием «HelloSwift»:
% mkdir HelloSwift % cd HelloSwift % swift package init --type=executable Creating executable package: HelloSwift Creating Package.swift Creating Sources/main.shswift
Чтобы убедиться, что программа работает на macOS, запустите ее с помощью стандартной команды swift run:
% swift run HelloSwift Building for debugging... Build of product 'HelloSwift' complete! (1.80s) Hello, world!
А теперь мы соберем и запустим его на эмуляторе (или устройстве) Android с помощью драйвера Swift Android, который мы включили в состав инструмента skip
, установленного вместе со всей цепочкой инструментов:
% skip android run HelloSwift Building for debugging... Build complete! (10.90s) [✓] Check Swift Package (0.68s) [✓] Connecting to Android (0.05s) [✓] Copying executable files (0.25s) Hello, world!
Вуаля! Swift работает на Android. А чтобы доказать, что мы действительно работаем на другом хосте, отредактируйте файл Sources/main.swift
в вашем любимом редакторе (или запустите xed Sources/main.swift
, чтобы отредактировать его в Xcode) и добавьте проверку платформы:
#if os(Android) print("Hello, Android!") #elseif os(macOS) print("Hello, macOS!") #else print("Hello, someone other platform…") #endif
Затем запустите его на macOS и Android:
% swift run HelloSwift Building for debugging... Build of product 'HelloSwift' complete! (0.47s) Hello, macOS! % skip android run HelloSwift Building for debugging... Build complete! (0.89s) [✓] Check Swift Package (0.23s) [✓] Connecting to Android (0.04s) [✓] Copying executable files (0.23s) Hello, Android!
Запуск тестовых примеров Swift на Android
Инструменты командной строки — это, конечно, здорово, но чтобы по-настоящему использовать Swift на Android, мы хотим иметь возможность запускать тестовые наборы. Именно так разработчики, заинтересованные в создании кросс-платформенных фреймворков, смогут проверить — и решить — проблемы в своем Swift-коде, возникающие из-за различий платформ.
К счастью, драйвер skip android
включает в себя не только команду run
, но и команду test
, которая подключается к эмулятору/устройству Android и запускает тестовый набор XCTest точно так же, как это делает swift test
для macOS.
Для демонстрации мы можем запустить набор тестов для пакета swift-algorithms от Apple, чтобы убедиться, что он корректно работает на Android:
% git clone https://github.com/apple/swift-algorithms.git Cloning into 'swift-algorithms'... … Resolving deltas: 100% (1054/1054), done. % cd swift-algorithms % skip android test Fetching https://github.com/apple/swift-numerics.git from cache Fetched https://github.com/apple/swift-numerics.git from cache (0.87s) Computing version for https://github.com/apple/swift-numerics.git Computed https://github.com/apple/swift-numerics.git at 1.0.2 (0.57s) Creating working copy for https://github.com/apple/swift-numerics.git Working copy of https://github.com/apple/swift-numerics.git resolved at 1.0.2 Building for debugging... … [92/93] Linking swift-algorithmsPackageTests.xctest Build complete! (25.91s) [✓] Check Swift Package (0.74s) [✓] Connecting to Android (0.06s) [✓] Copying test files (0.27s) Test Suite 'All tests' started at 2024-09-10 20:24:17.770 Test Suite 'swift-algorithms-C7A0585A-0DC2-4937-869A-8FD5E482398C.xctest' started at 2024-09-10 20:24:17.776 Test Suite 'AdjacentPairsTests' started at 2024-09-10 20:24:17.776 Test Case 'AdjacentPairsTests.testEmptySequence' started at 2024-09-10 20:24:17.776 Test Case 'AdjacentPairsTests.testEmptySequence' passed (0.001 seconds) … Test Case 'WindowsTests.testWindowsSecondAndLast' started at 2024-09-10 20:24:20.480 Test Case 'WindowsTests.testWindowsSecondAndLast' passed (0.0 seconds) Test Suite 'WindowsTests' passed at 2024-09-10 20:24:20.480 Executed 8 tests, with 0 failures (0 unexpected) in 0.004 (0.004) seconds Test Suite 'swift-algorithms-C7A0585A-0DC2-4937-869A-8FD5E482398C.xctest' passed at 2024-09-10 20:24:20.480 Executed 212 tests, with 0 failures (0 unexpected) in 2.702 (2.702) seconds Test Suite 'All tests' passed at 2024-09-10 20:24:20.480 Executed 212 tests, with 0 failures (0 unexpected) in 2.702 (2.702) seconds
Все проходит. Ура!
Не все тесты пакета пройдут так легко: Android основан на Linux — в отличие от Darwin/BSD, на которых построены macOS и iOS, — поэтому в вашем коде могут быть предположения, сделанные для Darwin, которые не будут верны для Linux. Прогон через комплексный набор тестов — лучший способ выявить, а затем устранить эти различия между платформами.
Следующие шаги: cоздание приложения
Исполняемые файлы командной строки и модульные тесты — это все хорошо, но «Hello World» — это не приложение. Чтобы создать настоящее приложение для Android, с доступом к возможностям устройства и графическим пользовательским интерфейсом, вам нужно работать с Android SDK, который написан на Java и Kotlin. А упаковывать и распространять приложение нужно собственным идиоматическим способом Android, с помощью автономных библиотек, встраивающихся в сборку приложения.
Именно здесь вступает в игру интеграция с широкой экосистемой Skip. В следующих частях этой серии мы рассмотрим готовящуюся систему Skip для прозрачного соединения скомпилированного Swift с Java, Kotlin и транслированным Swift, включая существующую в Skip поддержку SwiftUI для Android. Это позволит использовать лучшее из всех миров: транслированный Swift для общения с библиотеками Android, SwiftUI поверх Jetpack Compose, а также бизнес-логику и алгоритмы, реализованные в скомпилированном Swift. Следите за новостями!
Послесловие
Инструментарий Swift для Android — это кульминация многолетних усилий сообщества, в которых мы (команда Skip) сыграли лишь очень небольшую роль.
Еще до появления Swift с открытым исходным кодом люди пытались запустить его на Android, начиная с попытки Ромена Гойе «Running Swift code on Android» в 2015 году, которая позволила скомпилировать и запустить базовый Swift на Android-устройстве. Более практичный пример появился в 2016 году в книге Джорди Джей «How we put an app in the Android Play Store using Swift», где Swift был использован в реальном загружаемом приложении для Android. Затем в 2018 году Readdle опубликовала статью «Swift for Android: Our Experience and Tools» об интеграции Swift в их приложение Spark для Android. Эти статьи дают ценное техническое представление о механике и сложностях, связанных с кросс-компиляцией Swift для новой платформы.
В последние годы сообщество разработчиков Swift предпринимало различные совместные и независимые усилия по созданию пригодной для использования инструментальной цепочки Swift-on-Android. Среди наиболее заметных участников на GitHub — @finagolfin, @vgorloff, @andriydruk, @compnerd и @hyp. Наша работа — лишь часть их неустанных усилий, и мы хотим продолжить сотрудничество с ними в надежде, что Android в конечном итоге станет полностью поддерживаемой платформой для языка Swift.
Заглядывая в будущее, мы с нетерпением ждем финального релиза Swift 6.0, который позволит нам опубликовать инструментарий, поддерживающий все новые замечательные функции параллелизма, а также переделку библиотек Swift Foundation, что даст нам возможность обеспечить лучшую интеграцию между идиомами Foundation (пакеты, ресурсы, пользовательские настройки по умолчанию, уведомления, логирование и т.д.) и стандартными шаблонами Android. Инструментальная цепочка — это только первый шаг в превращении нативного Swift в жизнеспособный инструмент для создания высококачественных приложений для Android, но это важный компонент, который мы очень рады добавить в экосистему Skip.