From d4146cc03762280189c398cef6ec7334b2f416ee Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Fri, 8 May 2026 15:24:57 -0400 Subject: [PATCH 1/7] Fix AndroidBundle for upcoming Swift 6.4 changes to resource_bundle_accessor.swift --- .github/workflows/ci.yml | 3 ++- Sources/SkipAndroidBridge/AndroidBundle.swift | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ccdbede..7b7b0d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,4 +14,5 @@ permissions: jobs: call-workflow: uses: skiptools/actions/.github/workflows/skip-framework.yml@v1 - + with: + swift-android-sdk-version: "['', 'nightly-main']" diff --git a/Sources/SkipAndroidBridge/AndroidBundle.swift b/Sources/SkipAndroidBridge/AndroidBundle.swift index 09719f5..67827b2 100644 --- a/Sources/SkipAndroidBridge/AndroidBundle.swift +++ b/Sources/SkipAndroidBridge/AndroidBundle.swift @@ -50,16 +50,19 @@ open class AndroidBundle : Foundation.Bundle, @unchecked Sendable { super.init(path: Foundation.Bundle.main.bundlePath)! } - // These inits require 'override' on Android but not iOS or ROBOLECTRIC + // These inits require 'override' on Android but not iOS or ROBOLECTRIC. + // They must not be marked unavailable because the auto-generated + // resource_bundle_accessor.swift (produced by the swiftbuild build system) + // calls Bundle(for: BundleFinder.self) as part of its fallback chain. #if os(Android) - @available(*, unavailable) public override init(for aClass: AnyClass) { - fatalError() + self.bundleAccess = BundleAccess.main + super.init(path: Foundation.Bundle.main.bundlePath)! } - @available(*, unavailable) public override init?(identifier: String) { - fatalError() + self.bundleAccess = BundleAccess.main + super.init(path: Foundation.Bundle.main.bundlePath)! } #endif From 764c245e457c78f2aa17bb8e4b8d5119e46eabe6 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Fri, 8 May 2026 16:02:18 -0400 Subject: [PATCH 2/7] Build skip from source with skip-source: 'build-system' --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b7b0d7..f942aad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,4 +15,5 @@ jobs: call-workflow: uses: skiptools/actions/.github/workflows/skip-framework.yml@v1 with: + skip-source: 'build-system' swift-android-sdk-version: "['', 'nightly-main']" From 75f478138e7d261f675286e2a090a4e723cf9b56 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Fri, 8 May 2026 22:34:09 -0400 Subject: [PATCH 3/7] Return to using formula distribution of skip in CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f942aad..c2dd59a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,5 +15,5 @@ jobs: call-workflow: uses: skiptools/actions/.github/workflows/skip-framework.yml@v1 with: - skip-source: 'build-system' + runs-on: "['macos-15-intel', 'ubuntu-24.04']" swift-android-sdk-version: "['', 'nightly-main']" From f37aefb2b10f43f26ca1cce8fe75b770773b200a Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Tue, 26 May 2026 09:26:49 -0400 Subject: [PATCH 4/7] Update package name --- Package.swift | 2 +- Sources/SkipAndroidBridge/AndroidBridgeBootstrap.swift | 2 +- Sources/SkipAndroidBridge/AndroidUserDefaults.swift | 2 +- Sources/SkipAndroidBridge/AssetURLProtocol.swift | 6 +++--- .../SkipAndroidBridgeSamplesTests.swift | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Package.swift b/Package.swift index 349eeb8..933da08 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version: 6.1 import PackageDescription let package = Package( diff --git a/Sources/SkipAndroidBridge/AndroidBridgeBootstrap.swift b/Sources/SkipAndroidBridge/AndroidBridgeBootstrap.swift index 5292554..fcba764 100644 --- a/Sources/SkipAndroidBridge/AndroidBridgeBootstrap.swift +++ b/Sources/SkipAndroidBridge/AndroidBridgeBootstrap.swift @@ -64,7 +64,7 @@ public class AndroidBridge { /// get `Foundation` idioms working with Android conventions. // SKIP @bridge public class AndroidBridgeBootstrap { - private static var androidBridgeInit = false + nonisolated(unsafe) private static var androidBridgeInit = false /// Perform all the setup that is needed to get `Foundation` idioms working with Android conventions. /// diff --git a/Sources/SkipAndroidBridge/AndroidUserDefaults.swift b/Sources/SkipAndroidBridge/AndroidUserDefaults.swift index c015d39..9a0043c 100644 --- a/Sources/SkipAndroidBridge/AndroidUserDefaults.swift +++ b/Sources/SkipAndroidBridge/AndroidUserDefaults.swift @@ -7,7 +7,7 @@ open class AndroidUserDefaults : Foundation.UserDefaults { open override class var standard: AndroidUserDefaults { return _standard } - private static let _standard = AndroidUserDefaults() + nonisolated(unsafe) private static let _standard = AndroidUserDefaults() private let userDefaultsAccess: UserDefaultsAccess diff --git a/Sources/SkipAndroidBridge/AssetURLProtocol.swift b/Sources/SkipAndroidBridge/AssetURLProtocol.swift index e011130..4b64a52 100644 --- a/Sources/SkipAndroidBridge/AssetURLProtocol.swift +++ b/Sources/SkipAndroidBridge/AssetURLProtocol.swift @@ -11,10 +11,10 @@ fileprivate let logger: Logger = Logger(subsystem: "skip.android.bridge", catego /// A custom URLProtocol that serves requests from the native Android `AAssetManager`, which is implemented in `swift-android-native / AndroidAssetManager.swift` public class AssetURLProtocol: URLProtocol { /// The URL scheme that this protocol handles - public static var scheme = "asset" + public static let scheme = "asset" - private static var registered = false - private static var assetManager: AndroidAssetManager? = nil + nonisolated(unsafe) private static var registered = false + nonisolated(unsafe) private static var assetManager: AndroidAssetManager? = nil public static func register() throws { if registered { return } diff --git a/Tests/SkipAndroidBridgeSamplesTests/SkipAndroidBridgeSamplesTests.swift b/Tests/SkipAndroidBridgeSamplesTests/SkipAndroidBridgeSamplesTests.swift index 4594dcb..0ed27fb 100644 --- a/Tests/SkipAndroidBridgeSamplesTests/SkipAndroidBridgeSamplesTests.swift +++ b/Tests/SkipAndroidBridgeSamplesTests/SkipAndroidBridgeSamplesTests.swift @@ -99,7 +99,7 @@ final class SkipAndroidBridgeSamplesTests: XCTestCase { } // SkipAndroidBridgeSamplesTests.kt testAndroidContext -> SkipAndroidBridgeSamples.kt nativeAndroidContextPackageName -> SkipAndroidBridgeSamples.swift nativeAndroidContextPackageName -> AndroidContext.swift getPackageName() - XCTAssertEqual("skip.android.bridge.samples.test", try nativeAndroidContextPackageName()) + XCTAssertEqual("skip.android.bridge.samples.module.test", try nativeAndroidContextPackageName()) } func testLocalizedStringResource() throws { From 8ff85684e1ea5bc0e1eb00bc56187d9bc3f43f7d Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Tue, 26 May 2026 10:54:36 -0400 Subject: [PATCH 5/7] Update expected package name --- Tests/SkipAndroidBridgeTests/AndroidBridgeTests.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/SkipAndroidBridgeTests/AndroidBridgeTests.swift b/Tests/SkipAndroidBridgeTests/AndroidBridgeTests.swift index 81285f5..43d7d87 100644 --- a/Tests/SkipAndroidBridgeTests/AndroidBridgeTests.swift +++ b/Tests/SkipAndroidBridgeTests/AndroidBridgeTests.swift @@ -29,13 +29,13 @@ final class AndroidBridgeTests: XCTestCase { let cacheDir = URL(fileURLWithPath: context.getCacheDir().getAbsolutePath(), isDirectory: true) if isRobolectric { - // Robolectric's files folder is tough to predict (e.g. /var/folders/zl/wkdjv4s1271fbm6w0plzknkh0000gn/T/robolectric-AndroidBridgeTests_testAndroidBridge_SkipAndroidBridge_debugUnitTest10131350412654065418/skip.android.bridge.test-dataDir/files) - XCTAssertTrue(filesDir.path.hasSuffix("/files"), "unexpected filesDir.path: \(filesDir.path)") - XCTAssertTrue(cacheDir.path.hasSuffix("/cache"), "unexpected cacheDir.path: \(cacheDir.path)") + // Robolectric's files folder is tough to predict (e.g. /var/folders/zl/wkdjv4s1271fbm6w0plzknkh0000gn/T/robolectric-AndroidBridgeTests_testAndroidBridge_SkipAndroidBridge_debugUnitTest10131350412654065418/skip.android.bridge.module.test-dataDir/files) + XCTAssertTrue(filesDir.path.hasSuffix("/skip.android.bridge.module.test-dataDir/files"), "unexpected filesDir.path: \(filesDir.path)") + XCTAssertTrue(cacheDir.path.hasSuffix("/skip.android.bridge.module.test-dataDir/cache"), "unexpected cacheDir.path: \(cacheDir.path)") } else { // …but Android is predictably the app's "files" and "cache" directories - XCTAssertEqual("/data/user/0/skip.android.bridge.test/files", filesDir.path) - XCTAssertEqual("/data/user/0/skip.android.bridge.test/cache", cacheDir.path) + XCTAssertEqual("/data/user/0/skip.android.bridge.module.test/files", filesDir.path) + XCTAssertEqual("/data/user/0/skip.android.bridge.module.test/cache", cacheDir.path) } // make sure we can read and write to the filesDir From 9fc5a0e62e85a8107494f86731d8c5ee53c13b03 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 3 Jun 2026 09:25:13 -0400 Subject: [PATCH 6/7] preconcurrency import SwiftJNI to sidestep useage of static jni --- Sources/SkipAndroidBridge/AssetURLProtocol.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/SkipAndroidBridge/AssetURLProtocol.swift b/Sources/SkipAndroidBridge/AssetURLProtocol.swift index 4b64a52..c7898fd 100644 --- a/Sources/SkipAndroidBridge/AssetURLProtocol.swift +++ b/Sources/SkipAndroidBridge/AssetURLProtocol.swift @@ -5,6 +5,7 @@ import Foundation import FoundationNetworking import AndroidAssetManager import AndroidLogging +@preconcurrency import SwiftJNI fileprivate let logger: Logger = Logger(subsystem: "skip.android.bridge", category: "AssetURLProtocol") From cf96449844aba8a51c2d53681282746c4450393a Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 3 Jun 2026 16:07:35 -0400 Subject: [PATCH 7/7] Only run on macos-15-intel due to ubuntu-24.04 errors --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2dd59a..938e091 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,5 +15,5 @@ jobs: call-workflow: uses: skiptools/actions/.github/workflows/skip-framework.yml@v1 with: - runs-on: "['macos-15-intel', 'ubuntu-24.04']" + #runs-on: "['macos-15-intel', 'ubuntu-24.04']" swift-android-sdk-version: "['', 'nightly-main']"