Skip to content

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.

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:

META-INF/services/axion.bridgekit.discovery.BridgeKitModule
com.example.connect.ConnectBridgeModule

BridgeKit.initialize(host) runs ServiceLoader.load + each register().

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.

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.

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.

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 BridgeKit
import 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.