Skip to content

feat(pairing)!: report typed PairingState instead of bool - #308

Open
arxdeus wants to merge 2 commits into
Navideck:mainfrom
arxdeus:main
Open

arxdeus wants to merge 2 commits into
Navideck:mainfrom
arxdeus:main

Conversation

@arxdeus

@arxdeus arxdeus commented Sep 15, 2026

Copy link
Copy Markdown

universal_ble resolves user's connect cancellation of Bluetooth pairing as just "not paired", instead of give us exact state

pairingStateStream, onPairingStateChange and the native onPairStateChange callback now emit a PairingState (paired / pairing / rejectedByUser / failed / unpaired).

  • Android: read BluetoothDevice.EXTRA_REASON from ACTION_BOND_STATE_CHANGED and map UNBOND_REASON_AUTH_REJECTED, AUTH_CANCELED and AUTH_TIMEOUT to rejectedByUser.
  • Android: BOND_BONDING no longer completes a pending pair() future; it is surfaced as PairingState.pairing progress.
  • Linux: map BlueZ AuthenticationRejected/Canceled/Timeout to rejectedByUser.

BREAKING CHANGE: pairingStateStream, onPairingStateChange and onPairStateChange expose PairingState instead of bool.

Platforms only reported "paired / not paired", which conflated two very
different outcomes: the user explicitly refusing the system pairing
dialog, and the peripheral being unable to bond at all. Consumers could
not tell them apart, so an app had no way to abort a connection when the
user said no, while still tolerating devices that cannot bond.

`pairingStateStream`, `onPairingStateChange` and the native
`onPairStateChange` callback now emit a `PairingState`
(paired / pairing / rejectedByUser / failed / unpaired).

- Android: read `BluetoothDevice.EXTRA_REASON` from
  ACTION_BOND_STATE_CHANGED and map UNBOND_REASON_AUTH_REJECTED,
  AUTH_CANCELED and AUTH_TIMEOUT to `rejectedByUser`.
- Android: BOND_BONDING no longer completes a pending `pair()` future;
  it is surfaced as `PairingState.pairing` progress.
- Linux: map BlueZ AuthenticationRejected/Canceled/Timeout to
  `rejectedByUser`.

BREAKING CHANGE: `pairingStateStream`, `onPairingStateChange` and
`onPairStateChange` expose `PairingState` instead of `bool`.
The initial PairingState work only classified the outcome on Android and
Linux. Windows kept passing a bool into the regenerated
`OnPairStateChange(..., PairingState, ...)` signature, which no longer
compiles, and Apple reported no pairing outcome at all.

- Windows: map `DevicePairingResultStatus` to `PairingState`, so a
  cancelled prompt or a handler rejection becomes `rejectedByUser` while
  unpairable hardware stays `failed`.
- Apple: CoreBluetooth has no bonding API — pairing is triggered by
  touching an encrypted characteristic, so classify the error of that
  operation and publish the resulting `PairingState`. Errors unrelated to
  the ceremony report nothing instead of a misleading state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant