A Swift Package Manager plugin that builds and packages native Swift applications as Android APKs. It handles the full pipeline: cross-compiling Swift to Android, bundling resources and native libraries, and signing the APK.
- The latest Swift nightly
- The Swift Android SDK for your nightly
Note: The Swift Android SDK must be paired up with the same toolchain version. Set your Swift toolchain version correctly as such:
swiftly run +<snapshot-version> swift package bundle-apk
The Android SDK is auto-discovered from these locations (in order):
$ANDROID_HOMEenvironment variable$ANDROID_SDK_ROOTenvironment variable~/Library/Android/sdk~/Android/Sdk/usr/local/lib/android/sdk
In your package's Package.swift:
let package = Package(
name: "my-android-app",
dependencies: [
.package(url: "https://github.com/orlandos-nl/swift-apk-plugin.git", from: "0.1.0"),
],
targets: [
.executableTarget(name: "my-android-app"),
]
)Create an AndroidManifest.xml at the root of your package:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application
android:allowBackup="true"
android:hasCode="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true">
<activity android:name="android.app.NativeActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="true">
<meta-data android:name="android.app.lib_name"
android:value="my-android-app" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>Set android:value in the meta-data tag to the name of your app.
Create a res/ directory at the root of your package with your Android resources. At minimum you need:
res/
values/
strings.xml
mipmap-hdpi/
ic_launcher.png
Example res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My App</string>
</resources>swift package plugin bundle-apk --product my-android-app output.apkThe built APK is placed at .build-apk/<product>.apk.
| Option | Default | Description |
|---|---|---|
--product |
Auto-detected | Product to build |
--configuration, -c |
debug |
Build configuration (debug or release) |
--abi |
arm64-v8a |
Target ABI: arm64-v8a, armeabi-v7a, or x86_64 |
--api-level |
29 |
Minimum Android API level |
--target-sdk |
36 |
Target Android SDK version |
--install |
off | Install the APK on a connected device via adb after building |
Build a release APK for ARM64:
swift package --disable-sandbox --allow-writing-to-package-directory bundle-apk \
--product my-android-app \
-c releaseWe need the sandbox disabled to call your NDK tools.
Build and install on a connected device (or emulator):
swift package --disable-sandbox --allow-writing-to-package-directory bundle-apk \
--product my-android-app \
--installTarget an older API level:
swift package --disable-sandbox --allow-writing-to-package-directory bundle-apk \
--product my-android-app \
--api-level 24 \
--target-sdk 34The plugin runs a 6-step build process:
- Compile Swift -- Cross-compiles your Swift code using the installed Swift Android SDK
- Compile resources -- Runs
aapt2 compileon theres/directory - Link APK -- Links the manifest, compiled resources, and platform JAR into a base APK
- Add native libraries -- Bundles your
.sofiles, Swift runtime libraries, andlibc++_shared.so - Align APK -- Runs
zipalignfor optimized access - Sign APK -- Signs with a debug keystore (auto-created at
~/.android/debug.keystoreif missing)
| ABI | Swift Triple |
|---|---|
arm64-v8a |
aarch64-unknown-linux-android |
armeabi-v7a |
armv7-unknown-linux-android |
x86_64 |
x86_64-unknown-linux-android |
Build artifacts are written to two directories (both are .gitignore-safe):
.build-android/-- Swift cross-compilation output.build-apk/-- APK build artifacts and final signed APK