SDKs and platforms

Can I use Offline Protocol with Flutter?

Yes. The offline_protocol Flutter plugin runs on iOS 13 and later and Android 7.0 (API 24) and later with Flutter 3.10 or later. It compiles the same native bridge code as the React Native module, so it carries the same transports and secure storage. You add it as a path dependency on the SDK repository after building the mobile native libraries with Rust; it is a preview and not on pub.dev yet.

TL;DR

As of 0.31.0, Offline Protocol's Flutter plugin brings the React Native module's full native method surface to Flutter apps on iOS and Android, on the same transports and bridge code. You add it by path after building the native libraries with Rust. It is a preview, not on pub.dev yet.

Learning objectives

After reading this article you will be able to:

  • Build the native libraries and add the offline_protocol plugin to a Flutter app by path
  • Compare the plugin's coverage with the React Native module as of 0.31.0
  • Choose between the Flutter plugin and the React Native module for a new app

Offline Protocol Flutter plugin

Offline Protocol has a Flutter plugin, offline_protocol, that gives iOS and Android apps the mesh engine with its transports, encryption and events from Dart. It was added in 0.30.0, lives in the SDK repository under bindings/flutter, and is a preview as of 0.31.0 (October 2026).

The plugin is not a separate implementation. It links the same generated Kotlin and Swift as the React Native module and compiles the same hand-written native bridge code under bindings/react-native/{ios,android}, less the files that need React. So the transports, secure storage and configuration parser are the ones React Native apps run. The Dart side talks to them over a method channel, and events arrive as JSON on an event stream.

Flutter, iOS and Android requirements

The plugin needs these versions:

RequirementVersion
Flutter3.10 or later
iOS13.0 or later
AndroidAPI 24 (Android 7.0) or later
Build toolsThe Rust toolchain and a one-time build of the mobile native libraries

It also needs the same permissions as React Native. On iOS that means Bluetooth usage descriptions and the bluetooth-central and bluetooth-peripheral background modes, declared before Bluetooth LE starts. On Android it means the Bluetooth, location and nearby Wi-Fi runtime permissions where they apply. The Swift and Kotlin previews are the routes for native apps without Flutter.

Adding the plugin as a path dependency

The plugin is added by path, because it is not published to pub.dev yet. First build the mobile native libraries from the repository root, the same steps as the React Native module:

./scripts/generate-bindings.sh
cd bindings/react-native
npm run build:uniffi:all

That produces the Android .so files, the iOS XCFramework and the generated Kotlin and Swift. Then depend on the plugin in your app’s pubspec.yaml:

dependencies:
  offline_protocol:
    path: ../bindings/flutter/offline_protocol   # adjust for your layout

On iOS, pod install copies the shared Swift bridge sources into the plugin, because CocoaPods only indexes files under the pod root. If those shared sources change, run bindings/flutter/offline_protocol/ios/sync_bridge_rn.sh and pod install again, or the build compiles the old copy without saying so.

Flutter quick start

Subscribe to events before createFromConfig if you need every event, including gap recovery through native replay. This is the plugin’s own quick start:

import 'package:offline_protocol/offline_protocol.dart';

final sub = OfflineProtocol.events.listen((e) {
  final type = e.decodeEvent()['type'];
  // message_received, diagnostics, …
});

await OfflineProtocol.createFromConfig({
  'appId': 'com.example.app',
  'profile': 'default',
  'bleEnabled': true,
  'internetEnabled': true,
  'transports': {
    'internet': {
      'enabled': true,
      'serverAddress': 'wss://relay.example.com',
    },
    'wifiDirect': {'enabled': true},
  },
});
await OfflineProtocol.initializeMlsWithSecureStorage();
await OfflineProtocol.start();

final messageId = await OfflineProtocol.sendMessage(
  recipient: 'off1…',
  content: 'Hello',
);

The engine and transport work run on a dedicated engine thread, one per process, and method-channel results and events are delivered on the main isolate’s platform thread. Nothing blocking runs on the UI thread, so a teardown that waits on transport I/O does not freeze the app.

Flutter plugin coverage in 0.31.0

As of 0.31.0, the Flutter plugin reaches the React Native module’s full native method surface. The release added the plugin’s engine channel, generators for its method handlers on Android and iOS, parity guards and an iOS bridge job in CI:

AreaIn the Flutter plugin
Lifecycle, identity, messagingcreateFromConfig, initializeMlsWithSecureStorage, start, stop, destroy, localAddress, sendMessage
EventsOfflineProtocol.events, with sequence numbers and replayEvents when you subscribe early
Full native surfaceMeshSdk, whose method channel carries the React Native module’s native methods plus replayEvents (171 methods)
TransportsInternet, Bluetooth LE, Wi-Fi Direct, Nostr and Reticulum, on the same configuration model as React Native
TelemetryOn the method channel and through MeshSdk
Android backgroundMeshForegroundService keeps mesh work alive while the engine runs

A CI guard holds the channel’s method list equal across Dart, Android and iOS, so a method added on one side reaches all three. The one React Native feature that stays in React Native is the headless wake service, which brings mesh work back after the operating system kills the process. The public docs page still describes the 0.30.0 plugin, whose Dart API was narrower.

Flutter plugin status and testing

The plugin is a preview, added to an app by path while it is not on pub.dev, and upgrading means moving your SDK checkout to a new release tag. CI covers it on both platforms:

  • Dart. flutter test and flutter analyze run on every change to the plugin.
  • Android. CI builds the native library, assembles the plugin’s release library and checks its size against a committed baseline.
  • iOS. A bridge job typechecks the plugin’s Swift together with the shared bridge sources the pod compiles, against the Flutter engine framework. The Swift package job is the one that links the iOS library.

The example app runs on Android from the committed Gradle tree, and a script generates its Xcode Runner project for iOS. It starts with the internet transport flag only, subscribes to events and prints the device’s off1… address.

For a team choosing a framework from scratch, React Native is the stable integration, published on npm. For a team already on Flutter, the plugin runs the same native bridge code, so the same transports work across an iPhone and an Android phone. The SDK is AGPL-3.0-only, with a commercial licence for proprietary apps.

Frequently asked questions

Is the Offline Protocol Flutter plugin on pub.dev?

No. As of 0.31.0 (October 2026) it is not published to pub.dev. You check out the SDK repository and depend on bindings/flutter/offline_protocol by path.

Which Flutter, iOS and Android versions does the plugin support?

Flutter 3.10 or later, iOS 13.0 or later and Android API 24 (Android 7.0) or later. You also need the Rust toolchain for a one-time build of the mobile native libraries.

Does the Flutter plugin support Nostr and Reticulum?

Yes, from 0.31.0. The plugin compiles the shared Reticulum and Nostr managers, and they start when the configuration enables them. The 0.30.0 plugin refused a configuration with either set.

Is anything in the React Native module not in the Flutter plugin?

The headless wake service, which brings mesh work back after the process is killed, stays in React Native. The rest of the native method surface is in the plugin as of 0.31.0.

Does the Flutter plugin work in a browser or on desktop?

No. It is for iOS and Android apps only. Desktop and server hosts use Python, Java or the C API, and the browser has a separate experimental binding.

Can a Flutter app talk to a React Native app over the mesh?

Yes. The plugin links the same native artifacts and bridge code as the React Native module and follows the same configuration model, so both apps run the same engine and protocol.

Sources

Build it with Offline Protocol

The Flutter page of the docs has the requirements, the build steps, the path dependency, the platform permissions and the quick start.

Read the Flutter plugin docs