Using Swift to build… Android apps?
Apple just announced the first preview release of Swift for Android. Does this mean we can finally build mobile apps with only one native language?
On Friday Apple announced the first preview release of Swift for Android, “enabling you to build Android business logic with the same Swift that you use for Apple platforms.”
First off, a big thank you to Marco and everyone else tagged that me. If it wasn’t for them I wouldn’t have even known this existed! 😁
As soon as I saw this I immediately asked the obvious question: Can we use a single native programming language to build cross-platform Hotwire Native apps?
Or, what I really meant: Can we finally stop writing Kotlin?
We already need to learn three language for Hotwire Native apps: Ruby, Swift, and Kotlin. Wouldn’t it be great if we could combine those last two into one?
So let’s explore this new Swift release and see what it can do!
Use cases for Swift on Android
From the currently-being-written vision document:
The potential applications of Swift on Android are diverse and extend beyond simply sharing code between iOS and Android.
Shared Business Logic: A prominent use case is sharing core business logic, algorithms, and data models across iOS and Android applications. This minimizes duplication of effort and ensures consistency in application behavior.
Performance-Critical Modules: Swift’s strong performance characteristics make it ideal for developing performance-sensitive components, such as image processing, audio manipulation, or computationally intensive tasks within an Android app, akin to using C++ via the NDK.
Cross-Platform Libraries and SDKs: Developers can leverage Swift to build libraries and SDKs that can be easily integrated into existing Android (and iOS) applications, providing a consistent API surface across platforms.
Full Native Applications: While requiring significant effort for UI, it’s conceivable to build entire Android applications in Swift, using platform-native UI frameworks for each respective OS.
That last one is most exciting for me. Shared business logic doesn’t really help us in Hotwire Native world - that code already exists in our Rails app! But if we could build entire Android application, UI and all, using Swift… that could be game changing.
Installation
To get started using Swift for Android we first need to install a lot of pieces. Manually.
First, install Swiftly, the Swift environment manager. This is like rbenv for Swift.
Then, following the Swift for Android documentation:
The Host Toolchain: this is the
swiftcommand and related tools that you will use to build and run your Swift code.The Swift SDK for Android: the set of libraries, headers, and other resources needed to generate and run Swift code for the Android target.
The Android NDK: the “Native Development Kit” for Android includes the cross-compilation tools like
clangandldthat are used by the host toolchain to cross-compile and link.
I won’t write out each step here. But a heads up that it requires copy-pasting a fair amount of manual commands, including using cURL directly. I trust Apple but it can’t hurt to run all of this on a second machine or inside a VM. You know, just in case. 😳
Once you have the Android NDK installed we can start looking at some code.
Example apps
Pull down the new swift-android-examples repo. This includes five Android apps that interact with Swift in increasingly complex ways.
The examples start with the usual “Hello World” application, rendering a static string to the screen (left screenshot). From there, hello-swift-callback receives timed events from Swift to render a stopwatch-like interface (right screenshot). Both strings, Hello from Swift ❤️ and 00:00:13 are coming from native Swift code!
To run the apps on an Android emulator or device you’ll need to open the project in Android Studio. Once gradle finishes syncing (it might take a while) you can select the example name from the configuration dropdown and hit Run.
So, how does Android interact with Swift? And where in the world is the Swift code?
hello-swift code
Let’s explore the most basic example, hello-swift. Inside of MainActivity.kt you might notice that this looks a whole lot like a regular Android app. Not a good start, in my opinion. 🫠
There’s a whole lot of Kotlin code in here. In fact, the only thing that even mentions Swift is that stringFromSwift() function in the middle. What’s that?
The external keyword lets the compiler know that this function is not implemented in Kotlin but available somewhere else. In our case, Swift. But where is that code?
By default, Android Studio filters the project to the Android view, only showing Android-related files. Switch over the Project Explorer view from Android to Project at the top to display everything on the filesystem.
Buried deep down in the hello-swift directory we’ll find helloswift.swift. Which is, oh boy, quite the file: 😬
import Android
@_cdecl("Java_org_example_helloswift_MainActivity_stringFromSwift")
public func MainActivity_stringFromSwift(env: UnsafeMutablePointer<JNIEnv?>, clazz: jclass) -> jstring {
let hello = ["Hello", "from", "Swift", "❤️"].joined(separator: " ")
return hello.withCString { ptr in
env.pointee!.pointee.NewStringUTF(env, ptr)!
}
}The @_cdecl decorator at the top is what exposes this function from Swift to Android. stringFromSwift at the end of the string becomes the name of the function that we reference in MainActivity.kt. The beginning of the string is the full package name and where it is referenced.
The function itself uses some scary looking parameter types like UnsafeMutablePointer<JNIEnv?> and then manipulates a pointer. I haven’t used a pointer directly since working in Objective-C!
But if I squint I can sort-of-kind-of see how this returns a string. …right? 😅
But enough code, let’s assess.
So, can we stop writing Kotlin?
Short answer: No. 😭
Right now this release gets us one thing: shared business logic written in Swift. And again, that isn’t really that important for Hotwire Native apps. One major goal is to keep that business logic on our server!
And the way it currently stands, I’d honestly rather write Kotlin than that mess of Swift code I shared above. Yes, I know this will most likely improve so maybe that’s not a fair assessment. But still, woof.
Even the current long term vision doesn’t have a plan for writing cross-platform UIs without bringing in third-party tooling:
The UI for Swift on Android applications will primarily rely on Android’s native UI frameworks or existing cross-platform solutions. This means developers will likely choose from:
Jetpack Compose: Android’s modern, declarative UI toolkit in Kotlin. Swift applications could interact with Compose through robust bridging layers.
Android Views (XML-based): The traditional imperative UI system.
Third-Party Cross-Platform UI Frameworks: Such as Flutter (with Swift as the business logic language via FlutterSwift) or potentially others that offer C/C++ interop, which Swift can leverage.
Bridging Solutions: Tools like Skip.tools demonstrate how SwiftUI-like code can be transformed and rendered using Jetpack Compose on Android, offering a path to “native-feeling” cross-platform UI.
Longer answer: Not yet? 🤞
I won’t be adopting Swift for Android in my projects any time soon. But I can start to see a world where we are writing less native platform-specific code and sharing a single package between our apps. I’m thinking native authentication flows or in-app purchase logic.
The biggest win for Hotwire Native developers might be converting the underlying framework code to a single language. Ideally, that could help keep the two platforms feature-aligned and simplify development for maintainers like myself.
But to be honest, if we’re going to do either of those then Kotlin Multiplatform is probably a better choice. It’s been around for a while and is way more stable than Swift for Android is right now. 🤷♂️
What I really want is Ruby Motion to come back!
Have you tried any cross-platform tools? How’d it go? Leave a comment below!





