Swift for Android: Our Experience and Tools
Early last week, we launched Spark for Teams — a revolutionary email client that’s changing the way teams use email. Spark is still an phenomenal email for personal use because it shows what’s important in your inbox.
Spark is one of the most popular email apps available for Free on iPhone, iPad, Mac, as well as Apple Watch. For the millions of users on the Android platform, the time when Spark helps you love your email isn’t very far. In the meantime, we want to share with you an incredible new toolchain we’ve created that takes the pain and hassles out of working with Swift for Android. This toolchain helps dev teams utilize the code they’ve written for the iOS or Mac platforms to create great Android applications.
The Apple Swift compiler has had the ability to compile code for the Android platform for a few years now, but it hasn’t made many friends in the developer community owing to its complexity. Our toolchain was designed to solve this problem by taking the complexity and headaches out of the process, so you can focus on building great apps for your users.
When we started working on the development of the Android version of Spark, we were looking for a cross-platform language that could be used for both Android & iOS development and would also be easy to migrate from our existing Objective-C codebase.
It was around this time that Swift became an open-source project and after a short while, it also got the ability to compile code for the Android platform. We explored our options and it was pretty obvious to us that we should move in that direction.
Swift Android Compiler
How does Swift Android Compiler work?
The answer to that is simple: Low-Level Virtual Machine.
The LLVM is a compiler infrastructure that is based on the concepts of three-phase design with re-targetability. In simple terms, this means that any language that has a front-end LLVM compiler can be compiled for any target that has a LLVM backend compiler.
Google already makes use of LLVM compilers for native Android development with C/C++. That’s why, from an Android device perspective, there is no difference in libraries compiled from C/C++ or Swift code. Moreover, it’s actually better for developers, because they can re-use most of the instruments that were created for C/C++ development — Android profiling tools or an Android low-level debugger (with a limitation on an evaluation of swift code).
What frameworks are available?
Well…there aren’t many. We only have access to SwiftCore, Dispatch, and SwiftFoundation in our toolchain. SwiftCore and Dispatch are largely identical to iOS and Mac versions. But SwiftFoundation on the other hand is not the same Foundation that Apple uses for its own platforms; it’s a re-implementation of all classes from the original library. That’s why SwiftFoundation is still missing some features, but it covers all basic needs such as performing network requests, parsing JSON/XML, storing data on disk, etc.
Obviously UIKit or any high level frameworks are not available, so your Swift app for iOS cannot magically run on Android — you can use Swift for business logic code, but you will have to re-write all user interface and OS dependent parts specifically for Android.
What are the limitations of the Swift Android Compiler?
- At the moment, the Swift compiler only supports the ARM-v7A Android platform.
- Minimum version of Android supported is v5.0 (Lollipop).
- And one of the most significant limitations is the generation 32MB+ APK files, because build should include SwiftCode, SwiftFoundation, and libDispatch.
Introducing the Swift Android Toolchain
One of the biggest hurdles in using Swift compiler for Android is the lack of official support from Apple, which means no continuous integrations or no official builds. We realized that we could optimize the many of the hassles present in developing in Swift for Android and at the same time, improve the experience for our developers in this area. We wanted to avoid all the headaches that Android developers typically have to suffer when working with these tools.
That’s why we have the Swift Android Toolchain — a collection of tools that gives Android developers the ability to use Swift in their projects comfortably and without any hassles. It is an open-source project based on Apple Swift compiler and SwiftJava and SwiftAndroid projects. You can download the toolchain directly from Bintray (Mac only) or compile on your own from GitHub.
We’re currently using forked version of Swift. Our fork contains option to disable @objc and dynamic features in compiler because it doesn’t work properly on non-Darwin platforms. It also contains some minor fixes. We’re working on being able to use official Swift repository in future.
Furthermore, we use Swift Package Manager (SPM) as the build system for Swift. It is the build system that Apple uses in the compiler and others Swift libraries. This tool provides the ability to connect dependencies, compile code, link artifacts (dynamic libraries or executables) and run tests. Along with our toolchain, we provide scripts for SPM that will automate all processes of development and testing Android apps.
Gradle plugin
Of course, it’s great to build Swift code from the command line, but it’s simply more natural for Android developers to use the Android Studio IDE. Fortunately, the Android IDE uses a very flexible build system called ‘Gradle’.
We created a Gradle plugin for adding a Swift compilation build step. It gives us the ability to build mixed Swift/Java/Kotlin projects with just one button.
JVM interoperability
All Android applications run in the Java Virtual Machine. In case any developer prefers native code (C/C++), they must load the library inside an app and interact with it via the Java Native Interface (JNI). Swift is no exception. Thus, for using Swift code in JVM, we should load the libraries and write a JNI bridge.
It’s entirely up to you what JVM language (Java or Kotlin) you use and how you write the bridging code, but we recommend you take a look at our Swift Annotation Processor that generates all JNI code from the Java classes and interfaces.
Blueprint project
The Android team at Readdle has created a sample Swift application for trying out the Swift Android Toolchain in action. If you want to try Swift for Android, this is an excellent project to start with. The Blueprint project is a simple to-do app with business logic written in Swift, while the UI was done in Java.
Testing
The Swift project already includes a testing framework called XCTest and it can already be used for testing Swift code on Android platform. The Swift Package Manager allows compiling tests in one fat binary executable; after that, developers can upload binary executable on Android devices and run it via the Android shell.
BONUS: Our toolchain automates all stages of this testing process. And the Blueprint project includes few simple tests for you to try.
What’s next?
We still have a lot to do for Swift toolchain:
- ARM64 compiler (tentative deadline: August 2019)
- X86, X86_64 compiler (Chromebooks support)
- LLDB with Swift support: client and server
We hope that our Swift Android Toolchain will help you in making your development process easy and hassle-free. The Swift language has been evolving greatly over the last couple of years and developers who already code for the iOS and Mac platforms using Swift can now easily have Android on their radar too.
Sources
- Getting Started with Swift on Android https://github.com/apple/swift/blob/master/docs/Android.md
- The Architecture of Open Source Applications: LLVM http://www.aosabook.org/en/llvm.html
- Swift Android Toolchain https://github.com/readdle/swift-android-toolchain
- Swift Android Buildtools https://github.com/readdle/swift-android-buildtools
- Gradle plugin for building Swift code for Android https://github.com/readdle/swift-android-gradle
- Swift Java Code generation annotation processor https://github.com/readdle/swift-java-codegen
- Swift Android Blueprint project https://github.com/readdle/swift-android-architecture