Slide 1

Slide 1 text

How Swift runs on Android ~ Swift SDK for Android & KMP ~ STORES, Inc. • Yu Takahashi 2026/09/02 DroidKaigi 2026

Slide 2

Slide 2 text

Introduction Yu Takahashi Software Engineer at STORES, inc. Languages • Primary: Swift • Also : Kotlin, Ruby, TypeScript… My fun • Travel • Natural language (not programming) How Swift runs on Android X: @yutk_941 GitHub: @taka-2120 2 / 60

Slide 3

Slide 3 text

Agenda 1. How did Swift arrive on Android? 2. What does Swift SDK for Android provide? 3. How does Swift run on Android? 4. How is memory managed across both runtimes? 5. What is different from KMP? 6. What is it like to write? How Swift runs on Android 3 / 60

Slide 4

Slide 4 text

Agenda 1. How did Swift arrive on Android? 2. What does Swift SDK for Android provide? 3. How does Swift run on Android? 4. How is memory managed across both runtimes? 5. What is different from KMP? 6. What is it like to write? How Swift runs on Android 4 / 60

Slide 5

Slide 5 text

1. How did Swift arrive on Android? Choices • Flutter (Dart) • Kotlin lovers • KMP - Shares logic • CMP - Shares UI • Frontend lovers • React Native (JavaScript / TypeScript) How Swift runs on Android 5 / 60

Slide 6

Slide 6 text

1. How did Swift arrive on Android? What about Swift…? How Swift runs on Android 6 / 60

Slide 7

Slide 7 text

1. How did Swift arrive on Android? Swift is not only for Apple platform • Linux (since 2015) • Windows (since 2020) • Embedded (since 2024) • Java (since 2024) * Officially announced How Swift runs on Android 7 / 60

Slide 8

Slide 8 text

1. How did Swift arrive on Android? Skip (since 2024) Build Android apps with “Swift” Open-sourced: January 2026 Variations: Lite / Fuse How Swift runs on Android 8 / 60

Slide 9

Slide 9 text

1. How did Swift arrive on Android? Skip Lite Write logic with “Swift” = Write Kotlin code like Swift (a.k.a. Kotlish) Regulations • Most third-party packages cannot be used • Does not accept implementation that has no Kotlin equivalent How Swift runs on Android 9 / 60

Slide 10

Slide 10 text

1. How did Swift arrive on Android? Skip Fuse Write logic & UI with SwiftUI • Logic • Native compile • UI • Transpile Swift to Kotlin • SwiftUI on Jetpack Compose How Swift runs on Android 10 / 60

Slide 11

Slide 11 text

1. How did Swift arrive on Android? Language \ Shares Logic only Swift Skip (Lite) Kotlin KMP UI only Both Skip (Fuse) CMP Flutter Other React Native How Swift runs on Android 11 / 60

Slide 12

Slide 12 text

1. How did Swift arrive on Android? Android toolchains already existed • finagolfin / swift-android-sdk • Led Swift-on-Android as an individual for years • Became the basis of today s Swift SDK for Android • Many other community toolchains ’ How Swift runs on Android 12 / 60

Slide 13

Slide 13 text

1. How did Swift arrive on Android? 2025/02 • Swift on Android Community Working Group formed • Kicked off by the Skip team to unify scattered toolchains 2025/06 • Approved as an official Swift Android Workgroup 2026/03 • Swift 6.3 ships the first official Swift SDK for Android How Swift runs on Android 13 / 60

Slide 14

Slide 14 text

Agenda 1. How did Swift arrive on Android? 2. What does Swift SDK for Android provide? 3. How does Swift run on Android? 4. How is memory managed across both runtimes? 5. What is different from KMP? 6. What is it like to write? How Swift runs on Android 14 / 60

Slide 15

Slide 15 text

2. What does Swift SDK for Android provide? Details • The SDK officially released in Swift 6.3 • Share code with • SPM dependency for iOS • Maven or project dependency for Android • Over 25% of Swift Packages can be built for Android (As of Oct 2025) How Swift runs on Android 15 / 60

Slide 16

Slide 16 text

2. What does Swift SDK for Android provide? What can do • Working on iOS and Android • Sharing business logic What cannot do • Sharing UI related code • Using Apple platform or UI related libraries How Swift runs on Android 16 / 60

Slide 17

Slide 17 text

2. What does Swift SDK for Android provide? Language \ Shares Logic only UI only Both Skip (Lite) Swift Kotlin Skip (Fuse) Swift SDK for Android KMP CMP Flutter Other React Native How Swift runs on Android 17 / 60

Slide 18

Slide 18 text

