Auto-discovery (Android)
This page covers Android auto-discovery. java.util.ServiceLoader and R8 rules are JVM
concepts. iOS has no equivalent mechanism — see Swift: provide & consume for
how iOS providers are registered explicitly.
A feature shipped as an AAR needs its global-scope providers registered without the host app
wiring each one by hand. BridgeKit uses java.util.ServiceLoader for that — global scope
only.
A discovery module
Section titled “A discovery module”class ConnectBridgeModule : BridgeKitModule { override fun register(bridgekit: BridgeKit, host: BridgeKitHost) { // host carries the Application Context + the host-installed dependency locator bridgekit.provide(SegmentsContract, Scope.global) { SegmentsProvider(host.locate()) } }}Register it as a service:
com.example.connect.ConnectBridgeModuleBridgeKit.initialize(host) runs ServiceLoader.load + each register().
BridgeKitHost — the DI bridge
Section titled “BridgeKitHost — the DI bridge”Real providers need the DI graph (use cases, repos), but ServiceLoader instantiates
zero-arg classes. BridgeKitHost solves that: the host installs its dependency locator
once during Axion init — the same place ReactManager.setAxion*Dependencies lives today — and
modules call host.locate() to reach it. Factories stay lazy (resolved on first use);
eager = true opts in.
Ordering guarantee
Section titled “Ordering guarantee”ServiceLoader.load + all register() calls complete synchronously inside BridgeKit
init, which runs before reactHost.start(). So global state is sync-readable at the
first JS render — guaranteed, not racy.
R8 / minification
Section titled “R8 / minification”BridgeKit’s AAR ships consumer rules so discovery survives a minified release build:
-keep interface axion.bridgekit.BridgeKitModule-keep class * implements axion.bridgekit.BridgeKitModule { <init>(); }Minified-release discovery is one of the on-device acceptance criteria.
What ServiceLoader does not cover
Section titled “What ServiceLoader does not cover”ServiceLoader is for global providers only. Instance and feature contracts are
always provided through scope handles in host code — a feature fragment creates a
BridgeKitScope when its surface starts and provides into it. Two ServiceLoader modules
claiming the same global id is a hard error at init.
iOS: no ServiceLoader — explicit registration required
Section titled “iOS: no ServiceLoader — explicit registration required”iOS has no ServiceLoader equivalent. Every provider must be registered explicitly in app
code before the React Native bridge initializes — typically in
AppDelegate.application(_:didFinishLaunchingWithOptions:) or the @main App body:
import BridgeKitimport AxionContracts
// In AppDelegate, before the bridge starts:_ = BridgeKitRuntime.default.provide(AxionHostContract()) { AxionHostImpl() }Feature-scoped providers are registered when the feature surface appears and closed when it disappears. See Swift: provide & consume for the full API and scope options, and Installation for xcframework setup.