3167c936c0
apple / swift (push) Successful in 53s
ci / rust (push) Successful in 1m12s
android / android (push) Failing after 1m42s
ci / web (push) Successful in 29s
ci / docs-site (push) Successful in 31s
ci / bench (push) Successful in 1m44s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Failing after 1s
deb / build-publish (push) Failing after 2m45s
docker / deploy-docs (push) Successful in 5s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m49s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m0s
M4 Android stage 1 (discovery). Kotlin-only — browse _punktfunk._udp and present a tappable host list above the manual Host/Port fields. - clients/android/kit: HostDiscovery — NsdManager browse + resolve (registerServiceInfoCallback on API 34+ for reliable TXT, legacy resolveService on 31-33), MulticastLock while running, and a pure parseTxt(proto/fp/pair/id). Exposes the live host set via an onChange callback (NSD callbacks land on the main thread). DiscoveredHost(name, host, port, fingerprint?, pairingRequired). + a JVM unit test of parseTxt. - clients/android/app: ConnectScreen renders discovered hosts (tap -> fill host/port + connect); discovery scoped to the screen (start on enter, stop on connect/leave). Manifest adds CHANGE_WIFI_MULTICAST_STATE + ACCESS_WIFI_STATE (NEARBY_WIFI_DEVICES already declared). Trust stays TOFU (pin=None); fp shown advisory; pairingRequired shown (SPAKE2 PIN wiring is later). Verified: parseTxt unit test (5/5 green); on the emulator a loopback NsdManager.registerService of a fake _punktfunk._udp host was discovered + resolved + TXT-parsed and rendered as a card (name/host:port/TOFU/fp) -- the full browse->resolve->parse->UI path. Real cross-LAN discovery needs a physical device on the host LAN (the emulator's SLIRP NAT drops mDNS multicast). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
100 lines
4.4 KiB
Kotlin
100 lines
4.4 KiB
Kotlin
import java.io.File
|
|
import java.util.Properties
|
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
|
|
plugins {
|
|
// AGP 9 built-in Kotlin compiles this module's Kotlin (NativeBridge) — no kotlin.android plugin.
|
|
id("com.android.library")
|
|
}
|
|
|
|
val ndkVer = "28.2.13676358" // r28 LTS — matches the SDK NDK installed for cargo-ndk
|
|
|
|
android {
|
|
namespace = "io.unom.punktfunk.kit"
|
|
compileSdk = 37 // Android 17 — align with :app (androidx.core 1.19.0 requires it)
|
|
ndkVersion = ndkVer
|
|
|
|
defaultConfig {
|
|
minSdk = 31
|
|
ndk { abiFilters += listOf("arm64-v8a", "x86_64") }
|
|
}
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_21
|
|
targetCompatibility = JavaVersion.VERSION_21
|
|
}
|
|
packaging { jniLibs { useLegacyPackaging = false } } // 16 KB-page friendly
|
|
}
|
|
|
|
kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_21) } }
|
|
|
|
dependencies {
|
|
testImplementation("junit:junit:4.13.2") // JVM unit test for the pure TXT parser
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// cargo-ndk: cross-compile crates/punktfunk-android into this module's jniLibs/<abi>/ so the
|
|
// resulting libpunktfunk_android.so is packaged into the app (and any AAR this module produces).
|
|
// NDK r28+ aligns to 16 KB pages by default — no extra linker flags. Prereqs (see clients/android
|
|
// /README.md): `cargo install cargo-ndk` + `rustup target add aarch64-linux-android x86_64-linux-android`.
|
|
// ------------------------------------------------------------------------------------------------
|
|
val repoRoot = rootDir.parentFile.parentFile // clients/android -> clients -> repo root
|
|
val cargoBin = "${System.getProperty("user.home")}/.cargo/bin"
|
|
|
|
// SDK location without depending on AGP's DSL (sdkDirectory isn't in AGP 9's library extension):
|
|
// env first (set by Android Studio and by our CLI shell), then local.properties, then the default.
|
|
fun androidSdkDir(): String {
|
|
System.getenv("ANDROID_HOME")?.let { return it }
|
|
System.getenv("ANDROID_SDK_ROOT")?.let { return it }
|
|
val lp = rootProject.file("local.properties")
|
|
if (lp.exists()) {
|
|
val props = Properties()
|
|
lp.inputStream().use { props.load(it) }
|
|
props.getProperty("sdk.dir")?.let { return it }
|
|
}
|
|
return "${System.getProperty("user.home")}/Library/Android/sdk"
|
|
}
|
|
|
|
fun registerCargoNdk(taskName: String, release: Boolean) =
|
|
tasks.register<Exec>(taskName) {
|
|
group = "rust"
|
|
description = "cargo-ndk build of punktfunk-android (${if (release) "release" else "debug"})"
|
|
workingDir = repoRoot
|
|
val sdk = androidSdkDir()
|
|
// A GUI Android Studio launch does not source the login shell, so make cargo, the NDK, and
|
|
// cmake (libopus builds via the cmake crate) discoverable explicitly — same as a bare CLI.
|
|
val cmakeBin = "$sdk/cmake/3.22.1/bin"
|
|
environment(
|
|
"PATH",
|
|
cargoBin + File.pathSeparator + cmakeBin + File.pathSeparator + System.getenv("PATH"),
|
|
)
|
|
environment("ANDROID_HOME", sdk)
|
|
environment("ANDROID_NDK_HOME", "$sdk/ndk/$ndkVer")
|
|
// CMake's built-in Android support (used by the cmake crate for libopus) finds the NDK via
|
|
// these, and uses Ninja (bundled next to the SDK cmake) since there's no `make`.
|
|
environment("ANDROID_NDK_ROOT", "$sdk/ndk/$ndkVer")
|
|
environment("ANDROID_NDK", "$sdk/ndk/$ndkVer")
|
|
environment("CMAKE_GENERATOR", "Ninja")
|
|
// audiopus_sys picks static-vs-dynamic by HOST not target — force the bundled static libopus
|
|
// (pure C) so the android .so links it instead of looking for the host's libopus.so.
|
|
environment("LIBOPUS_STATIC", "1")
|
|
environment("LIBOPUS_NO_PKG", "1")
|
|
val cmd = mutableListOf(
|
|
"cargo", "ndk",
|
|
"-t", "arm64-v8a", "-t", "x86_64",
|
|
// Link against the minSdk-31 sysroot so libaaudio (API 26+) is found.
|
|
"--platform", "31",
|
|
"-o", file("src/main/jniLibs").absolutePath,
|
|
"build", "-p", "punktfunk-android",
|
|
)
|
|
if (release) cmd += "--release"
|
|
commandLine(cmd)
|
|
}
|
|
|
|
val cargoNdkDebug = registerCargoNdk("cargoNdkDebug", release = false)
|
|
val cargoNdkRelease = registerCargoNdk("cargoNdkRelease", release = true)
|
|
|
|
afterEvaluate {
|
|
tasks.named("preDebugBuild").configure { dependsOn(cargoNdkDebug) }
|
|
tasks.named("preReleaseBuild").configure { dependsOn(cargoNdkRelease) }
|
|
}
|