years • Community-led, not Apple-driven. • No official Android SDK for Swift exists. • Patches have to be applied on every official Swift Release to keep it compiling.
project. • Allows you to write Android apps and libraries in Swift. • No compromise solution for iOS apps. • Not the only Swift-on-Android toolchain out there! Skip.tools
compatible. • Relies on Swift Concurrency: • No Combine or RxSwift • No GCD • No OperationQueue • Good candidate for Skip ’ s Compiled-mode Starting Point For Naturitas.app
URL(string: "https://www.apple.com/iphone/")! let urlRequest = URLRequest(url: url) let _ = try await URLSession.shared.data(for: urlRequest) } Build for Android Open Source Foundation
throws { let url = URL(string: "https://www.apple.com/iphone/")! let urlRequest = URLRequest(url: url) let _ = try await URLSession.shared.data(for: urlRequest) } Build for Android Open Source Foundation
compile. • But runtime behavior of some classes is not guaranteed to be the same. • For example: UserDefaults does not persist it ’ s values. • Skip has Open Source packages to fill in the gaps. • Enter: Skip Fuse
code from Kotlin in Android Studio, we must first create JNI bindings. • WTF is JNI? • “It allows Java code that runs inside a Java Virtual Machine (VM) to interoperate with applications and libraries written in other programming languages”
• Installs the basic Android toolchain: • Java + Gradle • Android SDK • Emulators • Not AppKit-based, but Swing-Java based. • If you like “Mac-assed” apps, you ’ ll hate it. Everyone ’ s favorite IDE
somewhere where the Android codebase can reference it. • You can use: • Custom Maven repository • Github Packages • Merge the iOS and Android repositories • Storing .aars with Git LFS Let ’ s import the .aars
And use the code! class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { … } } }
And use the code! class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) skip.foundation.ProcessInfo.launch(this) enableEdgeToEdge() setContent { … } } }
from Kotlin! And use the code! import naturitas.core.AuthenticationManager val authManager = AuthenticationManager.create( apiClient = UserAPIClient.create(environment), socialNetworkTokenProvider = TokenRefresher() )
Anything can throw so nothing throws. • Remember to try catch when the Swift code you ’ re calling can throw. • Add logging. A LOT. • You can ’ t add breakpoints inside any precompiled code; and your Swift Packages are integrated like that. Some tips
App ’ s Binary. • Iterate cycle depends on re-exporting the Swift codebase, which is slow. • Cultural friction. • Android Developers will complain. • It helped us the fact that I could put my thumb in the scale and make executive decisions. Tradeoffs
usual errors where reported. • Based on libCURL • Not visible on Android Studio network debugger • We replaced it for an OKHTTP-based wrapper. Found issues
layer by layer the Naturitas app. • Replacing Kotlin-based subsystems by Swift-based subsystems. • Deeplinks, Push Notifications, Authentication and Remote Config ✅ • Networking and Data Validation ⏳ • Cart and Checkout ⏭ End result
is seamless across the IDE. • Collaborate with Google to minimize any binary size overhead when adding Swift to Android projects. • Keep investing in Swift-Java to make it the de- facto way to interoperate with JVM languages.