Initialise jni-utils, or every connect panics
Scanning worked on the tablet and connecting did not, and the reason was
one missing call.
btleplug's Android backend hands Rust its results as Java future objects
wrapped by jni-utils, and every one of those wrappers resolves its class
through a cache. Only `jni_utils::init` fills that cache. droidplug does
not call it — its own `init` registers droidplug's classes and assumes
the application has already done jni-utils' — and nothing else did
either, so the cache held droidplug's seven classes and none of
jni-utils' ten.
That split the BLE stack in half exactly where the symptom appeared.
Scan results arrive on a plain JNI callback and never touch a future, so
scanning was perfect. `connect` is the first path that awaits one, and
`JFuture::from_env` unwraps `get_class("…/future/Future")` — None —
straight into a panic on the runtime thread, taking the trainer
supervisor task with it. What reached the log was "trainer command
dropped — supervisor queue full or closed", which describes the corpse
rather than the cause; the panic itself only appeared under
RustStdoutStderr, and only because the Android target routes stdout to
logcat.
The GATT link was fine throughout, which is what made this confusing to
read: Android logged `onClientConnectionState … status=0 connected=true`
for the trainer a second *after* the task waiting for it had died.
Pinned to 0.1.1 deliberately. The cache is a static inside jni-utils, so
a second copy at a different version is a second, empty cache and the
panic comes back.
Verified on the tablet (Android 16, aarch64): both Click pods connect on
their own, and the trainer reaches state=Controlling with its FTMS
capabilities read back. Zero panics in the process log.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,3 +53,8 @@ keepawake = "0.6.0"
|
||||
btleplug = { workspace = true }
|
||||
jni = "0.19"
|
||||
libc = "0.2"
|
||||
# Pinned to the version btleplug 0.11 resolves to, and it must stay that way:
|
||||
# the class cache `init` populates is a static *inside this crate*, so a second
|
||||
# copy at a different version would be a second, empty cache and `connect`
|
||||
# would go back to panicking.
|
||||
jni-utils = "0.1.1"
|
||||
|
||||
Reference in New Issue
Block a user