react-native-geofence-manager 0.1.0-beta.11 → 0.1.0-beta.13

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.
Files changed (52) hide show
  1. package/README.md +173 -37
  2. package/android/src/main/AndroidManifest.xml +17 -16
  3. package/android/src/main/java/com/geofencemanager/GeofenceBroadcastReceiver.kt +133 -0
  4. package/android/src/main/java/com/geofencemanager/GeofenceHeadlessTaskService.kt +98 -141
  5. package/android/src/main/java/com/geofencemanager/GeofenceManagerModule.kt +187 -154
  6. package/ios/GeofenceManager.mm +21 -21
  7. package/lib/module/NativeGeofenceManager.js +1 -7
  8. package/lib/module/NativeGeofenceManager.js.map +1 -1
  9. package/lib/module/geofenceDebugLog.js +22 -0
  10. package/lib/module/geofenceDebugLog.js.map +1 -0
  11. package/lib/module/index.js +79 -35
  12. package/lib/module/index.js.map +1 -1
  13. package/lib/module/models/GeofenceEvent.js +4 -0
  14. package/lib/module/models/GeofenceEvent.js.map +1 -0
  15. package/lib/module/models/GeofenceEventType.js +2 -0
  16. package/lib/module/models/GeofenceEventType.js.map +1 -0
  17. package/lib/module/models/GeofenceModel.js +2 -0
  18. package/lib/module/models/GeofenceModel.js.map +1 -0
  19. package/lib/module/models/index.js +6 -0
  20. package/lib/module/models/index.js.map +1 -0
  21. package/lib/module/package.json +1 -0
  22. package/lib/typescript/package.json +1 -0
  23. package/lib/typescript/src/NativeGeofenceManager.d.ts +3 -16
  24. package/lib/typescript/src/NativeGeofenceManager.d.ts.map +1 -1
  25. package/lib/typescript/src/geofenceDebugLog.d.ts +3 -0
  26. package/lib/typescript/src/geofenceDebugLog.d.ts.map +1 -0
  27. package/lib/typescript/src/index.d.ts +27 -26
  28. package/lib/typescript/src/index.d.ts.map +1 -1
  29. package/lib/typescript/src/models/GeofenceEvent.d.ts +11 -0
  30. package/lib/typescript/src/models/GeofenceEvent.d.ts.map +1 -0
  31. package/lib/typescript/src/models/GeofenceEventType.d.ts +2 -0
  32. package/lib/typescript/src/models/GeofenceEventType.d.ts.map +1 -0
  33. package/lib/typescript/src/models/GeofenceModel.d.ts +8 -0
  34. package/lib/typescript/src/models/GeofenceModel.d.ts.map +1 -0
  35. package/lib/typescript/src/models/index.d.ts +4 -0
  36. package/lib/typescript/src/models/index.d.ts.map +1 -0
  37. package/package.json +16 -15
  38. package/src/NativeGeofenceManager.ts +4 -29
  39. package/src/geofenceDebugLog.ts +28 -0
  40. package/src/index.tsx +99 -71
  41. package/src/models/GeofenceEvent.ts +11 -0
  42. package/src/models/GeofenceEventType.ts +1 -0
  43. package/src/models/GeofenceModel.ts +7 -0
  44. package/src/models/index.ts +3 -0
  45. package/android/src/main/java/com/geofencemanager/GeofenceReceiver.kt +0 -192
  46. package/android/src/main/java/com/geofencemanager/RegionManager.kt +0 -387
  47. package/lib/commonjs/NativeGeofenceManager.js +0 -15
  48. package/lib/commonjs/NativeGeofenceManager.js.map +0 -1
  49. package/lib/commonjs/index.js +0 -47
  50. package/lib/commonjs/index.js.map +0 -1
  51. package/lib/commonjs/package.json +0 -1
  52. package/react-native.config.js +0 -11
@@ -1,193 +1,226 @@
1
1
  package com.geofencemanager
2
2
 
3
+ import android.app.PendingIntent
4
+ import android.content.ComponentName
5
+ import android.content.Context
6
+ import android.content.Intent
7
+ import android.content.SharedPreferences
3
8
  import android.util.Log
4
- import com.facebook.react.bridge.Arguments
5
- import com.facebook.react.bridge.LifecycleEventListener
6
9
  import com.facebook.react.bridge.Promise
7
10
  import com.facebook.react.bridge.ReactApplicationContext
8
11
  import com.facebook.react.bridge.ReadableArray
9
12
  import com.facebook.react.bridge.ReadableMap
10
- import com.facebook.react.bridge.WritableArray
13
+ import com.google.android.gms.location.Geofence
14
+ import com.google.android.gms.location.GeofencingClient
15
+ import com.google.android.gms.location.GeofencingRequest
16
+ import com.google.android.gms.location.LocationServices
17
+ import org.json.JSONArray
18
+ import org.json.JSONObject
11
19
 
12
20
  class GeofenceManagerModule(reactContext: ReactApplicationContext) :
13
- NativeGeofenceManagerSpec(reactContext), LifecycleEventListener {
21
+ NativeGeofenceManagerSpec(reactContext) {
14
22
 
15
23
  companion object {
24
+ private const val TAG = "GeofenceManager"
16
25
  const val NAME = "GeofenceManager"
17
- private const val TAG = "GeofenceManagerModule"
18
- private const val MAX_REGIONS = 100
19
- }
26
+ const val GEOFENCE_ACTION = "com.geofencemanager.GEOFENCE_TRANSITION"
27
+ const val GEOFENCE_HEADLESS_TASK_NAME = "GeofenceManagerTransition"
28
+ private const val GEOFENCE_REQUEST_CODE = 12345
29
+ private const val PREFS_NAME = "GeofenceManagerPrefs"
30
+ private const val PREFS_KEY_DETAILS = "geofence_details"
31
+ private const val PREFS_KEY_LAST_ADD_AT = "geofence_last_add_at"
32
+ private const val GRACE_PERIOD_MS = 90_000L
33
+
34
+ fun isWithinGracePeriod(context: Context): Boolean {
35
+ val lastAdd = getPrefs(context).getLong(PREFS_KEY_LAST_ADD_AT, 0L)
36
+ if (lastAdd == 0L) return false
37
+ return System.currentTimeMillis() - lastAdd < GRACE_PERIOD_MS
38
+ }
20
39
 
21
- init {
22
- Log.d(TAG, "════════════════════════════════════════")
23
- Log.d(TAG, "🚀 GeofenceManagerModule INICIALIZADO")
24
- Log.d(TAG, "📱 ReactContext: $reactContext")
25
- Log.d(TAG, "════════════════════════════════════════")
26
- GeofenceReceiver.reactContext = reactContext
27
- reactContext.addLifecycleEventListener(this)
28
- }
40
+ @Volatile
41
+ var reactContextRef: ReactApplicationContext? = null
42
+
43
+ private val geofenceNames = mutableMapOf<String, String>()
44
+ private val geofenceDetailsMap = mutableMapOf<String, GeofenceDetails>()
45
+
46
+ data class GeofenceDetails(
47
+ val id: String,
48
+ val name: String?,
49
+ val latitude: Double,
50
+ val longitude: Double,
51
+ val radius: Float
52
+ )
53
+
54
+ private fun getPrefs(context: Context): SharedPreferences =
55
+ context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
56
+
57
+ private fun loadDetailsFromPrefs(context: Context) {
58
+ synchronized(geofenceDetailsMap) {
59
+ if (geofenceDetailsMap.isNotEmpty()) return@synchronized
60
+ val json = getPrefs(context).getString(PREFS_KEY_DETAILS, null) ?: return@synchronized
61
+ try {
62
+ val arr = JSONArray(json)
63
+ for (i in 0 until arr.length()) {
64
+ val o = arr.getJSONObject(i)
65
+ val d = GeofenceDetails(
66
+ id = o.getString("id"),
67
+ name = if (o.has("name")) o.optString("name").takeIf { it.isNotEmpty() } else null,
68
+ latitude = o.getDouble("latitude"),
69
+ longitude = o.getDouble("longitude"),
70
+ radius = o.getDouble("radius").toFloat()
71
+ )
72
+ geofenceDetailsMap[d.id] = d
73
+ d.name?.let { geofenceNames[d.id] = it }
74
+ }
75
+ } catch (e: Exception) {
76
+ Log.w(TAG, "loadDetailsFromPrefs failed", e)
77
+ }
78
+ }
79
+ }
29
80
 
30
- override fun getName(): String = NAME
81
+ fun getGeofenceName(id: String): String? = geofenceNames[id]
31
82
 
32
- override fun onHostResume() {
33
- Log.d(TAG, "🔄 onHostResume() - App voltou ao foreground")
34
- Log.d(TAG, " └─ Atualizando reactContext no GeofenceReceiver")
35
- GeofenceReceiver.reactContext = reactApplicationContext
83
+ fun getGeofenceDetails(context: Context, id: String): GeofenceDetails? {
84
+ geofenceDetailsMap[id]?.let { return it }
85
+ loadDetailsFromPrefs(context)
86
+ return geofenceDetailsMap[id]
87
+ }
36
88
  }
37
89
 
38
- override fun onHostPause() {
39
- Log.d(TAG, "⏸️ onHostPause() - App foi para background")
90
+ init {
91
+ Log.i(TAG, "Module init: package=${reactContext.packageName} hasActivity=${reactContext.currentActivity != null}")
92
+ // Só guardar o contexto que tem Activity (tela principal). O contexto da headless task
93
+ // não tem currentActivity; se o armazenarmos, os eventos em foreground (dwell/exit)
94
+ // seriam emitidos para ele e o listener registrado na tela nunca receberia.
95
+ if (reactContext.currentActivity != null) {
96
+ GeofenceManagerModule.reactContextRef = reactContext
97
+ Log.i(TAG, "Module init: reactContextRef set (foreground JS will receive DeviceEventEmitter events)")
98
+ } else {
99
+ Log.w(TAG, "Module init: no currentActivity — reactContextRef NOT updated (normal for some init paths)")
100
+ }
40
101
  }
41
102
 
42
- override fun onHostDestroy() {
43
- Log.d(TAG, "💀 onHostDestroy() - App está sendo destruído")
103
+ private val applicationContext: Context = reactContext.applicationContext
104
+ private val geofencingClient: GeofencingClient =
105
+ LocationServices.getGeofencingClient(applicationContext)
106
+ private var geofencePendingIntent: PendingIntent? = null
107
+
108
+ private fun getPendingIntent(): PendingIntent {
109
+ geofencePendingIntent?.let {
110
+ Log.d(TAG, "getPendingIntent: reusing existing PendingIntent")
111
+ return it
112
+ }
113
+ Log.i(TAG, "getPendingIntent: creating new PendingIntent -> GeofenceBroadcastReceiver action=$GEOFENCE_ACTION")
114
+ val intent = Intent(applicationContext, GeofenceBroadcastReceiver::class.java).apply {
115
+ action = GEOFENCE_ACTION
116
+ setPackage(applicationContext.packageName)
117
+ component = ComponentName(applicationContext, GeofenceBroadcastReceiver::class.java)
118
+ }
119
+ geofencePendingIntent = PendingIntent.getBroadcast(
120
+ applicationContext,
121
+ GEOFENCE_REQUEST_CODE,
122
+ intent,
123
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
124
+ )
125
+ return geofencePendingIntent!!
44
126
  }
45
127
 
46
- override fun start(regions: ReadableArray, options: ReadableMap?, promise: Promise) {
47
- Log.d(TAG, "════════════════════════════════════════")
48
- Log.d(TAG, "▶️ START() CHAMADO")
49
- Log.d(TAG, "════════════════════════════════════════")
50
- Log.d(TAG, "📊 Parâmetros recebidos:")
51
- Log.d(TAG, " └─ Quantidade de regiões: ${regions.size()}")
52
- Log.d(TAG, " └─ Options: $options")
128
+ override fun getName(): String = NAME
53
129
 
130
+ override fun addGeofences(geofences: ReadableArray, promise: Promise) {
131
+ Log.i(TAG, "addGeofences: start, arraySize=${geofences.size()}")
54
132
  try {
55
- if (regions.size() > MAX_REGIONS) {
56
- Log.e(TAG, "❌ ERRO: Limite de regiões excedido!")
57
- Log.e(TAG, " └─ Máximo permitido: $MAX_REGIONS")
58
- Log.e(TAG, " └─ Recebido: ${regions.size()}")
59
- promise.reject(
60
- "GEOFENCE_LIMIT_EXCEEDED",
61
- "Limite máximo de $MAX_REGIONS regiões excedido. Recebido: ${regions.size()}"
133
+ val list = mutableListOf<Geofence>()
134
+ for (i in 0 until geofences.size()) {
135
+ val item: ReadableMap = geofences.getMap(i) ?: run {
136
+ Log.w(TAG, "addGeofences: index $i skipped (null map)")
137
+ continue
138
+ }
139
+ val id = item.getString("id") ?: run {
140
+ Log.w(TAG, "addGeofences: index $i skipped (missing id)")
141
+ continue
142
+ }
143
+ val name = if (item.hasKey("name")) item.getString("name") else null
144
+ val lat = item.getDouble("latitude")
145
+ val lng = item.getDouble("longitude")
146
+ val radius = if (item.hasKey("radius")) item.getDouble("radius").toFloat() else 100f
147
+ synchronized(GeofenceManagerModule.geofenceNames) {
148
+ if (name != null) GeofenceManagerModule.geofenceNames[id] = name
149
+ GeofenceManagerModule.geofenceDetailsMap[id] = GeofenceDetails(id, name, lat, lng, radius)
150
+ }
151
+ list.add(
152
+ Geofence.Builder()
153
+ .setRequestId(id)
154
+ .setCircularRegion(lat, lng, radius)
155
+ .setExpirationDuration(Geofence.NEVER_EXPIRE)
156
+ .setLoiteringDelay(30_000)
157
+ .setTransitionTypes(
158
+ Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT or Geofence.GEOFENCE_TRANSITION_DWELL
159
+ )
160
+ .build()
62
161
  )
63
- return
162
+ Log.i(TAG, "addGeofences: parsed geofence id=$id lat=$lat lng=$lng radius=$radius")
64
163
  }
65
-
66
- val regionList = parseRegions(regions)
67
- val dwellDelay = options?.takeIf { it.hasKey("dwellDelay") }?.getInt("dwellDelay") ?: 5000
68
- val headlessTaskTimeout = options?.takeIf { it.hasKey("headlessTaskTimeout") }?.getInt("headlessTaskTimeout") ?: 30000
69
-
70
- Log.d(TAG, "⚙️ Configurações:")
71
- Log.d(TAG, " └─ dwellDelay: ${dwellDelay}ms")
72
- Log.d(TAG, " └─ headlessTaskTimeout: ${headlessTaskTimeout}ms")
73
- Log.d(TAG, "📍 Regiões parseadas: ${regionList.size}")
74
- regionList.forEachIndexed { index, region ->
75
- Log.d(TAG, " └─ [$index] id=${region.id}, name=${region.name}")
76
- Log.d(TAG, " └─ lat=${region.latitude}, lng=${region.longitude}, radius=${region.radius}m")
164
+ if (list.isEmpty()) {
165
+ Log.e(TAG, "addGeofences: no valid geofences — resolving false (check id/latitude/longitude)")
166
+ promise.resolve(false)
167
+ return
77
168
  }
78
-
79
- Log.d(TAG, "🔄 Chamando RegionManager.registerGeofences()...")
80
-
81
- RegionManager.registerGeofences(
82
- context = reactApplicationContext,
83
- regions = regionList,
84
- dwellDelay = dwellDelay,
85
- headlessTaskTimeout = headlessTaskTimeout,
86
- onSuccess = {
87
- Log.d(TAG, "✅ START() SUCESSO - Promise resolvida")
88
- promise.resolve(null)
89
- },
90
- onError = { errorMessage ->
91
- Log.e(TAG, "❌ START() FALHOU - Promise rejeitada")
92
- Log.e(TAG, " └─ Erro: $errorMessage")
93
- promise.reject("GEOFENCE_ERROR", errorMessage)
169
+ saveDetailsToPrefs(applicationContext)
170
+ val request = GeofencingRequest.Builder()
171
+ .setInitialTrigger(0)
172
+ .addGeofences(list)
173
+ .build()
174
+ Log.i(TAG, "addGeofences: calling GeofencingClient.addGeofences count=${list.size}")
175
+ geofencingClient.addGeofences(request, getPendingIntent())
176
+ .addOnSuccessListener {
177
+ getPrefs(applicationContext).edit()
178
+ .putLong(PREFS_KEY_LAST_ADD_AT, System.currentTimeMillis())
179
+ .apply()
180
+ Log.i(TAG, "addGeofences: SUCCESS — geofences registered with Play Services")
181
+ promise.resolve(true)
182
+ }
183
+ .addOnFailureListener { e ->
184
+ Log.e(TAG, "addGeofences: FAILURE — ${e.message}", e)
185
+ promise.resolve(false)
94
186
  }
95
- )
96
187
  } catch (e: Exception) {
97
- Log.e(TAG, "💥 EXCEÇÃO em start():")
98
- Log.e(TAG, " └─ Message: ${e.message}")
99
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
100
- promise.reject("GEOFENCE_ERROR", e.message)
188
+ Log.e(TAG, "addGeofences: exception", e)
189
+ promise.reject(e)
101
190
  }
102
191
  }
103
192
 
104
- override fun stop(promise: Promise) {
105
- Log.d(TAG, "════════════════════════════════════════")
106
- Log.d(TAG, "⏹️ STOP() CHAMADO")
107
- Log.d(TAG, "════════════════════════════════════════")
108
- try {
109
- Log.d(TAG, "🔄 Chamando RegionManager.removeAllGeofences()...")
110
- RegionManager.removeAllGeofences(reactApplicationContext)
111
- Log.d(TAG, "✅ STOP() SUCESSO - Promise resolvida")
112
- promise.resolve(null)
113
- } catch (e: Exception) {
114
- Log.e(TAG, "💥 EXCEÇÃO em stop():")
115
- Log.e(TAG, " └─ Message: ${e.message}")
116
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
117
- promise.reject("GEOFENCE_ERROR", e.message)
193
+ private fun saveDetailsToPrefs(context: Context) {
194
+ synchronized(GeofenceManagerModule.geofenceDetailsMap) {
195
+ val arr = JSONArray()
196
+ GeofenceManagerModule.geofenceDetailsMap.values.forEach { d ->
197
+ arr.put(JSONObject().apply {
198
+ put("id", d.id)
199
+ put("name", d.name ?: "")
200
+ put("latitude", d.latitude)
201
+ put("longitude", d.longitude)
202
+ put("radius", d.radius.toDouble())
203
+ })
204
+ }
205
+ getPrefs(context).edit().putString(PREFS_KEY_DETAILS, arr.toString()).apply()
118
206
  }
119
207
  }
120
208
 
121
- override fun isActive(promise: Promise) {
122
- Log.d(TAG, "════════════════════════════════════════")
123
- Log.d(TAG, "❓ IS_ACTIVE() CHAMADO")
124
- Log.d(TAG, "════════════════════════════════════════")
125
- try {
126
- val active = RegionManager.isActive(reactApplicationContext)
127
- Log.d(TAG, "📊 Resultado: active=$active")
128
- Log.d(TAG, "✅ IS_ACTIVE() SUCESSO - Promise resolvida")
129
- promise.resolve(active)
130
- } catch (e: Exception) {
131
- Log.e(TAG, "💥 EXCEÇÃO em isActive():")
132
- Log.e(TAG, " └─ Message: ${e.message}")
133
- promise.reject("GEOFENCE_ERROR", e.message)
209
+ override fun removeAllGeofences(promise: Promise) {
210
+ Log.i(TAG, "removeAllGeofences: start")
211
+ synchronized(GeofenceManagerModule.geofenceNames) {
212
+ GeofenceManagerModule.geofenceNames.clear()
213
+ GeofenceManagerModule.geofenceDetailsMap.clear()
134
214
  }
135
- }
136
-
137
- override fun getActiveRegions(promise: Promise) {
138
- Log.d(TAG, "════════════════════════════════════════")
139
- Log.d(TAG, "📋 GET_ACTIVE_REGIONS() CHAMADO")
140
- Log.d(TAG, "════════════════════════════════════════")
141
- try {
142
- val regions = RegionManager.getRegions(reactApplicationContext)
143
- Log.d(TAG, "📊 Encontradas ${regions.size} região(ões) ativas")
144
-
145
- val result: WritableArray = Arguments.createArray()
146
-
147
- for (region in regions) {
148
- Log.d(TAG, " └─ id=${region.id}, name=${region.name}")
149
- Log.d(TAG, " └─ lat=${region.latitude}, lng=${region.longitude}, radius=${region.radius}m")
150
- val map = Arguments.createMap().apply {
151
- putString("id", region.id)
152
- putString("name", region.name)
153
- putString("data", region.data)
154
- putDouble("latitude", region.latitude)
155
- putDouble("longitude", region.longitude)
156
- putDouble("radius", region.radius.toDouble())
157
- }
158
- result.pushMap(map)
215
+ getPrefs(applicationContext).edit().remove(PREFS_KEY_DETAILS).apply()
216
+ geofencingClient.removeGeofences(getPendingIntent())
217
+ .addOnSuccessListener {
218
+ Log.i(TAG, "removeAllGeofences: SUCCESS")
219
+ promise.resolve(true)
159
220
  }
160
-
161
- Log.d(TAG, " GET_ACTIVE_REGIONS() SUCESSO - Promise resolvida")
162
- promise.resolve(result)
163
- } catch (e: Exception) {
164
- Log.e(TAG, "💥 EXCEÇÃO em getActiveRegions():")
165
- Log.e(TAG, " └─ Message: ${e.message}")
166
- promise.reject("GEOFENCE_ERROR", e.message)
167
- }
168
- }
169
-
170
- private fun parseRegions(regions: ReadableArray): List<Region> {
171
- Log.d(TAG, "🔧 parseRegions() - Parseando ${regions.size()} regiões...")
172
- val list = mutableListOf<Region>()
173
- for (i in 0 until regions.size()) {
174
- val map = regions.getMap(i)
175
- if (map == null) {
176
- Log.w(TAG, " └─ [$i] IGNORADA - map é null")
177
- continue
221
+ .addOnFailureListener { e ->
222
+ Log.e(TAG, "removeAllGeofences: FAILURE ${e.message}", e)
223
+ promise.resolve(false)
178
224
  }
179
- val region = Region(
180
- id = map.getString("id") ?: "region_$i",
181
- name = map.getString("name") ?: "",
182
- data = map.getString("data") ?: "",
183
- latitude = map.getDouble("latitude"),
184
- longitude = map.getDouble("longitude"),
185
- radius = map.takeIf { it.hasKey("radius") }?.getDouble("radius")?.toFloat() ?: 100f
186
- )
187
- Log.d(TAG, " └─ [$i] OK - id=${region.id}")
188
- list.add(region)
189
- }
190
- Log.d(TAG, "🔧 parseRegions() - Concluído: ${list.size} regiões válidas")
191
- return list
192
225
  }
193
226
  }
@@ -1,21 +1,21 @@
1
- #import "GeofenceManager.h"
2
-
3
- @implementation GeofenceManager
4
- - (NSNumber *)multiply:(double)a b:(double)b {
5
- NSNumber *result = @(a * b);
6
-
7
- return result;
8
- }
9
-
10
- - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
11
- (const facebook::react::ObjCTurboModule::InitParams &)params
12
- {
13
- return std::make_shared<facebook::react::NativeGeofenceManagerSpecJSI>(params);
14
- }
15
-
16
- + (NSString *)moduleName
17
- {
18
- return @"GeofenceManager";
19
- }
20
-
21
- @end
1
+ #import "GeofenceManager.h"
2
+
3
+ @implementation GeofenceManager
4
+
5
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
6
+ (const facebook::react::ObjCTurboModule::InitParams &)params
7
+ {
8
+ return std::make_shared<facebook::react::NativeGeofenceManagerSpecJSI>(params);
9
+ }
10
+
11
+ + (NSString *)moduleName
12
+ {
13
+ return @"GeofenceManager";
14
+ }
15
+
16
+ - (NSNumber *)multiply:(double)a b:(double)b
17
+ {
18
+ return @(a * b);
19
+ }
20
+
21
+ @end
@@ -1,11 +1,5 @@
1
1
  "use strict";
2
2
 
3
3
  import { TurboModuleRegistry } from 'react-native';
4
- const NativeModule = TurboModuleRegistry.get('GeofenceManager');
5
- if (NativeModule) {
6
- console.log('✅ react-native-geofence-manager: Native module linked successfully');
7
- } else {
8
- console.warn('❌ react-native-geofence-manager: Native module not found. Make sure you rebuilt the app after installing the package.');
9
- }
10
- export default NativeModule;
4
+ export default TurboModuleRegistry.getEnforcing('GeofenceManager');
11
5
  //# sourceMappingURL=NativeGeofenceManager.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","NativeModule","get","console","log","warn"],"sourceRoot":"..\\..\\src","sources":["NativeGeofenceManager.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAuBpE,MAAMC,YAAY,GAAGD,mBAAmB,CAACE,GAAG,CAAO,iBAAiB,CAAC;AAErE,IAAID,YAAY,EAAE;EAChBE,OAAO,CAACC,GAAG,CAAC,oEAAoE,CAAC;AACnF,CAAC,MAAM;EACLD,OAAO,CAACE,IAAI,CACV,uHACF,CAAC;AACH;AAEA,eAAeJ,YAAY","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"..\\..\\src","sources":["NativeGeofenceManager.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAQpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,iBAAiB,CAAC","ignoreList":[]}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Logs de diagnóstico da lib. Aparecem no Metro e no Logcat (Android) com filtro "GeofenceManager".
5
+ */
6
+ const TAG = '[GeofenceManager]';
7
+ function safeStringify(data) {
8
+ try {
9
+ return JSON.stringify(data);
10
+ } catch {
11
+ return String(data);
12
+ }
13
+ }
14
+ export function geofenceDebugLog(step, data) {
15
+ const line = data !== undefined ? `${TAG} ${step} ${safeStringify(data)}` : `${TAG} ${step}`;
16
+ console.log(line);
17
+ }
18
+ export function geofenceDebugWarn(step, data) {
19
+ const line = data !== undefined ? `${TAG} ${step} ${safeStringify(data)}` : `${TAG} ${step}`;
20
+ console.warn(line);
21
+ }
22
+ //# sourceMappingURL=geofenceDebugLog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TAG","safeStringify","data","JSON","stringify","String","geofenceDebugLog","step","line","undefined","console","log","geofenceDebugWarn","warn"],"sourceRoot":"..\\..\\src","sources":["geofenceDebugLog.ts"],"mappings":";;AAAA;AACA;AACA;AACA,MAAMA,GAAG,GAAG,mBAAmB;AAE/B,SAASC,aAAaA,CAACC,IAAa,EAAU;EAC5C,IAAI;IACF,OAAOC,IAAI,CAACC,SAAS,CAACF,IAAI,CAAC;EAC7B,CAAC,CAAC,MAAM;IACN,OAAOG,MAAM,CAACH,IAAI,CAAC;EACrB;AACF;AAEA,OAAO,SAASI,gBAAgBA,CAACC,IAAY,EAAEL,IAAc,EAAQ;EACnE,MAAMM,IAAI,GACRN,IAAI,KAAKO,SAAS,GACd,GAAGT,GAAG,IAAIO,IAAI,IAAIN,aAAa,CAACC,IAAI,CAAC,EAAE,GACvC,GAAGF,GAAG,IAAIO,IAAI,EAAE;EACtBG,OAAO,CAACC,GAAG,CAACH,IAAI,CAAC;AACnB;AAEA,OAAO,SAASI,iBAAiBA,CAACL,IAAY,EAAEL,IAAc,EAAQ;EACpE,MAAMM,IAAI,GACRN,IAAI,KAAKO,SAAS,GACd,GAAGT,GAAG,IAAIO,IAAI,IAAIN,aAAa,CAACC,IAAI,CAAC,EAAE,GACvC,GAAGF,GAAG,IAAIO,IAAI,EAAE;EACtBG,OAAO,CAACG,IAAI,CAACL,IAAI,CAAC;AACpB","ignoreList":[]}
@@ -1,42 +1,86 @@
1
1
  "use strict";
2
2
 
3
- import NativeGeofence from './NativeGeofenceManager';
4
- import { AppRegistry, NativeEventEmitter, Platform } from 'react-native';
5
- const emitter = new NativeEventEmitter();
6
- const MAX_REGIONS = 100;
7
- const notLinkedError = () => Promise.reject(new Error('❌ react-native-geofence-manager: Native module not linked. Rebuild your app.'));
8
- export const GeofenceManager = {
9
- start: (regions, options) => {
10
- if (!NativeGeofence) return notLinkedError();
11
- if (regions.length > MAX_REGIONS) {
12
- return Promise.reject(new Error(`Limite máximo de ${MAX_REGIONS} regiões excedido. Recebido: ${regions.length}`));
13
- }
14
- return NativeGeofence.start(regions, options ?? {}).then(() => {
15
- console.log('✅ react-native-geofence-manager: Geofencing started successfully');
16
- });
17
- },
18
- stop: () => {
19
- if (!NativeGeofence) return notLinkedError();
20
- return NativeGeofence.stop().then(() => {
21
- console.log('🛑 react-native-geofence-manager: Geofencing stopped');
3
+ import { AppRegistry, DeviceEventEmitter } from 'react-native';
4
+ import NativeGeofenceManager from "./NativeGeofenceManager.js";
5
+ import { geofenceDebugLog, geofenceDebugWarn } from "./geofenceDebugLog.js";
6
+ const EVENT_NAME = 'onGeofenceTransition';
7
+
8
+ /** Nome da headless task para eventos de geofence (app morto/background). Deve ser usado com registerGeofenceHeadlessTask no index do app. */
9
+ export const GEOFENCE_HEADLESS_TASK_NAME = 'GeofenceManagerTransition';
10
+ export function addGeofenceEventListener(callback) {
11
+ geofenceDebugLog('JS: addGeofenceEventListener registering listener', {
12
+ eventName: EVENT_NAME
13
+ });
14
+ const subscription = DeviceEventEmitter.addListener(EVENT_NAME, payload => {
15
+ geofenceDebugLog('JS: addGeofenceEventListener event received', payload);
16
+ callback(payload);
17
+ });
18
+ return () => {
19
+ geofenceDebugLog('JS: addGeofenceEventListener — unsubscribed');
20
+ subscription.remove();
21
+ };
22
+ }
23
+ export function onGeofenceEvent(callback) {
24
+ return addGeofenceEventListener(callback);
25
+ }
26
+
27
+ /**
28
+ * Registra o handler da headless task para quando o app é acordado por um evento de geofence
29
+ * (app morto ou em background). Deve ser chamado no index do app, antes de AppRegistry.registerComponent.
30
+ *
31
+ * @example
32
+ * // index.js
33
+ * import { AppRegistry } from 'react-native';
34
+ * import { registerGeofenceHeadlessTask } from 'react-native-geofence-manager';
35
+ * import App from './App';
36
+ * import { name as appName } from './app.json';
37
+ *
38
+ * registerGeofenceHeadlessTask((event) => {
39
+ * console.log('Geofence (headless):', event.geofenceId, event.event);
40
+ * });
41
+ *
42
+ * AppRegistry.registerComponent(appName, () => App);
43
+ */
44
+ export function registerGeofenceHeadlessTask(callback) {
45
+ geofenceDebugLog('JS: registerGeofenceHeadlessTask — registering', {
46
+ taskName: GEOFENCE_HEADLESS_TASK_NAME
47
+ });
48
+ AppRegistry.registerHeadlessTask(GEOFENCE_HEADLESS_TASK_NAME, () => data => {
49
+ geofenceDebugLog('JS: headless task invoked', data);
50
+ return Promise.resolve(callback(data));
51
+ });
52
+ }
53
+ const addGeofences = async geofences => {
54
+ geofenceDebugLog('JS: addGeofences — calling native', {
55
+ count: geofences.length,
56
+ ids: geofences.map(g => g.id)
57
+ });
58
+ try {
59
+ const ok = await NativeGeofenceManager.addGeofences(geofences);
60
+ geofenceDebugLog('JS: addGeofences — native result', {
61
+ success: ok
22
62
  });
23
- },
24
- onEnter: cb => emitter.addListener('onEnter', cb),
25
- onExit: cb => emitter.addListener('onExit', cb),
26
- onDwell: cb => emitter.addListener('onDwell', cb),
27
- registerBackgroundHandler: handler => {
28
- if (Platform.OS !== 'android') {
29
- return;
63
+ if (!ok) {
64
+ geofenceDebugWarn('JS: addGeofences native returned false (empty list, Geofencing API failure, or permissions)');
30
65
  }
31
- AppRegistry.registerHeadlessTask('GeofenceHeadlessTask', () => handler);
32
- },
33
- isActive: () => {
34
- if (!NativeGeofence) return Promise.resolve(false);
35
- return NativeGeofence.isActive();
36
- },
37
- getActiveRegions: () => {
38
- if (!NativeGeofence) return Promise.resolve([]);
39
- return NativeGeofence.getActiveRegions();
66
+ return ok;
67
+ } catch (e) {
68
+ geofenceDebugWarn('JS: addGeofences — threw (TurboModule missing or bridge error)', e);
69
+ throw e;
70
+ }
71
+ };
72
+ const removeAllGeofences = async () => {
73
+ geofenceDebugLog('JS: removeAllGeofences — calling native');
74
+ try {
75
+ const ok = await NativeGeofenceManager.removeAllGeofences();
76
+ geofenceDebugLog('JS: removeAllGeofences — native result', {
77
+ success: ok
78
+ });
79
+ return ok;
80
+ } catch (e) {
81
+ geofenceDebugWarn('JS: removeAllGeofences — threw', e);
82
+ throw e;
40
83
  }
41
84
  };
85
+ export { addGeofences, removeAllGeofences };
42
86
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeGeofence","AppRegistry","NativeEventEmitter","Platform","emitter","MAX_REGIONS","notLinkedError","Promise","reject","Error","GeofenceManager","start","regions","options","length","then","console","log","stop","onEnter","cb","addListener","onExit","onDwell","registerBackgroundHandler","handler","OS","registerHeadlessTask","isActive","resolve","getActiveRegions"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,cAAc,MAGd,yBAAyB;AAChC,SAASC,WAAW,EAAEC,kBAAkB,EAAEC,QAAQ,QAAQ,cAAc;AAExE,MAAMC,OAAO,GAAG,IAAIF,kBAAkB,CAAC,CAAC;AAExC,MAAMG,WAAW,GAAG,GAAG;AAmBvB,MAAMC,cAAc,GAAGA,CAAA,KACrBC,OAAO,CAACC,MAAM,CACZ,IAAIC,KAAK,CACP,8EACF,CACF,CAAC;AAEH,OAAO,MAAMC,eAAe,GAAG;EAC7BC,KAAK,EAAEA,CAACC,OAAiB,EAAEC,OAAyB,KAAoB;IACtE,IAAI,CAACb,cAAc,EAAE,OAAOM,cAAc,CAAC,CAAC;IAC5C,IAAIM,OAAO,CAACE,MAAM,GAAGT,WAAW,EAAE;MAChC,OAAOE,OAAO,CAACC,MAAM,CACnB,IAAIC,KAAK,CACP,oBAAoBJ,WAAW,gCAAgCO,OAAO,CAACE,MAAM,EAC/E,CACF,CAAC;IACH;IACA,OAAOd,cAAc,CAACW,KAAK,CAACC,OAAO,EAAEC,OAAO,IAAI,CAAC,CAAC,CAAC,CAACE,IAAI,CAAC,MAAM;MAC7DC,OAAO,CAACC,GAAG,CAAC,kEAAkE,CAAC;IACjF,CAAC,CAAC;EACJ,CAAC;EAEDC,IAAI,EAAEA,CAAA,KAAqB;IACzB,IAAI,CAAClB,cAAc,EAAE,OAAOM,cAAc,CAAC,CAAC;IAC5C,OAAON,cAAc,CAACkB,IAAI,CAAC,CAAC,CAACH,IAAI,CAAC,MAAM;MACtCC,OAAO,CAACC,GAAG,CAAC,sDAAsD,CAAC;IACrE,CAAC,CAAC;EACJ,CAAC;EAEDE,OAAO,EAAGC,EAAyC,IACjDhB,OAAO,CAACiB,WAAW,CAAC,SAAS,EAAED,EAAS,CAAC;EAE3CE,MAAM,EAAGF,EAAyC,IAChDhB,OAAO,CAACiB,WAAW,CAAC,QAAQ,EAAED,EAAS,CAAC;EAE1CG,OAAO,EAAGH,EAAyC,IACjDhB,OAAO,CAACiB,WAAW,CAAC,SAAS,EAAED,EAAS,CAAC;EAE3CI,yBAAyB,EAAGC,OAAkC,IAAW;IACvE,IAAItB,QAAQ,CAACuB,EAAE,KAAK,SAAS,EAAE;MAC7B;IACF;IACAzB,WAAW,CAAC0B,oBAAoB,CAAC,sBAAsB,EAAE,MAAMF,OAAO,CAAC;EACzE,CAAC;EAEDG,QAAQ,EAAEA,CAAA,KAAwB;IAChC,IAAI,CAAC5B,cAAc,EAAE,OAAOO,OAAO,CAACsB,OAAO,CAAC,KAAK,CAAC;IAClD,OAAO7B,cAAc,CAAC4B,QAAQ,CAAC,CAAC;EAClC,CAAC;EAEDE,gBAAgB,EAAEA,CAAA,KAAyB;IACzC,IAAI,CAAC9B,cAAc,EAAE,OAAOO,OAAO,CAACsB,OAAO,CAAC,EAAE,CAAC;IAC/C,OAAO7B,cAAc,CAAC8B,gBAAgB,CAAC,CAAC;EAC1C;AACF,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["AppRegistry","DeviceEventEmitter","NativeGeofenceManager","geofenceDebugLog","geofenceDebugWarn","EVENT_NAME","GEOFENCE_HEADLESS_TASK_NAME","addGeofenceEventListener","callback","eventName","subscription","addListener","payload","remove","onGeofenceEvent","registerGeofenceHeadlessTask","taskName","registerHeadlessTask","data","Promise","resolve","addGeofences","geofences","count","length","ids","map","g","id","ok","success","e","removeAllGeofences"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,WAAW,EACXC,kBAAkB,QAEb,cAAc;AACrB,OAAOC,qBAAqB,MAAM,4BAAyB;AAC3D,SAASC,gBAAgB,EAAEC,iBAAiB,QAAQ,uBAAoB;AASxE,MAAMC,UAAU,GAAG,sBAAsB;;AAEzC;AACA,OAAO,MAAMC,2BAA2B,GAAG,2BAA2B;AAEtE,OAAO,SAASC,wBAAwBA,CACtCC,QAAwC,EAC5B;EACZL,gBAAgB,CAAC,qDAAqD,EAAE;IACtEM,SAAS,EAAEJ;EACb,CAAC,CAAC;EACF,MAAMK,YAA+B,GAAGT,kBAAkB,CAACU,WAAW,CACpEN,UAAU,EACTO,OAAgB,IAAK;IACpBT,gBAAgB,CAAC,+CAA+C,EAAES,OAAO,CAAC;IAC1EJ,QAAQ,CAACI,OAAwB,CAAC;EACpC,CACF,CAAC;EACD,OAAO,MAAM;IACXT,gBAAgB,CAAC,6CAA6C,CAAC;IAC/DO,YAAY,CAACG,MAAM,CAAC,CAAC;EACvB,CAAC;AACH;AAEA,OAAO,SAASC,eAAeA,CAC7BN,QAAwC,EAC5B;EACZ,OAAOD,wBAAwB,CAACC,QAAQ,CAAC;AAC3C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASO,4BAA4BA,CAC1CP,QAAwC,EAClC;EACNL,gBAAgB,CAAC,gDAAgD,EAAE;IACjEa,QAAQ,EAAEV;EACZ,CAAC,CAAC;EACFN,WAAW,CAACiB,oBAAoB,CAC9BX,2BAA2B,EAC3B,MAAOY,IAAa,IAAK;IACvBf,gBAAgB,CAAC,2BAA2B,EAAEe,IAAI,CAAC;IACnD,OAAOC,OAAO,CAACC,OAAO,CAACZ,QAAQ,CAACU,IAAqB,CAAC,CAAC;EACzD,CACF,CAAC;AACH;AAEA,MAAMG,YAAY,GAAG,MACnBC,SAA0B,IACL;EACrBnB,gBAAgB,CAAC,mCAAmC,EAAE;IACpDoB,KAAK,EAAED,SAAS,CAACE,MAAM;IACvBC,GAAG,EAAEH,SAAS,CAACI,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,EAAE;EAChC,CAAC,CAAC;EACF,IAAI;IACF,MAAMC,EAAE,GAAG,MAAM3B,qBAAqB,CAACmB,YAAY,CAACC,SAAS,CAAC;IAC9DnB,gBAAgB,CAAC,kCAAkC,EAAE;MAAE2B,OAAO,EAAED;IAAG,CAAC,CAAC;IACrE,IAAI,CAACA,EAAE,EAAE;MACPzB,iBAAiB,CACf,+FACF,CAAC;IACH;IACA,OAAOyB,EAAE;EACX,CAAC,CAAC,OAAOE,CAAC,EAAE;IACV3B,iBAAiB,CAAC,gEAAgE,EAAE2B,CAAC,CAAC;IACtF,MAAMA,CAAC;EACT;AACF,CAAC;AAED,MAAMC,kBAAkB,GAAG,MAAAA,CAAA,KAA8B;EACvD7B,gBAAgB,CAAC,yCAAyC,CAAC;EAC3D,IAAI;IACF,MAAM0B,EAAE,GAAG,MAAM3B,qBAAqB,CAAC8B,kBAAkB,CAAC,CAAC;IAC3D7B,gBAAgB,CAAC,wCAAwC,EAAE;MAAE2B,OAAO,EAAED;IAAG,CAAC,CAAC;IAC3E,OAAOA,EAAE;EACX,CAAC,CAAC,OAAOE,CAAC,EAAE;IACV3B,iBAAiB,CAAC,gCAAgC,EAAE2B,CAAC,CAAC;IACtD,MAAMA,CAAC;EACT;AACF,CAAC;AAED,SAASV,YAAY,EAAEW,kBAAkB","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=GeofenceEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["models/GeofenceEvent.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=GeofenceEventType.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["models/GeofenceEventType.ts"],"mappings":"","ignoreList":[]}