2. What does Swift SDK for Android provide? Roles • Link NDK on cross-compiling Swift code • Share pre-built Swift runtime files So the compiler can emit a shared object (.so) to work on Android via JNI How Swift runs on Android Native Development Kit (NDK) Build C/C++ native code for Android Java Native Interface (JNI) Kotlin / Java call C/C++ native code for Android 18 / 60

Slide 19

Slide 19 text

2. What does Swift SDK for Android provide? Why are they required? • NDK • Provides Android s C library, headers and sysroot • The Swift compiler needs them to emit Android binaries • Swift Runtime • Android has nothing that can run Swift code ’ How Swift runs on Android 19 / 60

Slide 20

Slide 20 text

2. What does Swift SDK for Android provide? Swift source code Swift SDK for Android Swift compiler Build .so for Android How Swift runs on Android 20 / 60

Slide 21

Slide 21 text

2. What does Swift SDK for Android provide? NDK Swift source code Swift SDK for Android Symbolic link to NDK Swift compiler Built Swift runtime Build .so for Android How Swift runs on Android 21 / 60

Slide 22

Slide 22 text

2. What does Swift SDK for Android provide? SDK structure swift-android/ ├── scripts/ a shell script to setup ├── swift-resources/usr/ │ └── lib/ │ ├── swift-{arch}/ dynamic runtime (.so) │ ├── swift-static-{arch}/ static runtime (.a) │ … ├── swift-sdk.json resolves paths from triple └── swift-toolset.json compiler options How Swift runs on Android 22 / 60

Slide 23

Slide 23 text

Agenda 1. How did Swift arrive on Android? 2. What does Swift SDK for Android provide? 3.How does Swift run on Android? 4. How is memory managed across both runtimes? 5. What is different from KMP? 6. What is it like to write? How Swift runs on Android 23 / 60

Slide 24

Slide 24 text

4. How does Swift run on Android? Compile Build time Source code JVM bytecode DEX bytecode APK ART Runtime How Swift runs on Android 24 / 60

Slide 25

Slide 25 text

4. How does Swift run on Android? Swift code swift build Swift SDK for Android Swift .so Runtime Build time APK ART Runtime How Swift runs on Android 25 / 60

Slide 26

Slide 26 text

4. How does Swift run on Android? Cross-compile your SPM package swift build --swift-sdk aarch64-unknown-linux-android28 Target triple: ---android arch : one build per supported ABI vendor : unknown on Android (apple on Apple platforms) os : linux (macosx14.0 for Mac) api_level: Equivalent to minSdkVersion → Resolve Swift runtime & NDK paths by swift-sdk.json How Swift runs on Android 26 / 60

Slide 27

Slide 27 text

4. How does Swift run on Android? How to call Swift from Kotlin / Java? jextract in swift-java • Call Swift from Kotlin / Java • Analyze Swift code • Generates Swift wrapper for JNI & Java caller code • Named after OpenJDK s jextract (C → Java) ’ How Swift runs on Android 27 / 60

Slide 28

Slide 28 text

4. How does Swift run on Android? Original Swift code public func myFunc(name: String = "Swift") -> String { "Hello, \(name)!" } How Swift runs on Android 28 / 60

Slide 29

Slide 29 text

4. How does Swift run on Android? jextract generated Swift code for JNI @_cdecl("Java_yutakahashi_TestPackage_TestTarget__00024myFunc__Ljava_lang_String_2") public func Java_yutakahashi_TestPackage_TestTarget__00024myFunc__Ljava_lang_String_2( environment: UnsafeMutablePointer!, thisClass: jclass, Just wrapping the name: jstring? original function ) -> jstring? { return TestTarget.myFunc(name: String( fromJNI: name, in: environment )).getJNILocalRefValue(in: environment) } How Swift runs on Android 29 / 60

Slide 30

Slide 30 text

4. How does Swift run on Android? jextract generated Java code public final class TestTarget { ... public static java.lang.String myFunc(java.lang.String name) { return TestTarget.$myFunc(name); } } ... Call Swift function in .so How Swift runs on Android 30 / 60

Slide 31

Slide 31 text

4. How does Swift run on Android? Kotlin caller code import yutakahashi.TestPackage.TestTarget val greeting = TestTarget.myFunc(“Kotlin") println(greeting) // “Hello, Kotlin!” How Swift runs on Android 31 / 60

Slide 32

Slide 32 text

4. How does Swift run on Android? Swift code swift build Generated Java Swift SDK for Android Build time Runtime swift-java Runtime Swift .so ART How Swift runs on Android APK 32 / 60

Slide 33

Slide 33 text

Agenda 1. How did Swift arrive on Android? 2. What does Swift SDK for Android provide? 3. How does Swift run on Android? 4.How is memory managed across both runtimes? 5. What is different from KMP? 6. What is it like to write? How Swift runs on Android 33 / 60

Slide 34

Slide 34 text

4. How is memory managed across both runtimes? How does Swift manage memory? • Automatic Reference Counting (ARC) • Counts references & frees on zero • Reference types (class) • One instance = a and b point to the same thing • Managed by ARC • Value types (struct) • Copy on assign = a and b become separate values • Not managed by ARC How Swift runs on Android 34 / 60

Slide 35

Slide 35 text

4. How is memory managed across both runtimes? You might think… "Swift is compiled to native code, so the GC has nothing to do with it.” Not quite. What Kotlin holds is a Java object that lives on the Java heap. Java heap Native heap Calculator Calculator reference Store memory address The actual instance Managed by GC Managed by ARC How Swift runs on Android 35 / 60

Slide 36

Slide 36 text

4. How is memory managed across both runtimes? Solutions Use SwiftArena provided by swift-java to manage the lifetime of objects that cross the boundary How Swift runs on Android 36 / 60

Slide 37

Slide 37 text

4. How is memory managed across both runtimes? SwiftArena.ofConfined() Releases everything at once when the scope exits SwiftArena.ofConfined().use { arena -> HogeClass.init(arena) } // Dispose the class instance How Swift runs on Android 37 / 60

Slide 38

Slide 38 text

4. How is memory managed across both runtimes? SwiftArena.ofAuto() Release automatically determined by Java GC private val arena = SwiftArena.ofAuto() // no explicit closing val hoge: HogeClass = HogeClass.init(arena) fun onTapButton() { val result = hoge.doSomething() println(result) } How Swift runs on Android 38 / 60

Slide 39

Slide 39 text

4. How is memory managed across both runtimes? Exception Calling top-level functions in Swift Why No self. No Swift instance to keep alive. import yutakahashi.TestPackage.TestTarget val greeting = TestTarget.myFunc("Kotlin") How Swift runs on Android 39 / 60

Slide 40

Slide 40 text

4. How is memory managed across both runtimes? Original Swift code public final class Calculator { public init() {} } public func plus(lhs: Int, rhs: Int) -> Int { lhs + rhs } How Swift runs on Android 40 / 60

Slide 41

Slide 41 text

4. How is memory managed across both runtimes? jextract generated Java code public final class Calculator implements JNISwiftInstance { ... public static Calculator init(SwiftArena swiftArena) { return Calculator.wrapMemoryAddressUnsafe(Calculator.$init(), swiftArena); } } public long plus(long lhs, long rhs) throws SwiftIntegerOverflowException { return Calculator.$plus(lhs, rhs, this.$memoryAddress()); } private static native long $plus(long lhs, long rhs, long selfPointer); ... How Swift runs on Android 41 / 60

Slide 42

Slide 42 text

4. How is memory managed across both runtimes? Kotlin caller code import yutakahashi.TestPackage.Calculator import org.swift.swiftkit.core.SwiftArena SwiftArena.ofConfined().use { arena -> val calculator = Calculator.init(arena) val result = calculator.plus(1L, 2L) println(result) } How Swift runs on Android 42 / 60

Slide 43

Slide 43 text

Agenda 1. How did Swift arrive on Android? 2. What does Swift SDK for Android provide? 3. How does Swift run on Android? 4. How is memory managed across both runtimes? 5.What is different from KMP? 6. What is it like to write? How Swift runs on Android 43 / 60

Slide 44

Slide 44 text

5. What is different from KMP? Comparison KMP Swift SDK for Android Shared code Kotlin in shared module Swift in an SPM package Android side Kotlin, compiled with the app .so, called through JNI iOS side a framework, called through Obj-C Swift, compiled with the app App projects Generated by the template Prepared by yourself How Swift runs on Android 44 / 60

Slide 45

Slide 45 text

5. What is different from KMP? Decision criteria KMP Swift SDK for Android Already have an Android app an iOS app Sharing UI Possible with CMP Not possible Maturity Since 2023 Since 2026 APK size Minimal approx. + 80 MB How Swift runs on Android 45 / 60

Slide 46

Slide 46 text

5. What is different from KMP? Decision criteria How Swift runs on Android 46 / 60

Slide 47

Slide 47 text

5. What is different from KMP? Can they coexist? Yes • A KMP project contains Android app and iOS app projects • Add the library dependency into both projects How Swift runs on Android 47 / 60

Slide 48

Slide 48 text

5. What is different from KMP? MyKMPProject/ ├── shared/ ├── androidApp/ │ └── build.gradle.kts └── iosApp/ └── Package.swift + expect class + include(“:MySwiftPackage") + .package(path: "../MySwiftPackage") MySwiftPackage/ └── Sources/ How Swift runs on Android 48 / 60

Slide 49

Slide 49 text

Agenda 1. How did Swift arrive on Android? 2. What does Swift SDK for Android provide? 3. How does Swift run on Android? 4. How is memory managed across both runtimes? 5. What is different from KMP? 6.What is it like to write? How Swift runs on Android 49 / 60

Slide 50

Slide 50 text

6. What is it like to write? Setting up your projects (on local) 1. Make your SPM product .dynamic, so it produces a .so 2. Add gradle.properties and settings.gradle 3. Copy build.gradle from swiftlang/swift-android-examples How Swift runs on Android 50 / 60

Slide 51

Slide 51 text

6. What is it like to write? Setting up your projects 4. Publish swift-java to your local maven repository, because swift-java has not been available in Maven Central yet. ./gradlew --project-dir … :SwiftKitCore:publishToMavenLocal How Swift runs on Android 51 / 60

Slide 52

Slide 52 text

6. What is it like to write? Setting up your projects 5. Setup Android project // settings.gradle.kts include(":TestPackage") project(":TestPackage").projectDir = File(“../TestPackage") // app/build.gradle.kts implementation("org.swift.swiftkit:swiftkit-core:+") implementation(project(":TestPackage")) How Swift runs on Android 52 / 60

Slide 53

Slide 53 text

6. What is it like to write? Setting up your projects If the project is set up successfully, building the Android project triggers a Swift build for each ABI How Swift runs on Android 53 / 60

Slide 54

Slide 54 text

6. What is it like to write? Works fine • Foundation • URL, Date, Data, JSONEncoder / Decoder, etc… • Array, Generics, Concurrency • fatalError(), #if os(Android) How Swift runs on Android 54 / 60

Slide 55

Slide 55 text

6. What is it like to write? Does not work perfectly • Nested arrays of custom types • [[String]] works fine, but a custom one like [[MyStruct]] does not • #if DEBUG • Not wired to the Android build type, so a debug-only path can ship • 3rd party libraries (e.g. Alamofire) • Builds and runs, but OS-dependent features do not How Swift runs on Android 55 / 60

Slide 56

Slide 56 text

6. What is it like to write? public struct User { public let name: String public let age: Int } public func getGroupedUsers() -> [[User]] { [ [ User(name: "Yu Takahashi", age: 23) ], [ User(name: "Taro Droid", age: 23), User(name: "Hanako Swift", age: 23), ], ] } How Swift runs on Android 56 / 60

Slide 57

Slide 57 text

6. What is it like to write? public struct User { public let name: String public let age: Int } public func getGroupedUsers() -> [[User]] { [ [ User(name: "Yu Takahashi", age: 23) ], [ User(name: "Taro Droid", age: 23), JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:103: Assertion User(name: "Hanako with Swift", age: 23), failed: Not synchronized JavaTranslation, User[][] != long[][], ], name=getGroupedUsers ] } [98/101] Generate Java wrappers for Swift types How Swift runs on Android 57 / 60

Slide 58

Slide 58 text

6. What is it like to write? Debugging experience • Most unsupported things fail at Swift build time • Unable to set breakpoints to the Swift code • Logcat does not capture Swift s print() #if os(Android) import Android func print(_ items: Any..., separator: String = " ", terminator: String = "") { let message = items .map { String(describing: $0) } .joined(separator: separator) + terminator __android_log_write(Int32(ANDROID_LOG_DEBUG.rawValue), "Swift", message) } #endif ’ How Swift runs on Android 58 / 60

Slide 59

Slide 59 text

Is it a practical option today? Considerations • swift-java has not covered every Swift type yet • SPM packages may not provide full functions for Android • Outside a monorepo, every shared-logic change needs a tag and two dependency updates Practical use cases • Turning a shared core used by several apps into an SDK • Sharing logic between an iOS and an Android app in one monorepo How Swift runs on Android 59 / 60

Slide 60

Slide 60 text

Wrap up What the SDK does • Links the NDK and ships a prebuilt Swift runtime • That is enough to compile Swift into .so for Android How Kotlin calls it • swift-java generates Java bindings that call the .so through JNI Memory • The GC manages the Java wrapper, ARC manages the Swift instance • SwiftArena decides when the Swift instance is released Compared to KMP • KMP can share UI with CMP, the SDK cannot and UI stays native on both sides • They can coexist, add the Swift package to both projects in a KMP repo • The Swift runtime adds roughly 80 MB to your APK How Swift runs on Android 60 / 60

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

Thank you! X: @yutk_941 DroidKaigi × iOSDC After Night by Cybozu & STORES