Demo: library catalog with jextract JNI callbacks, official Swift Android SDK#48
Merged
Merged
Conversation
- Replace `skip android build` with direct `swift build --swift-sdk` (official Swift 6.3.3 Android SDK); --disable-sandbox enables the swift-java jextract plugin's nested Java callbacks build - Add CatalogBridge target using jextract JNI mode with enableJavaCallbacks for Swift<->Java closures/Runnable blocks - Stage SwiftKitCore + generated Java bindings into the app build, vendoring Android-compatible copies of jdk.jfr-based annotations - Smoke test in Application: Kotlin->Swift downcall and Swift->Kotlin closure callback, verified on emulator
Follow the trucksmart-ios integration pattern: an `jextract` Exec task runs `swift build` with the swift.org toolchain, a `stageJniLibs` Copy task stages product/runtime/NDK libraries, and the generated JNI Java + SwiftKitCore sources join the source set via srcDir + filter.exclude. Replaces build-swift.sh, the source-staging Sync task, and the vendored jdk.jfr-free annotation copies.
- CatalogBridge exposes catalogEntryCount/Name/Summary and runCatalogDemo(index, onLine, onCompleted) — demo output and completion are delivered from Swift to Kotlin through jextract JNI closures/runnable blocks - Curated demos exercising the SDK wrappers: AndroidOS (Build, SystemClock), AndroidContent (package/app info), AndroidLocation (providers), AndroidMedia (volumes, ringer), AndroidNet (connectivity, Wi-Fi), AndroidNFC (adapter) - Demos acquire the application Context via AndroidContext (ActivityThread bootstrap), wrapped once as a JNI global ref - Compose catalog UI: list of libraries with the Swift-driven clock header, per-entry demo screens - Remove the legacy SwiftObject/external-method callback shims (Runnable, ViewOnClickListener, adapters, Fragment) superseded by the jextract bridge - Add ACCESS_NETWORK_STATE, ACCESS_WIFI_STATE and NFC permissions required by the demos All six demos verified on the emulator (arm64-v8a, API 36).
Drop the separate CatalogBridge dynamic product: it duplicated the module (static-linked into the app library and as its own .so), splitting module statics between two copies. The jextract config's nativeLibraryName now points the generated Java bindings at SwiftAndroidApp, whose exported Java_* thunk symbols resolve the native methods.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Rebuilds the Demo app around a library catalog: a Compose list of the wrapped Android SDK modules, each opening a screen that runs a live demo implemented in Swift, with output streamed back to Kotlin through swift-java jextract (JNI mode) callbacks and runnable blocks.
Build system: Skip → official Swift Android SDK
swift build --swift-sdk aarch64-unknown-linux-android28(Swift 6.3.3 release toolchain + artifactbundle) directly from Gradle — anjextractExec task plus astageJniLibsCopy task replaceskip android buildandbuild-swift.sh.--disable-sandboxis required for the jextract plugin'senableJavaCallbacksnested Gradle build, which the Skip driver could not pass through.sourceSets+filter.excludefor the twojdk.jfr-dependent annotations, which don't exist on Android).jextract JNI bridge (
CatalogBridge)mode: jniandenableJavaCallbacks; public API iscatalogEntryCount/Name/SummaryandrunCatalogDemo(index:onLine:onCompleted:)— Swift invokes the Kotlin lambdas through generated thunks.nativeLibraryName: SwiftAndroidApppoints the generated bindings atlibSwiftAndroidApp.so, so there is a single copy of the module (no separate.so, no duplicated module statics).ContextviaAndroidContext.application(ActivityThread bootstrap), wrapped exactly once as a JNI global ref —JavaObjectHolderdeletes the incoming local ref on promotion, so re-wrapping a cached pointer would crash.SwiftObject/external-method callback shims (Runnable, ViewOnClickListener, list/recycler adapters, Fragment) are removed, superseded by the jextract bridge (net −500 LOC).Catalog demos
Context/ApplicationInfoLocationManagerproviders and enabled stateAudioManagerstream volumes and ringer modeConnectivityManageractive network,WifiManagerstateNfcAdapteravailabilityAdds
ACCESS_NETWORK_STATE,ACCESS_WIFI_STATE, andNFCpermissions required by the demos.Test plan
./gradlew :app:assembleDebugbuilds end-to-end (Swift cross-compile → jextract generation → APK)llvm-nmconfirms theJava_*thunk symbols are exported fromlibSwiftAndroidApp.so