expo-beacon 0.6.9 → 0.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -348,7 +348,12 @@ class BeaconForegroundService : Service(), BeaconConsumer {
348
348
  missCounters[region.uniqueId] = count
349
349
 
350
350
  if (enteredRegions.contains(region.uniqueId) && count >= EXIT_MISS_THRESHOLD) {
351
- cancelTimeout(region.uniqueId)
351
+ // Do NOT cancel the timeout here. A miss-based exit is triggered by BLE
352
+ // scan gaps (unreliable signal disappearance), not a confirmed physical
353
+ // departure. Cancelling the timeout here would prevent it from ever firing
354
+ // when the configured timeout (e.g. 25 s) exceeds the miss window (~21 s).
355
+ // The timeout runnable fires unconditionally; distance-based exits still
356
+ // call cancelTimeout() reliably when the beacon moves out of range.
352
357
  enteredRegions.remove(region.uniqueId)
353
358
  missCounters[region.uniqueId] = 0
354
359
  enterCounters[region.uniqueId] = 0
@@ -458,10 +463,11 @@ class BeaconForegroundService : Service(), BeaconConsumer {
458
463
  cancelTimeout(region.uniqueId)
459
464
  val runnable = Runnable {
460
465
  timeoutRunnables.remove(region.uniqueId)
461
- // Only fire if the beacon is still in range
462
- if (enteredRegions.contains(region.uniqueId)) {
463
- sendBeaconBroadcast(region, "timeout", -1.0)
464
- }
466
+ // Fire unconditionally. A miss-based exit may have cleared enteredRegions before
467
+ // the timer elapsed (BLE gaps can cause false exits at ~21 s), but the beacon
468
+ // may still be physically present. Distance-based exits call cancelTimeout() so
469
+ // this runnable is never queued when the beacon has genuinely moved away.
470
+ sendBeaconBroadcast(region, "timeout", -1.0)
465
471
  }
466
472
  timeoutRunnables[region.uniqueId] = runnable
467
473
  timeoutHandler.postDelayed(runnable, seconds * 1000L)
@@ -1078,7 +1078,7 @@ public class ExpoBeaconModule: Module {
1078
1078
  eddystoneEnterCounters[identifier] = 0
1079
1079
  eddystoneExitCounters[identifier] = 0
1080
1080
  eddystoneLatestSeen.removeValue(forKey: identifier)
1081
- cancelEddystoneTimeout(identifier: identifier)
1081
+ // Do NOT cancel the timeout here — same reason as iBeacon miss-based exit.
1082
1082
 
1083
1083
  let ns = paired["namespace"] as? String ?? ""
1084
1084
  let inst = paired["instance"] as? String ?? ""
@@ -1108,8 +1108,10 @@ public class ExpoBeaconModule: Module {
1108
1108
  let work = DispatchWorkItem { [weak self] in
1109
1109
  guard let self = self else { return }
1110
1110
  self.beaconTimeoutTimers.removeValue(forKey: identifier)
1111
- // Only fire if the beacon is still in range
1112
- guard self.enteredRegions.contains(identifier) else { return }
1111
+ // Fire unconditionally. A miss-based exit may have cleared enteredRegions before
1112
+ // the timer elapsed (ranging gaps can cause false exits), but the beacon may still
1113
+ // be physically present. Distance-based exits call cancelBeaconTimeout() so this
1114
+ // work item is cancelled before it runs on genuine out-of-range departures.
1113
1115
  self.sendLoggedEvent("onBeaconTimeout", self.makeBeaconEventParams(identifier: identifier, beacon: beacon))
1114
1116
  }
1115
1117
  beaconTimeoutTimers[identifier] = work
@@ -1130,7 +1132,7 @@ public class ExpoBeaconModule: Module {
1130
1132
  let work = DispatchWorkItem { [weak self] in
1131
1133
  guard let self = self else { return }
1132
1134
  self.eddystoneTimeoutTimers.removeValue(forKey: identifier)
1133
- guard self.eddystoneEnteredRegions.contains(identifier) else { return }
1135
+ // Fire unconditionally same reason as iBeacon timeout.
1134
1136
  self.sendLoggedEvent("onEddystoneTimeout", [
1135
1137
  "identifier": identifier,
1136
1138
  "namespace": namespace,
@@ -1377,7 +1379,11 @@ public class ExpoBeaconModule: Module {
1377
1379
  missCounters[identifier] = 0
1378
1380
  enterCounters[identifier] = 0
1379
1381
  exitCounters[identifier] = 0
1380
- cancelBeaconTimeout(identifier: identifier)
1382
+ // Do NOT cancel the timeout here. A miss-based exit is triggered by
1383
+ // ranging gaps (e.g. accuracy == -1), not a confirmed physical departure.
1384
+ // Cancelling here prevents the timeout from firing when it is longer than
1385
+ // the miss window. Distance-based exits call cancelBeaconTimeout() so the
1386
+ // timer is still cancelled on genuine out-of-range events.
1381
1387
 
1382
1388
  // Look up region info for the exit event payload
1383
1389
  let region = monitoredRegions.first { $0.identifier == identifier }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-beacon",
3
- "version": "0.6.9",
3
+ "version": "0.6.11",
4
4
  "description": "Expo module for scanning, pairing, and monitoring iBeacons on Android and iOS",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",