react-native-nitro-geolocation 1.4.0 → 1.4.1

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.
@@ -50,3 +50,12 @@ internal fun resolveMaxStored(configured: Int?, default: Int): Int {
50
50
  else -> configured
51
51
  }
52
52
  }
53
+
54
+ /**
55
+ * Headless JS is the fallback path when no in-process JS listener received the native event. If a
56
+ * live listener already handled the event, starting Headless JS duplicates delivery and React
57
+ * Native warns when the app did not register NitroBackgroundLocationTask.
58
+ */
59
+ internal fun shouldDispatchHeadlessTask(deliveredToInProcessListener: Boolean): Boolean {
60
+ return !deliveredToInProcessListener
61
+ }
@@ -45,22 +45,27 @@ class NitroBackgroundEventHub {
45
45
  errorListeners.remove(token)
46
46
  }
47
47
 
48
- fun emit(event: BackgroundEventEnvelope) {
48
+ fun emit(event: BackgroundEventEnvelope): Boolean {
49
+ var delivered = eventListeners.isNotEmpty()
49
50
  eventListeners.values.forEach { listener -> dispatch { listener(event) } }
50
51
 
51
52
  when (event.type) {
52
53
  BackgroundEventType.LOCATION -> {
53
54
  event.location?.let { location ->
55
+ delivered = delivered || locationListeners.isNotEmpty()
54
56
  locationListeners.values.forEach { listener -> dispatch { listener(location) } }
55
57
  }
56
58
  }
57
59
  BackgroundEventType.ERROR -> {
58
60
  event.error?.let { error ->
61
+ delivered = delivered || errorListeners.isNotEmpty()
59
62
  errorListeners.values.forEach { listener -> dispatch { listener(error) } }
60
63
  }
61
64
  }
62
65
  else -> Unit
63
66
  }
67
+
68
+ return delivered
64
69
  }
65
70
 
66
71
  // Listeners run inline on the caller's thread (often the broadcast receiver thread). Isolate
@@ -604,7 +604,8 @@ class NitroBackgroundLocationController private constructor(
604
604
  }
605
605
 
606
606
  private fun dispatchEvent(event: BackgroundEventEnvelope) {
607
- eventHub.emit(event)
607
+ val deliveredToInProcessListener = eventHub.emit(event)
608
+ if (!shouldDispatchHeadlessTask(deliveredToInProcessListener)) return
608
609
  // The in-process eventHub already delivered to any live JS listeners; the headless task is
609
610
  // the fallback for when JS is dead. Guard its start: startService from the background can be
610
611
  // rejected (ForegroundServiceStartNotAllowed / IllegalState), which must not crash the
@@ -64,4 +64,14 @@ class BackgroundDecisionsTest {
64
64
  assertEquals(0, resolveMaxStored(0, 10_000))
65
65
  assertEquals(0, resolveMaxStored(-5, 10_000))
66
66
  }
67
+
68
+ @Test
69
+ fun headlessTaskIsSkippedWhenInProcessListenerReceivedEvent() {
70
+ assertFalse(shouldDispatchHeadlessTask(true))
71
+ }
72
+
73
+ @Test
74
+ fun headlessTaskRunsWhenNoInProcessListenerReceivedEvent() {
75
+ assertTrue(shouldDispatchHeadlessTask(false))
76
+ }
67
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-geolocation",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Nitro-powered native geolocation for modern React Native apps",
5
5
  "main": "src/index",
6
6
  "source": "src/index",