Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

206 Commits

Repository files navigation

jni

Go ReferenceGo Report CardLicense: CC0-1.0Go VersionAsk AI

Idiomatic Go bindings for the Java Native Interface and 53 Android Java API packages, auto-generated from YAML specs to ensure full coverage and easy maintenance.

For remote Android API access over gRPC, see jni-proxy.

Android Interfaces for Go

This project is part of a family of three Go libraries that cover the major Android interface surfaces. Each wraps a different layer of the Android platform:

graph TD
subgraph "Go application"
GO["Go code"]
end
subgraph "Interface libraries"
NDK["<b>ndk</b><br/>C API bindings via cgo"]
JNI["<b>jni</b><br/>Java API bindings via JNI+cgo"]
AIDL["<b>binder</b><br/>Binder IPC, pure Go"]
end
subgraph "Android platform"
CAPI["NDK C libraries<br/>(libcamera2ndk, libaaudio,<br/>libEGL, libvulkan, ...)"]
JAVA["Java SDK<br/>(android.bluetooth,<br/>android.location, ...)"]
BINDER["/dev/binder<br/>kernel driver"]
SYSSVCS["System services<br/>(ActivityManager,<br/>PowerManager, ...)"]
end
GO --> NDK
GO --> JNI
GO --> AIDL
NDK -- "cgo / #include" --> CAPI
JNI -- "cgo / JNIEnv*" --> JAVA
AIDL -- "ioctl syscalls" --> BINDER
BINDER --> SYSSVCS
JAVA -. "internally uses" .-> BINDER
CAPI -. "some use" .-> BINDER
Loading
LibraryInterfaceRequiresBest for
ndkAndroid NDK C APIscgo + NDK toolchainHigh-performance hardware access: camera, audio, sensors, OpenGL/Vulkan, media codecs
jni (this project)Java Android SDK via JNIcgo + JNI + JVM/ARTJava-only APIs with no NDK equivalent: Bluetooth, WiFi, NFC, location, telephony, content providers
binderBinder IPC (system services)pure Go (no cgo)Direct system service calls without Java: works on non-Android Linux with binder, minimal footprint

When to use which

  • Start with ndk when the NDK provides a C API for what you need (camera, audio, sensors, EGL/Vulkan, media codecs). These are the lowest-latency, lowest-overhead bindings since they go straight from Go to the C library via cgo.

  • Use jni when you need a Java Android SDK API that the NDK does not expose. Examples: Bluetooth discovery, WiFi P2P, NFC tag reading, location services, telephony, content providers, notifications. JNI is also the right choice when you need to interact with Java components (Activities, Services, BroadcastReceivers) or when you need the gRPC remote-access layer.

  • Use binder when you want pure-Go access to Android system services without any cgo dependency. This is ideal for lightweight tools, CLI programs, or scenarios where you want to talk to the binder driver from a non-Android Linux system. AIDL covers the same system services that Java SDK wraps (ActivityManager, PowerManager, etc.) but at the wire-protocol level.

  • Combine them when your application needs multiple layers. For example, a streaming app might use ndk for camera capture and audio encoding, jni for Bluetooth controller discovery, and binder for querying battery status from a companion daemon.

How they relate to each other

All three libraries talk to the same Android system services, but through different paths:

  • The NDK C APIs are provided by Google as stable C interfaces to Android platform features. Some (camera, sensors, audio) internally use binder IPC to talk to system services; others (EGL, Vulkan, OpenGL) talk directly to kernel drivers. The ndk library wraps these C APIs via cgo.
  • The Java SDK uses binder IPC internally for system service access (BluetoothManager, LocationManager, etc.), routing calls through the Android Runtime (ART/Dalvik). The jni library calls into these Java APIs via the JNI C interface and cgo.
  • The AIDL binder protocol is the underlying IPC mechanism that system-facing NDK and Java SDK APIs use. The binder library implements this protocol directly in pure Go, bypassing both C and Java layers entirely.

Usage Examples

Bluetooth

import"github.com/AndroidGoLab/jni/bluetooth"adapter, _:=bluetooth.NewAdapter(ctx)
deferadapter.Close()
enabled, _:=adapter.IsEnabled()
name, _:=adapter.GetName()
addr, _:=adapter.GetAddress()
fmt.Printf("Bluetooth: %s (%s), enabled=%v\n", name, addr, enabled)

Location

import"github.com/AndroidGoLab/jni/location"mgr, _:=location.NewManager(ctx)
defermgr.Close()
locObj, _:=mgr.GetLastKnownLocation(location.GpsProvider)
fmt.Printf("Location: %v\n", locObj)

WiFi

import"github.com/AndroidGoLab/jni/net/wifi"mgr, _:=wifi.NewManager(ctx)
defermgr.Close()
enabled, _:=mgr.IsWifiEnabled()
fmt.Println("WiFi enabled:", enabled)

Notifications

