Install
The jar is on Maven Central ascom.offlineprotocol:offline-protocol-java:
Use a jar and a native library from the same release. Run on JDK 22 or later, allow native access, and point the JVM at the library:
-Duniffi.component.offline_protocol.libraryOverride=/path/to/liboffline_protocol_uniffi.dylib. Without --enable-native-access the JVM warns on the first native call, and a future JDK refuses it.
Quick start
com.offlineprotocol.sdk. OfflineProtocol is the engine, and MeshServices and DataStore hang off it. Every record and enum of the definition is a class. An engine refusal is a subclass of ProtocolException named for the variant; see error codes. OfflineProtocolLib holds the functions that need no engine, such as deriveAddress, parseInvite and runStorageConformance.
Java has no default arguments, so new ProtocolConfig(...) takes every field in order. When a release changes a default in the interface definition, your Java code keeps passing the old value until you change it. The binding’s ConsumerCheckTest.config() carries the definition’s defaults field for field.
Events
setEventCallback installs an EventCallback, or pollEvent takes the oldest queued event. Every event is queued either way. An event is the engine’s JSON text, so parse it with the library you already use; the payloads are the ones in the event reference.
The callback runs on whichever thread is inside the engine, before the engine call that produced it returns. It must be safe from any thread, must not call back into the engine (closing the engine included) and must not throw.
What your host provides
Your process is the platform, so it owns the radios and sockets:- Transports. Implement
BleTransportCallback,WifiDirectTransportCallback,ReticulumTransportCallbackandNostrTransportCallbackto learn when a queue has frames, and drain them with theble*,wifiDirect*,internet*,reticulum*andnostr*methods. - Storage. Implement
MlsStorageProvider(key material, backed by a keystore) andProtocolStateStorageProviderand pass both toinitializeMls, or use the built-in file stores as above. Prove an adapter withOfflineProtocolLib.runStorageConformance. - Telemetry platform. If you enable telemetry, pass
TelemetryConfig.osandosMajoras the platform the process actually runs on (TelemetryOs.LINUX,MACOSorWINDOWS), read from the JVM’sos.nameandos.version. No layer in this binding fills them. - Lifecycle.
start,stopandprocesson a timer.try-with-resourcesfrees the engine once; it does not wait for calls in flight on other threads.
Reference
- Java binding README: building and testing the binding from source.
- Java binding contract: defaults, telemetry, threading and what the JVM requires.

