Make the Android BLE backend fail loudly and recoverably
Three defects on the path between MainActivity and the scan loop, all of which presented as "no trainer found". initBtleplug ran after super.onCreate, which is a race rather than a clean ordering bug: the super chain dispatches Rust.create(), and tao's ndk_glue spawns a thread to run `run()` on. That thread builds the AppState and starts the scan loop concurrently. Reaching btleplug first hits droidplug's global_adapter(), which is an `expect` — the scan task panics and scanning is dead for the process, silently and only on some phones. Initialising before super.onCreate means the race cannot be lost. The same panic was reachable without any race, because init failure was logged and shrugged off while every later call still went through to `expect`. Failing soft is right; it just needed READY, so the call sites can produce an ordinary "no adapter" instead of taking the task down (NFR-4). MainActivity retries the init on resume, which is idempotent, so a rider who launched with Bluetooth off recovers by going to Settings. Neither of those covers a radio the rider switches off, which btleplug does not model at all: getDefaultAdapter() returns a disabled adapter whose scans just find nothing. MainActivity now watches ACTION_STATE_CHANGED — the quick-settings shade never fires onResume — and pushes the state to Rust, with requestBluetoothEnable coming back the other way so the connection screen can offer the system dialog rather than describing an empty room. Tri-state on purpose: unknown is not off, or a rider with a working radio gets told to switch it on at launch. Also: the adapter hint told Android riders to check BlueZ. Verified on debug and release APKs for aarch64. Release matters separately here — every one of these classes is reached only by name over JNI, so R8 would strip or rename the lot and the failure would appear only in a shipped build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,14 @@
|
||||
-keepclassmembers class * extends android.bluetooth.BluetoothGattCallback { *; }
|
||||
-keepclassmembers class * extends android.bluetooth.le.ScanCallback { *; }
|
||||
|
||||
# Our own JNI entry point, called from MainActivity as an `external fun`.
|
||||
# Our own JNI entry points, called from MainActivity as `external fun`.
|
||||
-keepclasseswithmembernames class paris.tourolle.bikecontrol.MainActivity {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# The one call that goes the other way. Rust resolves it by name and signature
|
||||
# at runtime, so R8 renaming it would leave the "turn Bluetooth on" button doing
|
||||
# nothing in release builds and working perfectly in debug ones.
|
||||
-keepclassmembers class paris.tourolle.bikecontrol.MainActivity {
|
||||
public void requestBluetoothEnable();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user