Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ build/
local.properties
jniLibs

# generated documentation from swift package generate-documentation
docs/

# Kotlin Gradle plugin data
# See https://kotlinlang.org/docs/whatsnew20.html#new-directory-for-kotlin-data-in-gradle-projects
.kotlin/
Expand Down
16 changes: 16 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// swift-tools-version: 6.0

import PackageDescription

let package = Package(
name: "swift-android-examples",
products: [
.library(name: "SwiftAndroid", targets: ["SwiftAndroid"])
],
dependencies: [
.package(
url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0")
],
targets: [
.target(name: "SwiftAndroid")
])
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,14 @@ Examples using raw JNI, without generated bridging sources:
- **[hello-swift-raw-jni](hello-swift-raw-jni/)** - basic Swift integration that calls a Swift function.
- **[hello-swift-raw-jni-callback](hello-swift-raw-jni-callback/)** - demonstrates bidirectional communication with Swift timer callbacks updating Android UI.
- **[hello-swift-raw-jni-library](hello-swift-raw-jni-library/)** - shows how to package Swift code as a reusable Android library component.

## Documentation

The `Sources/SwiftAndroid/Documentation.docc` directory contains a DocC documentation catalog for Swift on Android. To build and preview it locally:

```shell
swift package generate-documentation --target SwiftAndroid --transform-for-static-hosting --output-path docs
python3 -m http.server 8000 --directory docs
```

Then open <http://localhost:8000/documentation/swiftandroid> in your browser.
45 changes: 45 additions & 0 deletions Sources/SwiftAndroid/Documentation.docc/BuildingForAndroid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Building for Android

Cross-compile Swift code and package it into Android applications

## Overview

Swift on Android uses cross-compilation: you build on a macOS or Linux host, and the compiler produces native ARM or x86_64 binaries targeting Android.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or Windows


```shell
$ swift build --swift-sdk aarch64-unknown-linux-android28

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope to get this changed to --swift-sdk swift-6.3.2-RELEASE_android --triple aarch64-unknown-linux-android28 soon.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that WIP somewhere? That would be a great improvement, and will be relevant for all the SDKs going forward.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in trunk now, 😄 trying to get it into 6.3 here, swiftlang/swift-package-manager#9998.

```

## Conditional compilation

Use `#if os(Android)` to conditionalize code for Android:

```swift
#if os(Android)
import Android
#elseif canImport(Darwin)
import Darwin
#endif
```

## Foundation

Foundation networking types require a separate import on non-Apple platforms:

```swift
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
```

## JNI integration

Export Swift functions for JNI using `@_cdecl`:

```swift
@_cdecl("Java_com_example_MyClass_hello")
func hello(env: UnsafeMutablePointer<JNIEnv>, thisObj: jobject) -> jstring {
return env.pointee.pointee.NewStringUTF(env, "Hello from Swift")!
}
```
19 changes: 19 additions & 0 deletions Sources/SwiftAndroid/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Swift on Android

Use Swift to build native libraries and applications for Android

@Metadata {
@TechnologyRoot
}

## Topics

### Getting Started

- <doc:GettingStarted>
- <doc:BuildingForAndroid>

### Guides

- <doc:PortingPackages>
- <doc:Integration>
29 changes: 29 additions & 0 deletions Sources/SwiftAndroid/Documentation.docc/GettingStarted.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Getting Started

Install the Swift toolchain, Android NDK, and Swift SDK for Android

## Overview

Development requires three components:

1. **Swift Toolchain** -- install with [swiftly](https://github.com/swiftlang/swiftly): `swiftly install latest`
2. **Android NDK** -- download from [developer.android.com](https://developer.android.com/ndk/downloads) (r27d+ recommended)
3. **Swift SDK for Android** -- install with `swift sdk install` (see [swift.org](https://www.swift.org/documentation/articles/swift-sdk-for-android-getting-started.html))

## Hello World

```shell
$ swift package init --type executable
$ swift build --swift-sdk aarch64-unknown-linux-android28
$ adb push .build/aarch64-unknown-linux-android28/debug/HelloWorld /data/local/tmp/
$ adb shell /data/local/tmp/HelloWorld
Hello, world!
```

## Target triples

| Architecture | Triple |
|---|---|
| ARM64 | `aarch64-unknown-linux-android28` |
| ARM32 | `armv7-unknown-linux-androideabi28` |
| x86_64 | `x86_64-unknown-linux-android28` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32bit x86 is also supported in the Android SDK bundled with the Windows installer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of us use that SDK, which doesn't even have any install instructions yet. I have asked those behind it to write some up.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32bit x86 Android is almost completely non-existent. I think we should avoid any mention of it, even if the Windows SDK happens to still support it.

29 changes: 29 additions & 0 deletions Sources/SwiftAndroid/Documentation.docc/Integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Integration

Integrate Swift builds with Android tooling and frameworks

## Gradle

Add a custom Gradle task to invoke `swift build` and copy the resulting `.so` into `jniLibs/`:

```kotlin
tasks.register<Exec>("buildSwiftLibrary") {
workingDir = file("${rootDir}/swift")
commandLine("swift", "build",
"--swift-sdk", "aarch64-unknown-linux-android28",
"-c", "release", "--static-swift-stdlib")
}
```

## Swift Package Manager

```shell
$ swift build --swift-sdk aarch64-unknown-linux-android28
```

## Resources

- [Swift SDK for Android -- Getting Started](https://www.swift.org/documentation/articles/swift-sdk-for-android-getting-started.html)
- [swift-java](https://github.com/swiftlang/swift-java) -- Java/Kotlin interop
- [swift-android-action](https://github.com/marketplace/actions/swift-android-action) -- GitHub Actions
- [Swift Forums](https://forums.swift.org/)
27 changes: 27 additions & 0 deletions Sources/SwiftAndroid/Documentation.docc/PortingPackages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Porting Swift Packages to Android

Adapt existing Swift packages to build and run on Android

## Overview

Many Swift packages build for Android with minimal changes. The typical process is: attempt a build, fix platform-specific code with conditional compilation, then test on a device.

## Good candidates

- Business logic, algorithms, data structures
- Networking and API clients
- Parsers, formatters, encoders/decoders
- SQLite and other database access

## Conditional imports

```swift
#if canImport(Darwin)
import Darwin
#elseif canImport(Android)
import Android
#elseif canImport(Glibc)
import Glibc
#endif
```

1 change: 1 addition & 0 deletions Sources/SwiftAndroid/Empty.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// This file is included so SwiftPM considers the target to be a Swift target.