Mobile Support (Android & iOS)
This guide describes the architecture, compilation toolchain, development workflow, and testing procedures for running sam-node on mobile platforms (Android and iOS).
Architecture Overview
To run sam-node on mobile with near-zero codebase maintenance, we avoid rewriting the p2p network stack and routing logic in Kotlin/Swift. Instead, we use Go’s CGO compiler to generate native C-compatible libraries that are loaded and controlled inside a Flutter app using Dart FFI (Foreign Function Interface).
┌────────────────────────────────────────────────────────┐
│ Flutter Mobile App │
│ │
│ ┌─────────────────┐ ┌──────────────────┐ │
│ │ Dart GUI │ │ Dart FFI Client │ │
│ └────────┬────────┘ └────────┬─────────┘ │
│ │ │ │
└───────────┼───────────────────────────────┼────────────┘
│ │ (C Function Calls)
│ (HTTP / JSON RPC) ▼
┌───────────┼───────────────────────────────┼────────────┐
│ ▼ │ │
│ ┌─────────────────┐ ┌────────▼─────────┐ │
│ │ Sidecar API │ │ Go FFI Entry │ │
│ │ (127.0.0.1) │ │ (sam-node-ffi) │ │
│ └────────┬────────┘ └────────┬─────────┘ │
│ │ │ (Go APIs) │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ sam-node │ │
│ └──────────────────────────────────────────────────┘ │
│ Go Runtime │
└────────────────────────────────────────────────────────┘
- Go FFI Binding Package (
mobile/sam-node-ffi/): Contains CGO-exported functions (StartNode,StopNode,EnrollNode,GetNodeID,FreeString) which compile into a C-shared library (.so) or static archive (.a). - Flutter App (
mobile/sam-node-app/): A cross-platform app containing:lib/sam_ffi.dart: The Dart FFI wrapper loading the Go library and exposing Dart methods.lib/main.dart: Simple control UI to enroll and start/stop the background node.
- Local Loopback Communication:
- The Flutter Dart environment controls the node lifecycle (construction, starting, stopping) via FFI.
- Any actual tool registration, discovery, or mesh API queries are performed using standard HTTP JSON-RPC calls over local loopback (
127.0.0.1) to thesam-nodesidecar API.
Make Build Targets
We provide dedicated Makefile targets to automate Go FFI compilation and copy binaries into the mobile app:
1. Build Host FFI (For local desktop testing)
Compiles bin/libsam.so for the host platform:
make mobile-ffi-host
2. Build Android FFI Library
Compiles bin/android/libsam.so targeting Android ARM64 devices:
make mobile-ffi-android
3. Build iOS FFI Library
Compiles bin/ios/libsam.a targeting iOS ARM64 devices:
make mobile-ffi-ios
4. Build Complete Android Release APK
Compiles the FFI library, bundles it inside the Flutter project, and builds the final release APK:
make mobile-app-apk
Local Development Workflow
To make changes to sam-node and run them on a mobile device:
Android Setup
- Compile the Android ARM64 FFI shared library:
make mobile-ffi-android - Copy the library into the Android project’s
jniLibsdirectory:mkdir -p mobile/sam-node-app/android/app/src/main/jniLibs/arm64-v8a cp bin/android/libsam.so mobile/sam-node-app/android/app/src/main/jniLibs/arm64-v8a/libsam.so - Connect your Android device via USB (verify connection with
adb devices). - Run the app:
cd mobile/sam-node-app flutter run
Integration Testing (E2E)
We automate end-to-end integration verification in the CI by running a headless Android Emulator and executing bidirectional MCP discovery:
Local Execution of E2E Script
If you have an active emulator running locally, you can run the full E2E orchestration test:
./mobile/mobile_e2e.sh
What the E2E test validates:
- Starts a local Mock OIDC Server and sam-hub process on the host.
- Registers a dummy tool (
host-tool) on a host-level sam-node. - Boots the Android Emulator, installs the FFI-embedded app, and starts the node inside the emulator.
- Registers an
emulator-toolinside the emulator app. - Asserts bidirectional discovery:
- The emulator app successfully discovers the host’s
host-toolvia the mesh. - The host node successfully discovers the emulator’s
emulator-toolvia the mesh.
- The emulator app successfully discovers the host’s
- Terminates all background processes and cleans up directories on completion.