Sensor Access from Termux

May 29, 2026 ยท View on GitHub

Native Android sensor access from Termux using the NDK (Native Development Kit) ASensorManager API. No root, no JNI, no proot required.

Note: This uses ASensorManager from the Android NDK, loaded via dlsym at runtime. It does not use the termux-sensor command (which relies on the Termux:API Java bridge). The NDK approach provides direct hardware access with higher sample rates and lower latency than the Java bridge (JNI) path.


Summary

9 of 11 standard sensor types confirmed working in my testing on a Samsung S26 Ultra (Android 16, ARM64), using a compiled C binary in native Termux linked against -landroid -ldl.


Hardware Inventory

45 sensors detected via ASensorManager on the test device (Samsung S26 Ultra, Android 16). Counts vary by device and enumeration API: docs/avf-guide.md (the Android Virtualization Framework guide in this repo) reports 42 sensors on Pixel 10 Pro via dumpsys sensorservice. Different devices, different APIs; both numbers are accurate for their respective contexts.

Key sensors:

TypeSensorStatus
1AccelerometerWORKS
2MagnetometerWORKS
4GyroscopeWORKS
5Light (ALS, Ambient Light Sensor)WORKS
6Pressure (Barometer)WORKS
8ProximityWORKS (event-driven, 1 sample per change)
9Gravity (fused)WORKS
10Linear Acceleration (fused)WORKS
11Rotation Vector (fused)Not tested
19Step CounterWORKS (cumulative since reboot, fires on step events)

Device-specific sensors (tilt detector, pick-up gesture, auto-rotation, motion detect, etc.) were also present but not tested. The number and type of device-specific sensors will vary by manufacturer.


Test Results

Test 1: Multi-Sensor Quick Read (5 samples each)

All 8 quick-read sensor types returned data (step counter confirmed separately during walking test):

  • Accelerometer: x=0.49, y=3.23, z=9.25 m/s^2 (phone tilted ~20 deg from vertical)
  • Magnetometer: x=40.3, y=30.1, z=-36.0 uT (indoor magnetic field, stable)
  • Gyroscope: x=0.02, y=-0.08, z=0.04 rad/s (slight rotation while held)
  • Light: 1050-1341 lux (the SI unit for illuminance; bright indoor, fluctuating)
  • Pressure: 1012.95 hPa (hectopascals, the standard meteorological unit; sea-level-equivalent indoor pressure)
  • Proximity: 5.00 cm (binary sensor, max distance = nothing close)
  • Gravity: x=0.94, y=3.14, z=9.24 m/s^2 (device orientation)
  • Linear Accel: near zero (stationary baseline)

Test 2: 30-Second Walking Capture

Accelerometer (300 samples at ~125Hz)

MetricValue
Samples301
Mean magnitude9.824 m/s^2
Min magnitude0.000 m/s^2
Max magnitude10.763 m/s^2
Range10.763 m/s^2

The magnitude oscillation (9.0 to 10.8) around gravity (9.81) is the classic walking signature: each footstrike creates a vertical acceleration spike.

Barometric Pressure (300 samples over 24 seconds)

MetricValue
Samples300
Duration24.0 seconds
Mean1013.910 hPa
Min1013.537 hPa
Max1014.251 hPa
Range0.714 hPa
Net drift-0.033 hPa

0.714 hPa range over 24 seconds. In a standard atmosphere, 1 hPa corresponds to roughly 8.3 meters of altitude. Net drift of only -0.033 hPa shows the sensor is stable: the variation is real environmental signal, not sensor drift.

Gyroscope (291 samples over ~29 seconds)

MetricValue
Samples291
Mean magnitude0.163 rad/s
Min magnitude0.003 rad/s
Max magnitude1.057 rad/s
Range1.053 rad/s

Peak rotation of 1.057 rad/s (about 60 deg/s) indicates turns while walking.


Observations

  1. All standard sensors I tested worked from native Termux using the ASensorManager NDK API loaded via dlsym. No JNI, no root, no proot needed.

  2. Sensor rates: Accelerometer and gyroscope deliver at ~125Hz (10ms). Pressure delivers at ~12.5Hz (80ms). Light at ~5Hz. These rates are device-specific and may vary.

  3. Proximity sensor is event-driven (only fires on change), so it returned just 1 sample in 5 attempts. This is correct behavior.

  4. Step counter reports cumulative steps since last reboot and only fires on step events. A longer capture during active walking would show incrementing values.

  5. The walking signature is clearly visible in the accelerometer data: magnitude oscillates around 9.81 m/s^2 with each footstrike pushing it to ~10.8 and each flight phase dropping it below 9.0.

  6. Barometric pressure captures real environmental signal at 0.01 hPa resolution, sufficient for indoor floor-level detection.


Vendor-Specific Sensors (Samsung)

The sensor reader supports vendor-specific sensor types (type IDs above 65536) via list-scan fallback when getDefaultSensor returns NULL. On my Samsung Galaxy S26 Ultra (Android 16), these Samsung-specific sensors were detected and resolved:

Type IDNameVendorStatus
65605Pocket ModeSamsungResolved (event-driven, awaiting trigger)
65644Drop ClassifierSamsungResolved (event-driven, awaiting trigger)
65648Car Crash DetectSamsungResolved (event-driven, awaiting trigger)
65651Back TapSamsungResolved (event-driven, awaiting trigger)
65655Elevator DetectorSamsungResolved (event-driven, awaiting trigger)

Note: these are event-driven wakeup sensors. They resolve via the NDK API but only produce data when their physical trigger occurs (phone dropped, back tapped, elevator entered, etc.). Availability varies by device manufacturer and model. Non-Samsung devices will have different vendor-specific sensors or none.


Methodology

A small C program was compiled in native Termux, linked against -landroid -ldl. At runtime it:

  1. Loads libandroid.so via dlopen
  2. Resolves ASensorManager_getInstance, ASensorManager_getSensorList, ASensorManager_createEventQueue, etc. via dlsym
  3. Enumerates all available sensors
  4. For each target sensor type, enables it, polls for events, and prints timestamped readings
  5. Disables the sensor and moves to the next

No root permissions, no Java bridge, no proot environment required. The binary runs directly in the native Termux environment.


Reproducing

To build the sensor reader, you need:

pkg install clang -y

Write a C file that uses dlopen("libandroid.so", RTLD_NOW) and resolves the ASensorManager_* functions. Compile with:

clang sensor-reader.c -o sensor-reader -landroid -ldl
./sensor-reader list        # enumerate sensors
./sensor-reader 1 5         # read 5 samples from accelerometer (type 1)

The Android NDK sensor types are defined in <android/sensor.h>. The numeric type codes (1=accelerometer, 2=magnetometer, etc.) are stable across Android versions.


Tested on Android 16 device (ARM64), native Termux, March 2026.

Last updated: 2026-05-29.