import"github.com/AndroidGoLab/jni/app/notification"mgr, _:=notification.NewManager(ctx)
defermgr.Close()
ch, _:=notification.NewChannel(vm, "alerts", "Alerts",
int32(notification.ImportanceHigh))
mgr.CreateNotificationChannel(ch.Obj)
b, _:=notification.NewBuilder(vm, appCtx, "alerts")
b.SetSmallIcon1_1(iconResID)
b.SetContentTitle("Hello from Go!")
b.SetContentText("Posted via JNI — no Java code")
notif, _:=b.Build()
mgr.Notify2(1, notif)

Running Examples

All 53 examples are self-contained NativeActivity apps — zero Java code. Each lives in examples/<name>/ with its own Makefile:

cd examples/alarm
make run # build APK → install → grant permissions → launch

Build and install all examples at once from the repo root:

make examples # builds all 53 APKs

See examples/ for the full list.

Supported Packages

53 Android API packages organized in a Java SDK-mirroring hierarchy:

Android APIGo PackageImport Path
Application Framework
appappgithub.com/AndroidGoLab/jni/app
alarmalarmgithub.com/AndroidGoLab/jni/app/alarm
downloaddownloadgithub.com/AndroidGoLab/jni/app/download
jobjobgithub.com/AndroidGoLab/jni/app/job
notificationnotificationgithub.com/AndroidGoLab/jni/app/notification
usageusagegithub.com/AndroidGoLab/jni/app/usage
accountsaccountsgithub.com/AndroidGoLab/jni/accounts
Bluetooth
bluetoothbluetoothgithub.com/AndroidGoLab/jni/bluetooth
Content & Storage
clipboardclipboardgithub.com/AndroidGoLab/jni/content/clipboard
pmpmgithub.com/AndroidGoLab/jni/content/pm
preferencespreferencesgithub.com/AndroidGoLab/jni/content/preferences
resolverresolvergithub.com/AndroidGoLab/jni/content/resolver
permissionpermissiongithub.com/AndroidGoLab/jni/content/permission
Graphics
pdfpdfgithub.com/AndroidGoLab/jni/graphics/pdf
Hardware
biometricbiometricgithub.com/AndroidGoLab/jni/hardware/biometric
cameracameragithub.com/AndroidGoLab/jni/hardware/camera
irirgithub.com/AndroidGoLab/jni/hardware/ir
lightslightsgithub.com/AndroidGoLab/jni/hardware/lights
usbusbgithub.com/AndroidGoLab/jni/hardware/usb
Health
healthconnectgithub.com/AndroidGoLab/jni/health/connect
Location
locationlocationgithub.com/AndroidGoLab/jni/location
Media
audiomanageraudiomanagergithub.com/AndroidGoLab/jni/media/audiomanager
playerplayergithub.com/AndroidGoLab/jni/media/player
projectionprojectiongithub.com/AndroidGoLab/jni/media/projection
recorderrecordergithub.com/AndroidGoLab/jni/media/recorder
sessionsessiongithub.com/AndroidGoLab/jni/media/session
Networking
netnetgithub.com/AndroidGoLab/jni/net
nsdnsdgithub.com/AndroidGoLab/jni/net/nsd
wifiwifigithub.com/AndroidGoLab/jni/net/wifi
p2pp2pgithub.com/AndroidGoLab/jni/net/wifi/p2p
rttrttgithub.com/AndroidGoLab/jni/net/wifi/rtt
NFC
nfcnfcgithub.com/AndroidGoLab/jni/nfc
OS Services
batterybatterygithub.com/AndroidGoLab/jni/os/battery
buildbuildgithub.com/AndroidGoLab/jni/os/build
environmentenvironmentgithub.com/AndroidGoLab/jni/os/environment
keyguardkeyguardgithub.com/AndroidGoLab/jni/os/keyguard
powerpowergithub.com/AndroidGoLab/jni/os/power
storagestoragegithub.com/AndroidGoLab/jni/os/storage
vibratorvibratorgithub.com/AndroidGoLab/jni/os/vibrator
Providers
documentsdocumentsgithub.com/AndroidGoLab/jni/provider/documents
mediastoremediagithub.com/AndroidGoLab/jni/provider/media
settingssettingsgithub.com/AndroidGoLab/jni/provider/settings
Security
keystorekeystoregithub.com/AndroidGoLab/jni/security/keystore
credentialscredentialsgithub.com/AndroidGoLab/jni/credentials
omapiomapigithub.com/AndroidGoLab/jni/se/omapi
Telecom
telecomtelecomgithub.com/AndroidGoLab/jni/telecom
telephonytelephonygithub.com/AndroidGoLab/jni/telephony
UI
displaydisplaygithub.com/AndroidGoLab/jni/view/display
inputmethodinputmethodgithub.com/AndroidGoLab/jni/view/inputmethod
toasttoastgithub.com/AndroidGoLab/jni/widget/toast
Other
companioncompaniongithub.com/AndroidGoLab/jni/companion
printprintgithub.com/AndroidGoLab/jni/print
speechspeechgithub.com/AndroidGoLab/jni/speech

Architecture

The project converts Android Java API specifications into safe, idiomatic Go packages through four code generation stages:

