feat(android): report key missing and link encryption results (0.1.8, 0.1.9) - #26
Merged
Merged
Conversation
wabicai
approved these changes
Sep 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Android 16+ no longer removes a bond whose keys the device has lost (device wiped, bond removed on the device). It keeps the bond and only broadcasts
android.bluetooth.device.action.KEY_MISSING; GATT just shows a peer disconnect. This release reports that broadcast to JS so the SDK can tell a stale bond from an ordinary disconnect and guide the user to forget the device, instead of looping on "Bluetooth unpaired".Changes
0.1.8 (this change)
ACTION_KEY_MISSINGon API 36+ (string literal, so oldercompileSdkstill builds) and emit a new eventonDeviceKeyMissingwith the device address.supportsKeyMissingEvent/supportsDeviceKeyMissing(): false on older Android and on native builds without this change, so JS never waits for an event that cannot fire.pairDeviceadditionally returnsinitiated, to tell a bonding this call started from one the system started by itself (Android 17 re-pairs on its own after a lost bond).onDeviceKeyMissingsubscriptions are removed individually;onDeviceBondStateis unchanged.0.1.7 (already on npm, never merged)
2371f8fwas published to npm as 0.1.7 fromfix/electron-ble-scan-cachewithout a PR, somainis behind the registry. This branch is stacked on it and brings it intomain: it forwards the hiddenEXTRA_UNBOND_REASONint onBOND_NONE, whichhd-transport-react-nativealready consumes to classify pairing cancel / timeout.Compatibility
Additive only: one new event, one new constant, one new optional result field. iOS is untouched. With an older native binary the new JS helpers report unsupported and behave as a no-op.
Verification
yarn lint,yarn typecheck,yarn testpass.:onekeyfe_react-native-ble-utils:compileDebugKotlinbuilds in the example app.dumpsys activity broadcasts:KEY_MISSINGis an implicit ordered broadcast requiring onlyBLUETOOTH_CONNECT, enqueued ~15 ms after the ACL drop. Not yet exercised end to end on a device with this native build.0.1.9 — link encryption results
On Android 16+ the system encrypts a bonded LE link on its own right after connecting. If a request that needs encryption (the notification CCCD write) is sent before that attempt finishes, the framework retries it by encrypting again with the same stale key; Pro 2 firmware tolerates one key failure per link and drops the second, before the system re-pair can finish. HCI captures on a Pixel 9a (Android 17) show this is the whole difference between a dropped attempt and one where the pairing request completes.
ACTION_ENCRYPTION_CHANGE(API 36) and emitonDeviceEncryptionChange{ id, status, enabled }for LE links.statusis the HCI status: 0 on success, 6 when the peer lost the bond. Verified on device that the broadcast fires ~7 ms after both successful and failed encryptions.ACTION_ACL_DISCONNECTEDand emitonDeviceAclDisconnected{ id }, so JS knows when an earlier encryption result stops describing the current link (unlike a GATT disconnect, it does not fire while the system keeps the link for another client).supportsEncryptionChangeEvent/supportsDeviceEncryptionChange(); false below API 36 and on older native builds, where neither event fires.android.jar/api-versions.xml(ACTION_ENCRYPTION_CHANGE,EXTRA_ENCRYPTION_STATUS,EXTRA_ENCRYPTION_ENABLED,ACTION_KEY_MISSINGsince 36;EXTRA_TRANSPORTsince 33). Literals keep oldercompileSdkbuilding.Published as 0.1.9 from
cc86db8. Consumed by OneKeyHQ/hardware-js-sdk#951.