Birdo VPN Mobile Client -- Android & iOS (Kotlin Multiplatform + SwiftUI)
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
The universal mobile client for Birdo VPN -- built once with Kotlin Multiplatform, running natively on Android and iOS.
Looking for Windows, macOS, or Linux? See the Desktop Client.
The KMP shared module holds the cross-platform wire types and pure helpers
— not the tunnel:
• model/Models.kt — the serialised API request/response types
• util/{FlagUtils,FormatUtils,InputValidator}.kt — formatting and validation
• Platform.kt (+ androidMain / appleMain actuals) — clock and IP-literal
validation查看完整 README ↗The universal mobile client for Birdo VPN -- built once with Kotlin Multiplatform, running natively on Android and iOS.
| Platform | Min Version | Framework | Store |
|---|---|---|---|
| Android | 10 (API 29) | Kotlin + Jetpack Compose | Google Play |
| iOS | 17.0 | KMP + SwiftUI | App Store |
Looking for Windows, macOS, or Linux? See the Desktop Client.
birdo-client-mobile/
shared/ Kotlin Multiplatform shared module (Android + iOS)
app/ Android app (Jetpack Compose UI)
iosApp/ iOS app (SwiftUI + PacketTunnel Network Extension)
store-assets/ Play Store and App Store screenshots
shared/)The KMP shared module holds the cross-platform wire types and pure helpers — not the tunnel:
model/Models.kt — the serialised API request/response typesutil/{FlagUtils,FormatUtils,InputValidator}.kt — formatting and validationPlatform.kt (+ androidMain / appleMain actuals) — clock and IP-literal
validationTunnel management, the API client, the connection state machine and certificate
pinning live in each platform's own source tree (app/, iosApp/), not here.
Compiled to:
BirdoShared framework and no workflow builds it
(MR-1085). The Apple targets in shared/build.gradle.kts still compile if
asked, but nothing ships them.app/)VpnService API with wireguard-go (com.wireguard.android:tunnel)iosApp/)project.yml) generates the Xcode projectSUPPORTS_ALWAYS_ON=true, pinned
by ApiLevel36ContractTest. When Android starts the service at boot, on
unlock or when the setting changes, the service puts its block up first and
then reconnects on its own to the last server (SystemStartPolicy). An app
update restores the session (PackageReplacedReceiver). After a crash the
service is NOT restarted by Android (START_NOT_STICKY, live on API 35).
Instead, a connection you left on comes back, block first, the next time
BirdoVPN's process starts for any reason: you open the app, tap the widget
or the Quick Settings tile, or a home-screen widget refresh starts it. That
is not only after a crash: it also happens after a reboot without Always-on
(launchers refresh their widgets at boot) and after a Force stop once the app
is next opened. Disconnect in BirdoVPN first if you do not want the
connection back. A tap on the tile or widget that starts the process joins
that resume rather than cancelling it. With "Block connections without VPN"
on, Android keeps blocking through the gap.brew install xcodegen)# Debug build
./gradlew assembleDebug
# Release build (requires signing config)
./gradlew assembleRelease
# Run tests
./gradlew testDebugUnitTest
# Generate Xcode project (no Kotlin step: the app uses no KMP code)
cd iosApp && xcodegen generate
# Build (unsigned)
xcodebuild build \
-project BirdoVPN.xcodeproj \
-scheme BirdoVPN \
-destination 'generic/platform=iOS' \
-configuration Release \
CODE_SIGN_IDENTITY="-" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGNING_ALLOWED=NO
cp local.properties.example local.properties
# Edit local.properties with your Android SDK path
Every release APK and AAB is signed with Sigstore using keyless signing from GitHub Actions. See docs/VERIFICATION.md for instructions.
cosign verify-blob \
--bundle BirdoVPN-release.apk.sigstore \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp "github.com/BirdoVPN/" \
BirdoVPN-release.apk
| Workflow | Trigger | Platforms |
|---|---|---|
| Android CI | PRs (any base branch), push to main | Lint, unit tests, CodeQL, debug APK + R8, native gates, instrumented tests on an emulator |
| Android Release | Push to main (dry run), android-v* tags, manual dispatch | Signed APK + AAB, Sigstore + GPG, draft release, Play upload |
| Apple CI | Every PR and main push; the jobs are skipped unless iosApp/, native/birdo-pq-ios/ or the build inputs changed | iOS simulator tests, unsigned macOS build |
| iOS Release | android-v* tags, manual dispatch | Unsigned .ipa on the release, TestFlight upload |
| macOS Release | mac-v* tags, manual dispatch | Unit tests, then the Mac App Store upload; UI screenshots |
All workflows use pinned action SHAs, minimal permissions, and Sigstore cosign for artifact signing.
| Component | Technology |
|---|---|
| Shared Logic | Kotlin Multiplatform 2.4.10 |
| Android UI | Jetpack Compose + Material 3 |
| iOS UI | SwiftUI (Swift 6.0) |
| VPN Protocol | WireGuard (wireguard-go on Android, Network Extension on iOS) |
| Encryption | ChaCha20-Poly1305 |
| Key Exchange | Curve25519 + Post-Quantum (BirdoPQ v1, ML-KEM-1024) |
| DI (Android) | Dagger Hilt 2.60.1 |
| Build (Android) | Gradle 9.7.1 + AGP 9.4.0 |
| Build (iOS) | XcodeGen + Xcode 26+ |
| Serialization | kotlinx.serialization |
| Code Signing | Sigstore (keyless) + Android Keystore |
.github/workflows/
android-ci.yml Android CI: lint, test, CodeQL, debug APK, R8, native gates
android.yml Android release: signed APK + AAB, draft release, Play upload
apple-ci.yml Apple CI: iOS simulator tests, macOS build
ios.yml iOS release: .ipa, TestFlight
app/
src/main/ Android app source (Kotlin + Compose)
build.gradle.kts Android app build config
shared/
src/commonMain/ KMP shared code (both platforms)
src/androidMain/ Android-specific implementations
src/appleMain/ Apple-specific implementations (iOS + macOS)
build.gradle.kts KMP module build config
iosApp/
iosApp/ SwiftUI app source
PacketTunnel/ WireGuard Network Extension
project.yml XcodeGen project spec
store-assets/ Store screenshots and graphics
docs/
CODE_SIGNING.md How artifacts are signed
VERIFICATION.md How to verify downloads
build.gradle.kts Root Gradle config
settings.gradle.kts Module declarations
version.properties Centralized version (1.4.29)
For vulnerability reports, email [email protected].
This project is licensed under Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0). That makes the apps source-available, not open source: CC BY-NC is not an OSI-approved licence. The server code is private.
birdo.app -- A secure and independent VPN