Android quickstart
Build the ForestVPN Android tunnel runtime from source with cargo-ndk and bridge it from your VpnService.
The Android surface is the forestvpn-android-jni crate — the tunnel runtime
compiled as a cdylib (libforestvpn_android_jni.so) that your
VpnService drives over a small, stable C ABI.
Honest distribution note: this path is source-only today. There is no prebuilt AAR, no Maven artifact, and no Kotlin/Java wrapper library — you build the shared library from source and bring your own JNI (or JNA) bridge. If that changes, this page will change with it.
Prerequisites
- The Rust toolchain (rustup.rs) with the Android
targets (
rustup target add aarch64-linux-android) cargo-ndk(cargo install cargo-ndk)- The Android NDK, with
ANDROID_NDK_HOMEset - A checkout of the ForestVPN repository
1. Get the source
git clone [email protected]:forestvpn/forestvpn.git
cd forestvpn2. Build the shared library
#!/usr/bin/env bash
# Build the ForestVPN Android tunnel runtime from source (the only
# distribution path today — no prebuilt AAR ships). Run from the repo root.
# Prerequisites: the Rust toolchain, cargo-ndk, and the Android NDK
# (ANDROID_NDK_HOME).
set -euo pipefail
cd forestvpn-sdk
cargo ndk -t arm64-v8a build -p forestvpn-android-jni --release
# → target/aarch64-linux-android/release/libforestvpn_android_jni.soAdd more -t targets (armeabi-v7a, x86_64) as your ABI matrix needs.
Copy the resulting .so into your app module's src/main/jniLibs/<abi>/
directory and load it with System.loadLibrary("forestvpn_android_jni").
3. The C ABI you bridge
The library exports a compact extern "C" surface (see
forestvpn-sdk/crates/forestvpn-android-jni/src/exports.rs — the
authoritative signatures live there):
| Entry point | What it does |
|---|---|
fvpn_android_abi_version | ABI version handshake — check it before anything else |
fvpn_android_initialize | Create a tunnel runtime from an established VpnService TUN fd + a versioned runtime config |
fvpn_android_set_target_state | Drive the tunnel state machine (secured / unsecured) |
fvpn_android_apply_runtime_config | Apply a new runtime config to a live runtime |
fvpn_android_status | Read the runtime's status document |
fvpn_android_last_error_message | Copy the thread-local error message after a failed call |
fvpn_android_shutdown | Tear down and free the runtime handle |
The flow mirrors every other ForestVPN tunnel platform: your VpnService
establishes the TUN interface, hands its fd plus the runtime config from the
control plane to fvpn_android_initialize, then sets the target state to
secured. Status and errors are polled through the same handle.
Verified by
scripts/quickstart-verify/android-jni.sh — asserts the crate exists at the
documented path, that every entry point named above is really exported, and
(when cargo-ndk + the NDK are present) runs the exact build script this
page embeds. Without the Android toolchain the build leg skips loudly.