flowchart TD
JNISPEC["spec/jni.yaml"]
JNIOVER["spec/overlays/jni.yaml"]
JNITMPL["templates/jni/"]
JAVASPEC["spec/java/*.yaml"]
JAVAOVER["spec/overlays/java/*.yaml"]
JAVATMPL["templates/java/"]
CAPI["capi/*.go"]
ROOT["*.go (VM, Env, Class, Object, ...)"]
PKGS["{package}/*.go (53 packages)"]
JNISPEC --> S1
JNIOVER --> S1
JNITMPL --> S1
subgraph S1["jnigen"]
direction LR
S1D["Generates CGo bindings + idiomatic JNI types"]
end
S1 --> CAPI
S1 --> ROOT
JAVASPEC --> S2
JAVAOVER --> S2
JAVATMPL --> S2
subgraph S2["javagen"]
direction LR
S2D["Generates Android API wrapper packages"]
end
S2 --> PKGS
style JNISPEC fill:#fff3cd,color:#000
style JNIOVER fill:#fff3cd,color:#000
style JNITMPL fill:#fff3cd,color:#000
style JAVASPEC fill:#fff3cd,color:#000
style JAVAOVER fill:#fff3cd,color:#000
style JAVATMPL fill:#fff3cd,color:#000
style CAPI fill:#d4edda,color:#000
style ROOT fill:#cce5ff,color:#000
style PKGS fill:#cce5ff,color:#000
Loading

Legend: Yellow = hand-written inputs, Green = generated intermediates, Blue = final consumer-facing output.

Layers

  1. Raw CGo Layer (capi/) — Direct C bindings to JNI via vtable dispatch. Generated by jnigen.

  2. Idiomatic JNI Layer (root package) — Safe Go types: VM, Env, Class, Object, Value, String, Array, MethodID, FieldID. All JNI exceptions converted to Go errors. Thread safety via VM.Do(). Generated by jnigen.

  3. Android API Layer (53 packages) — High-level wrappers for Android system services. Each package provides a Manager type obtained via NewManager(ctx), with methods that call through JNI. Generated by javagen.

  4. gRPC Layer — See jni-proxy for gRPC remote access (proto/grpc generation lives in that repo).

Project Layout

.
├── *.go # Core JNI types (VM, Env, Class, Object, ...)
├── capi/ # Raw CGo bindings to JNI C API
├── internal/ # Internal: exception handling, test JVM
│
├── app/ # Android API wrappers (Java SDK hierarchy)
│ ├── alarm/, download/, ...
├── bluetooth/
├── hardware/
│ ├── camera/, usb/, ...
├── media/
│ ├── audiomanager/, player/, ...
├── net/
│ ├── wifi/, nsd/, ...
├── os/
│ ├── power/, battery/, ...
├── ... # (53 packages total)
│
├── tools/ # Code generators
│ ├── jnigen/ # Core JNI + capi generation
│ ├── javagen/ # Android API package generation
│ └── specgen/ # YAML spec generation from .class files
├── spec/ # YAML API specifications
│ ├── jni.yaml # JNI C API spec
│ ├── java/ # Per-package Android API specs
│ └── overlays/ # Hand-written customizations
├── templates/ # Go text templates for code generation
│ ├── jni/
│ └── java/
│
├── ref/android/ # Reference .class files
└── examples/ # Per-package usage examples (53 NativeActivity apps)
├── common/ui/ # Shared NativeActivity lifecycle + Canvas renderer
├── alarm/, battery/, ... # One directory per package
└── apk.mk # Shared APK build rules

Make Targets

TargetDescriptionRequires
make generateRun all generators (specs + jni + java)JDK + Android SDK
make specsGenerate YAML specs from .class filesJDK + Android SDK
make jniGenerate core JNI + capi--
make javaGenerate Android API packages--
make testRun all testsJDK
make test-toolsRun generator tests only--
make examplesBuild all 53 example APKsAndroid SDK + NDK
make buildCross-compile for android/arm64Android NDK
make proveVerify Lean 4 proofselan/lake
make lintRun golangci-lintgolangci-lint
make cleanRemove all generated files--

E2E Test Verification

The JNI bindings and generated Android API packages are verified via jni-proxy E2E tests against real hardware.

Verified platforms (click to expand)
TypeDeviceAndroidAPIABIBuildDatePassedTotal
PhonePixel 8a1636arm64-v8aBP4A.260205.0012026-03-152121
Emulatorsdk_gphone64_x86_641535x86_642026-03-142121

Tests cover: JNI version, class operations, method lookup + call, string round-trip, object operations, handle lifecycle, field access, exception handling, and full integration workflows. Camera recording, microphone recording, GPS location, and battery status are also verified on the Pixel 8a.

Adding a New Android API Package

  1. Create spec/java/{package}.yaml with the Java class, methods, and go_import path.
  2. Optionally create spec/overlays/java/{package}.yaml for customizations (extra methods, type overrides, name overrides).
  3. Run make java to generate the Go package.
  4. For gRPC support, see jni-proxy.

About

Go bindings for 137 Android SDK classes — Bluetooth, WiFi, NFC, location, telephony, camera, and more via JNI.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages