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,192 +0,0 @@
1
- package com.geofencemanager
2
-
3
- import android.content.BroadcastReceiver
4
- import android.content.Context
5
- import android.content.Intent
6
- import android.util.Log
7
- import com.facebook.react.bridge.Arguments
8
- import com.facebook.react.bridge.ReactContext
9
- import com.facebook.react.modules.core.DeviceEventManagerModule
10
- import com.google.android.gms.location.Geofence
11
- import com.google.android.gms.location.GeofencingEvent
12
-
13
- class GeofenceReceiver : BroadcastReceiver() {
14
-
15
- companion object {
16
- private const val TAG = "GeofenceReceiver"
17
- const val HEADLESS_TASK_NAME = "GeofenceHeadlessTask"
18
-
19
- @Volatile
20
- var reactContext: ReactContext? = null
21
- }
22
-
23
- override fun onReceive(context: Context, intent: Intent) {
24
- Log.d(TAG, "════════════════════════════════════════")
25
- Log.d(TAG, "📡 ON_RECEIVE() - BROADCAST RECEBIDO!")
26
- Log.d(TAG, "════════════════════════════════════════")
27
- Log.d(TAG, "⏰ Timestamp: ${System.currentTimeMillis()}")
28
- Log.d(TAG, "📦 Intent: $intent")
29
- Log.d(TAG, " └─ Action: ${intent.action}")
30
- Log.d(TAG, " └─ Extras: ${intent.extras}")
31
-
32
- val geofencingEvent = GeofencingEvent.fromIntent(intent)
33
- if (geofencingEvent == null) {
34
- Log.e(TAG, "❌ GeofencingEvent é NULL - Intent inválido")
35
- return
36
- }
37
-
38
- Log.d(TAG, "📍 GeofencingEvent recebido:")
39
- Log.d(TAG, " └─ hasError: ${geofencingEvent.hasError()}")
40
-
41
- if (geofencingEvent.hasError()) {
42
- val errorCode = geofencingEvent.errorCode
43
- val errorMessage = when (errorCode) {
44
- 1 -> "GEOFENCE_NOT_AVAILABLE"
45
- 2 -> "GEOFENCE_TOO_MANY_GEOFENCES"
46
- 3 -> "GEOFENCE_TOO_MANY_PENDING_INTENTS"
47
- else -> "UNKNOWN_ERROR"
48
- }
49
- Log.e(TAG, "❌ ERRO NO GEOFENCING!")
50
- Log.e(TAG, " └─ ErrorCode: $errorCode ($errorMessage)")
51
- return
52
- }
53
-
54
- val triggeringGeofences = geofencingEvent.triggeringGeofences
55
- Log.d(TAG, " └─ triggeringGeofences: ${triggeringGeofences?.size ?: 0}")
56
-
57
- if (triggeringGeofences.isNullOrEmpty()) {
58
- Log.w(TAG, "⚠️ Nenhuma geofence na lista de triggering")
59
- return
60
- }
61
-
62
- val transitionType = geofencingEvent.geofenceTransition
63
- val transitionName = when (transitionType) {
64
- Geofence.GEOFENCE_TRANSITION_ENTER -> "ENTER"
65
- Geofence.GEOFENCE_TRANSITION_EXIT -> "EXIT"
66
- Geofence.GEOFENCE_TRANSITION_DWELL -> "DWELL"
67
- else -> "UNKNOWN($transitionType)"
68
- }
69
-
70
- Log.d(TAG, " └─ transitionType: $transitionType ($transitionName)")
71
- Log.d(TAG, " └─ triggeringLocation: ${geofencingEvent.triggeringLocation}")
72
-
73
- val eventName = when (transitionType) {
74
- Geofence.GEOFENCE_TRANSITION_ENTER -> "onEnter"
75
- Geofence.GEOFENCE_TRANSITION_EXIT -> "onExit"
76
- Geofence.GEOFENCE_TRANSITION_DWELL -> "onDwell"
77
- else -> {
78
- Log.w(TAG, "⚠️ Transição desconhecida: $transitionType - ignorando")
79
- return
80
- }
81
- }
82
-
83
- Log.d(TAG, "🎯 Processando ${triggeringGeofences.size} geofence(s) disparada(s):")
84
- Log.d(TAG, "════════════════════════════════════════")
85
- Log.d(TAG, "⚠️ LISTA DE GEOFENCES DISPARADAS:")
86
- Log.d(TAG, "════════════════════════════════════════")
87
- for ((index, geofence) in triggeringGeofences.withIndex()) {
88
- Log.d(TAG, " └─ [$index] requestId: ${geofence.requestId}")
89
- }
90
- Log.d(TAG, "════════════════════════════════════════")
91
-
92
- // Processa cada geofence disparada
93
- for ((index, geofence) in triggeringGeofences.withIndex()) {
94
- Log.d(TAG, "📤 Enviando evento [$index]: ${geofence.requestId}")
95
- sendEvent(context, eventName, geofence.requestId)
96
- }
97
- }
98
-
99
- private fun sendEvent(context: Context, eventName: String, regionId: String) {
100
- Log.d(TAG, "────────────────────────────────────────")
101
- Log.d(TAG, "📤 SEND_EVENT()")
102
- Log.d(TAG, "────────────────────────────────────────")
103
- Log.d(TAG, " └─ eventName: $eventName")
104
- Log.d(TAG, " └─ regionId: $regionId")
105
-
106
- val ctx = reactContext
107
- Log.d(TAG, " └─ reactContext: ${ctx ?: "NULL"}")
108
-
109
- val region = RegionManager.getRegionById(context, regionId)
110
- Log.d(TAG, " └─ region: ${if (region != null) "ENCONTRADA" else "NULL"}")
111
- if (region != null) {
112
- Log.d(TAG, " └─ name: ${region.name}")
113
- Log.d(TAG, " └─ lat: ${region.latitude}, lng: ${region.longitude}")
114
- }
115
-
116
- if (ctx != null) {
117
- Log.d(TAG, "🔍 Verificando hasActiveReactInstance()...")
118
- val hasActive = ctx.hasActiveReactInstance()
119
- Log.d(TAG, " └─ hasActiveReactInstance: $hasActive")
120
-
121
- if (hasActive) {
122
- try {
123
- Log.d(TAG, "📱 APP EM FOREGROUND - Enviando evento JS...")
124
- val params = buildRegionMap(region, regionId)
125
- Log.d(TAG, " └─ Params: id=${params.getString("id")}, name=${params.getString("name")}")
126
-
127
- ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
128
- .emit(eventName, params)
129
-
130
- Log.d(TAG, "✅ Evento JS emitido com sucesso!")
131
- return
132
- } catch (e: Exception) {
133
- Log.e(TAG, "💥 Erro ao enviar evento JS:")
134
- Log.e(TAG, " └─ Message: ${e.message}")
135
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
136
- }
137
- }
138
- }
139
-
140
- Log.d(TAG, "📴 APP EM BACKGROUND - Iniciando HeadlessTask...")
141
- startHeadlessTask(context, eventName, region, regionId)
142
- }
143
-
144
- private fun buildRegionMap(region: Region?, regionId: String) = Arguments.createMap().apply {
145
- putString("id", region?.id ?: regionId)
146
- putString("name", region?.name ?: "")
147
- putString("data", region?.data ?: "")
148
- putDouble("latitude", region?.latitude ?: 0.0)
149
- putDouble("longitude", region?.longitude ?: 0.0)
150
- putDouble("radius", region?.radius?.toDouble() ?: 100.0)
151
- }
152
-
153
- private fun startHeadlessTask(context: Context, eventName: String, region: Region?, regionId: String) {
154
- Log.d(TAG, "────────────────────────────────────────")
155
- Log.d(TAG, "🔧 START_HEADLESS_TASK()")
156
- Log.d(TAG, "────────────────────────────────────────")
157
- Log.d(TAG, " └─ eventName: $eventName")
158
- Log.d(TAG, " └─ regionId: $regionId")
159
- Log.d(TAG, " └─ region: ${region?.name ?: "NULL"}")
160
-
161
- try {
162
- val serviceIntent = Intent(context, GeofenceHeadlessTaskService::class.java).apply {
163
- putExtra("eventName", eventName)
164
- putExtra("regionId", region?.id ?: regionId)
165
- putExtra("regionName", region?.name ?: "")
166
- putExtra("regionData", region?.data ?: "")
167
- putExtra("regionLatitude", region?.latitude ?: 0.0)
168
- putExtra("regionLongitude", region?.longitude ?: 0.0)
169
- putExtra("regionRadius", region?.radius?.toDouble() ?: 100.0)
170
- }
171
-
172
- Log.d(TAG, "📦 ServiceIntent criado:")
173
- Log.d(TAG, " └─ Intent: $serviceIntent")
174
- Log.d(TAG, " └─ Extras:")
175
- Log.d(TAG, " └─ eventName: $eventName")
176
- Log.d(TAG, " └─ regionId: ${region?.id ?: regionId}")
177
- Log.d(TAG, " └─ regionName: ${region?.name ?: ""}")
178
- Log.d(TAG, " └─ regionLat: ${region?.latitude ?: 0.0}")
179
- Log.d(TAG, " └─ regionLng: ${region?.longitude ?: 0.0}")
180
-
181
- Log.d(TAG, "🚀 Chamando context.startService()...")
182
- context.startService(serviceIntent)
183
- Log.d(TAG, "✅ HeadlessTask service iniciado!")
184
-
185
- } catch (e: Exception) {
186
- Log.e(TAG, "💥 ERRO ao iniciar HeadlessTask:")
187
- Log.e(TAG, " └─ Exception: ${e.javaClass.simpleName}")
188
- Log.e(TAG, " └─ Message: ${e.message}")
189
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
190
- }
191
- }
192
- }
@@ -1,387 +0,0 @@
1
- package com.geofencemanager
2
-
3
- import android.Manifest
4
- import android.app.PendingIntent
5
- import android.content.Context
6
- import android.content.Intent
7
- import android.content.SharedPreferences
8
- import android.content.pm.PackageManager
9
- import android.os.Build
10
- import android.util.Log
11
- import androidx.core.app.ActivityCompat
12
- import com.google.android.gms.location.Geofence
13
- import com.google.android.gms.location.GeofencingClient
14
- import com.google.android.gms.location.GeofencingRequest
15
- import com.google.android.gms.location.LocationServices
16
- import org.json.JSONArray
17
- import org.json.JSONObject
18
-
19
- data class Region(
20
- val id: String,
21
- val name: String,
22
- val data: String,
23
- val latitude: Double,
24
- val longitude: Double,
25
- val radius: Float = 100f
26
- )
27
-
28
- object RegionManager {
29
- private const val TAG = "RegionManager"
30
- private const val PREFS_NAME = "GeofenceManagerPrefs"
31
- private const val REGIONS_KEY = "registered_regions"
32
- private const val HEADLESS_TIMEOUT_KEY = "headless_task_timeout"
33
- private const val ACTIVE_KEY = "geofence_active"
34
-
35
- private var geofencingClient: GeofencingClient? = null
36
- private var pendingIntent: PendingIntent? = null
37
-
38
- fun registerGeofences(
39
- context: Context,
40
- regions: List<Region>,
41
- dwellDelay: Int = 5000,
42
- headlessTaskTimeout: Int = 30000,
43
- onSuccess: (() -> Unit)? = null,
44
- onError: ((String) -> Unit)? = null
45
- ) {
46
- Log.d(TAG, "════════════════════════════════════════")
47
- Log.d(TAG, "📍 REGISTER_GEOFENCES() INICIADO")
48
- Log.d(TAG, "════════════════════════════════════════")
49
- Log.d(TAG, "📊 Parâmetros:")
50
- Log.d(TAG, " └─ Regiões: ${regions.size}")
51
- Log.d(TAG, " └─ dwellDelay: ${dwellDelay}ms")
52
- Log.d(TAG, " └─ headlessTaskTimeout: ${headlessTaskTimeout}ms")
53
-
54
- if (regions.isEmpty()) {
55
- Log.w(TAG, "⚠️ Lista de regiões vazia - abortando")
56
- onError?.invoke("Nenhuma região para registrar")
57
- return
58
- }
59
-
60
- Log.d(TAG, "🔐 Verificando permissões...")
61
-
62
- val hasFineLocation = hasLocationPermission(context)
63
- Log.d(TAG, " └─ ACCESS_FINE_LOCATION: ${if (hasFineLocation) "✅ CONCEDIDA" else "❌ NEGADA"}")
64
-
65
- if (!hasFineLocation) {
66
- Log.e(TAG, "❌ ABORTANDO - Falta permissão ACCESS_FINE_LOCATION")
67
- onError?.invoke("Permissão ACCESS_FINE_LOCATION não concedida")
68
- return
69
- }
70
-
71
- val hasBackgroundLocation = hasBackgroundLocationPermission(context)
72
- Log.d(TAG, " └─ ACCESS_BACKGROUND_LOCATION: ${if (hasBackgroundLocation) "✅ CONCEDIDA" else "❌ NEGADA"}")
73
- Log.d(TAG, " └─ Android Version: ${Build.VERSION.SDK_INT} (Q=${Build.VERSION_CODES.Q})")
74
-
75
- if (!hasBackgroundLocation) {
76
- Log.e(TAG, "❌ ABORTANDO - Falta permissão ACCESS_BACKGROUND_LOCATION (Android 10+)")
77
- onError?.invoke("Permissão ACCESS_BACKGROUND_LOCATION não concedida (necessária para Android 10+)")
78
- return
79
- }
80
-
81
- Log.d(TAG, "✅ Todas as permissões OK!")
82
-
83
- Log.d(TAG, "💾 Salvando regiões no SharedPreferences...")
84
- saveRegions(context, regions)
85
-
86
- Log.d(TAG, "💾 Salvando headlessTimeout: ${headlessTaskTimeout}ms")
87
- saveHeadlessTimeout(context, headlessTaskTimeout)
88
-
89
- Log.d(TAG, "🔄 Obtendo GeofencingClient...")
90
- geofencingClient = LocationServices.getGeofencingClient(context)
91
- Log.d(TAG, " └─ GeofencingClient: $geofencingClient")
92
-
93
- Log.d(TAG, "🗑️ Removendo geofences antigas antes de adicionar novas...")
94
- val pendingIntentToRemove = getGeofencePendingIntent(context)
95
- Log.d(TAG, " └─ PendingIntent: $pendingIntentToRemove")
96
-
97
- geofencingClient?.removeGeofences(pendingIntentToRemove)
98
- ?.addOnCompleteListener { task ->
99
- Log.d(TAG, "🗑️ Remoção de geofences antigas concluída")
100
- Log.d(TAG, " └─ Sucesso: ${task.isSuccessful}")
101
- if (!task.isSuccessful) {
102
- Log.w(TAG, " └─ Exception: ${task.exception?.message}")
103
- }
104
- Log.d(TAG, "🔄 Chamando addNewGeofences()...")
105
- addNewGeofences(context, regions, dwellDelay, onSuccess, onError)
106
- }
107
- }
108
-
109
- private fun addNewGeofences(
110
- context: Context,
111
- regions: List<Region>,
112
- dwellDelay: Int,
113
- onSuccess: (() -> Unit)? = null,
114
- onError: ((String) -> Unit)? = null
115
- ) {
116
- Log.d(TAG, "════════════════════════════════════════")
117
- Log.d(TAG, "➕ ADD_NEW_GEOFENCES() INICIADO")
118
- Log.d(TAG, "════════════════════════════════════════")
119
- Log.d(TAG, "🔧 Construindo lista de Geofence objects...")
120
-
121
- val geofenceList = regions.mapIndexed { index, region ->
122
- Log.d(TAG, " └─ [$index] Criando Geofence:")
123
- Log.d(TAG, " └─ requestId: ${region.id}")
124
- Log.d(TAG, " └─ lat: ${region.latitude}")
125
- Log.d(TAG, " └─ lng: ${region.longitude}")
126
- Log.d(TAG, " └─ radius: ${region.radius}m")
127
- Log.d(TAG, " └─ dwellDelay: ${dwellDelay}ms")
128
- Log.d(TAG, " └─ transitions: ENTER | EXIT | DWELL")
129
- Log.d(TAG, " └─ expiration: NEVER_EXPIRE")
130
-
131
- Geofence.Builder()
132
- .setRequestId(region.id)
133
- .setCircularRegion(region.latitude, region.longitude, region.radius)
134
- .setExpirationDuration(Geofence.NEVER_EXPIRE)
135
- .setTransitionTypes(
136
- Geofence.GEOFENCE_TRANSITION_ENTER or
137
- Geofence.GEOFENCE_TRANSITION_EXIT or
138
- Geofence.GEOFENCE_TRANSITION_DWELL
139
- )
140
- .setLoiteringDelay(dwellDelay)
141
- .setNotificationResponsiveness(0)
142
- .build()
143
- }
144
-
145
- Log.d(TAG, "✅ ${geofenceList.size} Geofence objects criados")
146
-
147
- Log.d(TAG, "🔧 Construindo GeofencingRequest...")
148
- Log.d(TAG, " └─ initialTrigger: NENHUM (0) - Só dispara em transições reais")
149
-
150
- val geofencingRequest = GeofencingRequest.Builder()
151
- .setInitialTrigger(0) // Não dispara no registro, só em transições reais
152
- .addGeofences(geofenceList)
153
- .build()
154
-
155
- Log.d(TAG, "✅ GeofencingRequest construído")
156
- Log.d(TAG, " └─ Geofences no request: ${geofencingRequest.geofences.size}")
157
-
158
- try {
159
- Log.d(TAG, "📡 Chamando geofencingClient.addGeofences()...")
160
- val pendingIntent = getGeofencePendingIntent(context)
161
- Log.d(TAG, " └─ PendingIntent: $pendingIntent")
162
-
163
- geofencingClient?.addGeofences(geofencingRequest, pendingIntent)
164
- ?.addOnSuccessListener {
165
- Log.d(TAG, "════════════════════════════════════════")
166
- Log.d(TAG, "🎉 GEOFENCES REGISTRADAS COM SUCESSO!")
167
- Log.d(TAG, "════════════════════════════════════════")
168
- Log.d(TAG, " └─ Total: ${geofenceList.size} geofences")
169
- setActive(context, true)
170
- Log.d(TAG, " └─ Status ACTIVE salvo: true")
171
- Log.d(TAG, " └─ Chamando onSuccess callback...")
172
- onSuccess?.invoke()
173
- }
174
- ?.addOnFailureListener { e ->
175
- Log.e(TAG, "════════════════════════════════════════")
176
- Log.e(TAG, "💥 FALHA AO REGISTRAR GEOFENCES!")
177
- Log.e(TAG, "════════════════════════════════════════")
178
- Log.e(TAG, " └─ Exception: ${e.javaClass.simpleName}")
179
- Log.e(TAG, " └─ Message: ${e.message}")
180
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
181
- onError?.invoke(e.message ?: "Erro desconhecido ao registrar geofences")
182
- }
183
- } catch (e: SecurityException) {
184
- Log.e(TAG, "════════════════════════════════════════")
185
- Log.e(TAG, "🔒 SECURITY EXCEPTION!")
186
- Log.e(TAG, "════════════════════════════════════════")
187
- Log.e(TAG, " └─ Message: ${e.message}")
188
- Log.e(TAG, " └─ Provavelmente faltam permissões")
189
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
190
- onError?.invoke(e.message ?: "SecurityException ao registrar geofences")
191
- }
192
- }
193
-
194
- fun removeAllGeofences(context: Context) {
195
- Log.d(TAG, "════════════════════════════════════════")
196
- Log.d(TAG, "🗑️ REMOVE_ALL_GEOFENCES() INICIADO")
197
- Log.d(TAG, "════════════════════════════════════════")
198
-
199
- geofencingClient = LocationServices.getGeofencingClient(context)
200
- Log.d(TAG, " └─ GeofencingClient: $geofencingClient")
201
- Log.d(TAG, " └─ PendingIntent atual: $pendingIntent")
202
-
203
- if (pendingIntent == null) {
204
- Log.w(TAG, "⚠️ PendingIntent é NULL - tentando recriar...")
205
- getGeofencePendingIntent(context)
206
- }
207
-
208
- pendingIntent?.let { intent ->
209
- Log.d(TAG, "📡 Chamando geofencingClient.removeGeofences()...")
210
- geofencingClient?.removeGeofences(intent)
211
- ?.addOnSuccessListener {
212
- Log.d(TAG, "════════════════════════════════════════")
213
- Log.d(TAG, "✅ GEOFENCES REMOVIDAS COM SUCESSO!")
214
- Log.d(TAG, "════════════════════════════════════════")
215
- clearRegions(context)
216
- Log.d(TAG, " └─ Regiões limpas do SharedPreferences")
217
- setActive(context, false)
218
- Log.d(TAG, " └─ Status ACTIVE salvo: false")
219
- }
220
- ?.addOnFailureListener { e ->
221
- Log.e(TAG, "════════════════════════════════════════")
222
- Log.e(TAG, "💥 FALHA AO REMOVER GEOFENCES!")
223
- Log.e(TAG, "════════════════════════════════════════")
224
- Log.e(TAG, " └─ Message: ${e.message}")
225
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
226
- }
227
- } ?: run {
228
- Log.e(TAG, "❌ Não foi possível remover - PendingIntent é NULL")
229
- }
230
- }
231
-
232
- fun isActive(context: Context): Boolean {
233
- val active = getPrefs(context).getBoolean(ACTIVE_KEY, false)
234
- Log.d(TAG, "❓ isActive() = $active")
235
- return active
236
- }
237
-
238
- private fun setActive(context: Context, active: Boolean) {
239
- Log.d(TAG, "💾 setActive($active)")
240
- getPrefs(context).edit()
241
- .putBoolean(ACTIVE_KEY, active)
242
- .apply()
243
- }
244
-
245
- fun getRegionById(context: Context, id: String): Region? {
246
- Log.d(TAG, "🔍 getRegionById(id=$id)")
247
- val region = getRegions(context).find { it.id == id }
248
- Log.d(TAG, " └─ Resultado: ${if (region != null) "ENCONTRADA (${region.name})" else "NÃO ENCONTRADA"}")
249
- return region
250
- }
251
-
252
- fun getHeadlessTimeout(context: Context): Int {
253
- val timeout = getPrefs(context).getInt(HEADLESS_TIMEOUT_KEY, 30000)
254
- Log.d(TAG, "⏱️ getHeadlessTimeout() = ${timeout}ms")
255
- return timeout
256
- }
257
-
258
- private fun saveHeadlessTimeout(context: Context, timeout: Int) {
259
- Log.d(TAG, "💾 saveHeadlessTimeout(${timeout}ms)")
260
- getPrefs(context).edit()
261
- .putInt(HEADLESS_TIMEOUT_KEY, timeout)
262
- .apply()
263
- }
264
-
265
- fun getRegions(context: Context): List<Region> {
266
- Log.d(TAG, "📋 getRegions() - Lendo do SharedPreferences...")
267
- val json = getPrefs(context).getString(REGIONS_KEY, null)
268
-
269
- if (json == null) {
270
- Log.d(TAG, " └─ Nenhuma região salva (JSON null)")
271
- return emptyList()
272
- }
273
-
274
- Log.d(TAG, " └─ JSON encontrado: ${json.take(100)}${if (json.length > 100) "..." else ""}")
275
-
276
- return try {
277
- val jsonArray = JSONArray(json)
278
- val list = mutableListOf<Region>()
279
- Log.d(TAG, " └─ Parseando ${jsonArray.length()} regiões...")
280
-
281
- for (i in 0 until jsonArray.length()) {
282
- val obj = jsonArray.getJSONObject(i)
283
- val region = Region(
284
- id = obj.getString("id"),
285
- name = obj.getString("name"),
286
- data = obj.getString("data"),
287
- latitude = obj.getDouble("latitude"),
288
- longitude = obj.getDouble("longitude"),
289
- radius = obj.getDouble("radius").toFloat()
290
- )
291
- Log.d(TAG, " └─ [$i] id=${region.id}, name=${region.name}")
292
- list.add(region)
293
- }
294
- Log.d(TAG, " └─ Total parseado: ${list.size} regiões")
295
- list
296
- } catch (e: Exception) {
297
- Log.e(TAG, "💥 Erro ao ler regiões:")
298
- Log.e(TAG, " └─ Message: ${e.message}")
299
- Log.e(TAG, " └─ StackTrace: ${e.stackTraceToString()}")
300
- emptyList()
301
- }
302
- }
303
-
304
- private fun saveRegions(context: Context, regions: List<Region>) {
305
- Log.d(TAG, "💾 saveRegions() - Salvando ${regions.size} regiões...")
306
- val jsonArray = JSONArray()
307
- for (region in regions) {
308
- val obj = JSONObject().apply {
309
- put("id", region.id)
310
- put("name", region.name)
311
- put("data", region.data)
312
- put("latitude", region.latitude)
313
- put("longitude", region.longitude)
314
- put("radius", region.radius)
315
- }
316
- jsonArray.put(obj)
317
- }
318
-
319
- val jsonString = jsonArray.toString()
320
- Log.d(TAG, " └─ JSON gerado: ${jsonString.take(100)}${if (jsonString.length > 100) "..." else ""}")
321
-
322
- getPrefs(context).edit()
323
- .putString(REGIONS_KEY, jsonString)
324
- .apply()
325
-
326
- Log.d(TAG, "✅ ${regions.size} região(ões) salvas com sucesso")
327
- }
328
-
329
- private fun clearRegions(context: Context) {
330
- Log.d(TAG, "🗑️ clearRegions() - Removendo regiões do SharedPreferences...")
331
- getPrefs(context).edit()
332
- .remove(REGIONS_KEY)
333
- .apply()
334
- Log.d(TAG, " └─ Regiões removidas")
335
- }
336
-
337
- private fun getPrefs(context: Context): SharedPreferences {
338
- return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
339
- }
340
-
341
- private fun getGeofencePendingIntent(context: Context): PendingIntent {
342
- Log.d(TAG, "🔧 getGeofencePendingIntent()")
343
- pendingIntent?.let {
344
- Log.d(TAG, " └─ Retornando PendingIntent existente: $it")
345
- return it
346
- }
347
-
348
- Log.d(TAG, " └─ Criando novo PendingIntent...")
349
- val intent = Intent(context, GeofenceReceiver::class.java)
350
- val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
351
- Log.d(TAG, " └─ Intent: $intent")
352
- Log.d(TAG, " └─ Flags: FLAG_UPDATE_CURRENT | FLAG_MUTABLE")
353
-
354
- pendingIntent = PendingIntent.getBroadcast(context, 0, intent, flags)
355
- Log.d(TAG, " └─ PendingIntent criado: $pendingIntent")
356
- return pendingIntent!!
357
- }
358
-
359
- private fun hasLocationPermission(context: Context): Boolean {
360
- val result = ActivityCompat.checkSelfPermission(
361
- context,
362
- Manifest.permission.ACCESS_FINE_LOCATION
363
- ) == PackageManager.PERMISSION_GRANTED
364
- Log.d(TAG, "🔐 hasLocationPermission() = $result")
365
- return result
366
- }
367
-
368
- private fun hasBackgroundLocationPermission(context: Context): Boolean {
369
- Log.d(TAG, "🔐 hasBackgroundLocationPermission()")
370
- Log.d(TAG, " └─ SDK_INT: ${Build.VERSION.SDK_INT}")
371
- Log.d(TAG, " └─ VERSION_CODES.Q: ${Build.VERSION_CODES.Q}")
372
-
373
- // ACCESS_BACKGROUND_LOCATION é necessário apenas no Android 10 (API 29) ou superior
374
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
375
- val result = ActivityCompat.checkSelfPermission(
376
- context,
377
- Manifest.permission.ACCESS_BACKGROUND_LOCATION
378
- ) == PackageManager.PERMISSION_GRANTED
379
- Log.d(TAG, " └─ Android 10+ - Verificando ACCESS_BACKGROUND_LOCATION: $result")
380
- result
381
- } else {
382
- Log.d(TAG, " └─ Android < 10 - Background location não necessária")
383
- // Em versões anteriores ao Android 10, a permissão de foreground é suficiente
384
- true
385
- }
386
- }
387
- }
@@ -1,15 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _reactNative = require("react-native");
8
- const NativeModule = _reactNative.TurboModuleRegistry.get('GeofenceManager');
9
- if (NativeModule) {
10
- console.log('✅ react-native-geofence-manager: Native module linked successfully');
11
- } else {
12
- console.warn('❌ react-native-geofence-manager: Native module not found. Make sure you rebuilt the app after installing the package.');
13
- }
14
- var _default = exports.default = NativeModule;
15
- //# sourceMappingURL=NativeGeofenceManager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_reactNative","require","NativeModule","TurboModuleRegistry","get","console","log","warn","_default","exports","default"],"sourceRoot":"..\\..\\src","sources":["NativeGeofenceManager.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAuBA,MAAMC,YAAY,GAAGC,gCAAmB,CAACC,GAAG,CAAO,iBAAiB,CAAC;AAErE,IAAIF,YAAY,EAAE;EAChBG,OAAO,CAACC,GAAG,CAAC,oEAAoE,CAAC;AACnF,CAAC,MAAM;EACLD,OAAO,CAACE,IAAI,CACV,uHACF,CAAC;AACH;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEcR,YAAY","ignoreList":[]}
@@ -1,47 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.GeofenceManager = void 0;
7
- var _NativeGeofenceManager = _interopRequireDefault(require("./NativeGeofenceManager"));
8
- var _reactNative = require("react-native");
9
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
- const emitter = new _reactNative.NativeEventEmitter();
11
- const MAX_REGIONS = 100;
12
- const notLinkedError = () => Promise.reject(new Error('❌ react-native-geofence-manager: Native module not linked. Rebuild your app.'));
13
- const GeofenceManager = exports.GeofenceManager = {
14
- start: (regions, options) => {
15
- if (!_NativeGeofenceManager.default) return notLinkedError();
16
- if (regions.length > MAX_REGIONS) {
17
- return Promise.reject(new Error(`Limite máximo de ${MAX_REGIONS} regiões excedido. Recebido: ${regions.length}`));
18
- }
19
- return _NativeGeofenceManager.default.start(regions, options ?? {}).then(() => {
20
- console.log('✅ react-native-geofence-manager: Geofencing started successfully');
21
- });
22
- },
23
- stop: () => {
24
- if (!_NativeGeofenceManager.default) return notLinkedError();
25
- return _NativeGeofenceManager.default.stop().then(() => {
26
- console.log('🛑 react-native-geofence-manager: Geofencing stopped');
27
- });
28
- },
29
- onEnter: cb => emitter.addListener('onEnter', cb),
30
- onExit: cb => emitter.addListener('onExit', cb),
31
- onDwell: cb => emitter.addListener('onDwell', cb),
32
- registerBackgroundHandler: handler => {
33
- if (_reactNative.Platform.OS !== 'android') {
34
- return;
35
- }
36
- _reactNative.AppRegistry.registerHeadlessTask('GeofenceHeadlessTask', () => handler);
37
- },
38
- isActive: () => {
39
- if (!_NativeGeofenceManager.default) return Promise.resolve(false);
40
- return _NativeGeofenceManager.default.isActive();
41
- },
42
- getActiveRegions: () => {
43
- if (!_NativeGeofenceManager.default) return Promise.resolve([]);
44
- return _NativeGeofenceManager.default.getActiveRegions();
45
- }
46
- };
47
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_NativeGeofenceManager","_interopRequireDefault","require","_reactNative","e","__esModule","default","emitter","NativeEventEmitter","MAX_REGIONS","notLinkedError","Promise","reject","Error","GeofenceManager","exports","start","regions","options","NativeGeofence","length","then","console","log","stop","onEnter","cb","addListener","onExit","onDwell","registerBackgroundHandler","handler","Platform","OS","AppRegistry","registerHeadlessTask","isActive","resolve","getActiveRegions"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,sBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAIA,IAAAC,YAAA,GAAAD,OAAA;AAAyE,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEzE,MAAMG,OAAO,GAAG,IAAIC,+BAAkB,CAAC,CAAC;AAExC,MAAMC,WAAW,GAAG,GAAG;AAmBvB,MAAMC,cAAc,GAAGA,CAAA,KACrBC,OAAO,CAACC,MAAM,CACZ,IAAIC,KAAK,CACP,8EACF,CACF,CAAC;AAEI,MAAMC,eAAe,GAAAC,OAAA,CAAAD,eAAA,GAAG;EAC7BE,KAAK,EAAEA,CAACC,OAAiB,EAAEC,OAAyB,KAAoB;IACtE,IAAI,CAACC,8BAAc,EAAE,OAAOT,cAAc,CAAC,CAAC;IAC5C,IAAIO,OAAO,CAACG,MAAM,GAAGX,WAAW,EAAE;MAChC,OAAOE,OAAO,CAACC,MAAM,CACnB,IAAIC,KAAK,CACP,oBAAoBJ,WAAW,gCAAgCQ,OAAO,CAACG,MAAM,EAC/E,CACF,CAAC;IACH;IACA,OAAOD,8BAAc,CAACH,KAAK,CAACC,OAAO,EAAEC,OAAO,IAAI,CAAC,CAAC,CAAC,CAACG,IAAI,CAAC,MAAM;MAC7DC,OAAO,CAACC,GAAG,CAAC,kEAAkE,CAAC;IACjF,CAAC,CAAC;EACJ,CAAC;EAEDC,IAAI,EAAEA,CAAA,KAAqB;IACzB,IAAI,CAACL,8BAAc,EAAE,OAAOT,cAAc,CAAC,CAAC;IAC5C,OAAOS,8BAAc,CAACK,IAAI,CAAC,CAAC,CAACH,IAAI,CAAC,MAAM;MACtCC,OAAO,CAACC,GAAG,CAAC,sDAAsD,CAAC;IACrE,CAAC,CAAC;EACJ,CAAC;EAEDE,OAAO,EAAGC,EAAyC,IACjDnB,OAAO,CAACoB,WAAW,CAAC,SAAS,EAAED,EAAS,CAAC;EAE3CE,MAAM,EAAGF,EAAyC,IAChDnB,OAAO,CAACoB,WAAW,CAAC,QAAQ,EAAED,EAAS,CAAC;EAE1CG,OAAO,EAAGH,EAAyC,IACjDnB,OAAO,CAACoB,WAAW,CAAC,SAAS,EAAED,EAAS,CAAC;EAE3CI,yBAAyB,EAAGC,OAAkC,IAAW;IACvE,IAAIC,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAAE;MAC7B;IACF;IACAC,wBAAW,CAACC,oBAAoB,CAAC,sBAAsB,EAAE,MAAMJ,OAAO,CAAC;EACzE,CAAC;EAEDK,QAAQ,EAAEA,CAAA,KAAwB;IAChC,IAAI,CAACjB,8BAAc,EAAE,OAAOR,OAAO,CAAC0B,OAAO,CAAC,KAAK,CAAC;IAClD,OAAOlB,8BAAc,CAACiB,QAAQ,CAAC,CAAC;EAClC,CAAC;EAEDE,gBAAgB,EAAEA,CAAA,KAAyB;IACzC,IAAI,CAACnB,8BAAc,EAAE,OAAOR,OAAO,CAAC0B,OAAO,CAAC,EAAE,CAAC;IAC/C,OAAOlB,8BAAc,CAACmB,gBAAgB,CAAC,CAAC;EAC1C;AACF,CAAC","ignoreList":[]}
@@ -1 +0,0 @@
1
- {"type":"commonjs"}
@@ -1,11 +0,0 @@
1
- module.exports = {
2
- dependency: {
3
- platforms: {
4
- android: {
5
- packageImportPath: 'import com.geofencemanager.GeofenceManagerPackage;',
6
- packageInstance: 'new GeofenceManagerPackage()',
7
- },
8
- ios: {},
9
- },
10
- },
11
- };