react-native-geofence-manager 0.1.0-beta.14 → 0.1.0-beta.15
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.
- package/README.md +5 -17
- package/android/src/main/java/com/geofencemanager/GeofenceBroadcastReceiver.kt +12 -57
- package/android/src/main/java/com/geofencemanager/GeofenceHeadlessTaskService.kt +13 -41
- package/android/src/main/java/com/geofencemanager/GeofenceManagerModule.kt +21 -49
- package/lib/module/index.js +7 -62
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +0 -13
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/models/GeofenceEvent.d.ts +4 -0
- package/lib/typescript/src/models/GeofenceEvent.d.ts.map +1 -1
- package/lib/typescript/src/models/GeofenceModel.d.ts +5 -0
- package/lib/typescript/src/models/GeofenceModel.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +7 -62
- package/src/models/GeofenceEvent.ts +4 -0
- package/src/models/GeofenceModel.ts +5 -0
- package/lib/module/geofenceDebugLog.js +0 -22
- package/lib/module/geofenceDebugLog.js.map +0 -1
- package/lib/typescript/src/geofenceDebugLog.d.ts +0 -3
- package/lib/typescript/src/geofenceDebugLog.d.ts.map +0 -1
- package/src/geofenceDebugLog.ts +0 -28
package/README.md
CHANGED
|
@@ -60,7 +60,9 @@ const ok = await addGeofences([
|
|
|
60
60
|
name: 'Loja centro',
|
|
61
61
|
latitude: -23.5505,
|
|
62
62
|
longitude: -46.6333,
|
|
63
|
-
radius: 150,
|
|
63
|
+
radius: 150,
|
|
64
|
+
// opcional: string livre (ex. JSON) — volta em GeofenceEvent.data
|
|
65
|
+
data: JSON.stringify({ lojaId: '123', promo: true }),
|
|
64
66
|
},
|
|
65
67
|
]);
|
|
66
68
|
// ok === true se o registro foi aceito pelo sistema
|
|
@@ -98,6 +100,7 @@ await removeAllGeofences();
|
|
|
98
100
|
| `longitude` | `number` | Sim | Longitude do centro |
|
|
99
101
|
| `name` | `string` | Não | Nome exibido nos eventos |
|
|
100
102
|
| `radius` | `number` | Não | Raio em metros |
|
|
103
|
+
| `data` | `string` | Não | Payload opaco; repassado no evento para você dar `JSON.parse` etc. |
|
|
101
104
|
|
|
102
105
|
---
|
|
103
106
|
|
|
@@ -106,6 +109,7 @@ await removeAllGeofences();
|
|
|
106
109
|
- `geofenceId` — ID da geofence
|
|
107
110
|
- `event` — `'enter' | 'exit' | 'dwell'`
|
|
108
111
|
- `timestamp`, `name`, `latitude`, `longitude`, `radius` — quando disponíveis
|
|
112
|
+
- `data` — mesma string definida em `GeofenceModel.data` (vazio se não houver)
|
|
109
113
|
|
|
110
114
|
---
|
|
111
115
|
|
|
@@ -115,22 +119,6 @@ Para geofences confiáveis é necessário **localização** (fina ou aproximada)
|
|
|
115
119
|
|
|
116
120
|
---
|
|
117
121
|
|
|
118
|
-
## Depuração (logs)
|
|
119
|
-
|
|
120
|
-
A lib emite logs em cada etapa para localizar falhas (SDK nativo + JS).
|
|
121
|
-
|
|
122
|
-
**Android (Logcat)** — filtre pela tag:
|
|
123
|
-
|
|
124
|
-
```text
|
|
125
|
-
adb logcat -s GeofenceManager
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
Você verá, entre outros: inicialização do módulo, `addGeofences` (sucesso/falha do Play Services), `BroadcastReceiver` (transição, foreground vs headless), `HeadlessTaskService` e erros de reflexão.
|
|
129
|
-
|
|
130
|
-
**JavaScript** — mensagens com prefixo `[GeofenceManager]` no console (Metro) e também no Logcat como `ReactNativeJS` ao rodar no dispositivo.
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
122
|
## App de exemplo
|
|
135
123
|
|
|
136
124
|
Na raiz do repositório:
|
|
@@ -4,84 +4,47 @@ import android.content.BroadcastReceiver
|
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.content.Intent
|
|
6
6
|
import android.os.Build
|
|
7
|
-
import android.util.Log
|
|
8
7
|
import android.os.Handler
|
|
9
8
|
import android.os.Looper
|
|
10
9
|
import com.facebook.react.HeadlessJsTaskService
|
|
11
10
|
import com.facebook.react.bridge.Arguments
|
|
12
11
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
13
|
-
import com.facebook.react.bridge.WritableMap
|
|
14
12
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
15
13
|
import com.google.android.gms.location.Geofence
|
|
16
14
|
import com.google.android.gms.location.GeofencingEvent
|
|
17
15
|
|
|
18
16
|
class GeofenceBroadcastReceiver : BroadcastReceiver() {
|
|
19
17
|
|
|
20
|
-
companion object {
|
|
21
|
-
private const val TAG = "GeofenceManager"
|
|
22
|
-
}
|
|
23
|
-
|
|
24
18
|
override fun onReceive(context: Context?, intent: Intent?) {
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
Log.w(TAG, "BroadcastReceiver.onReceive: abort — null context or intent")
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
if (intent.action != GeofenceManagerModule.GEOFENCE_ACTION) {
|
|
31
|
-
Log.w(TAG, "BroadcastReceiver.onReceive: wrong action, expected ${GeofenceManagerModule.GEOFENCE_ACTION}")
|
|
32
|
-
return
|
|
33
|
-
}
|
|
19
|
+
if (context == null || intent == null) return
|
|
20
|
+
if (intent.action != GeofenceManagerModule.GEOFENCE_ACTION) return
|
|
34
21
|
|
|
35
|
-
val geofencingEvent = GeofencingEvent.fromIntent(intent)
|
|
36
|
-
if (geofencingEvent
|
|
37
|
-
Log.e(TAG, "BroadcastReceiver.onReceive: GeofencingEvent.fromIntent returned null")
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
if (geofencingEvent.hasError()) {
|
|
41
|
-
Log.e(TAG, "BroadcastReceiver.onReceive: Geofencing error code=${geofencingEvent.errorCode}")
|
|
42
|
-
return
|
|
43
|
-
}
|
|
22
|
+
val geofencingEvent = GeofencingEvent.fromIntent(intent) ?: return
|
|
23
|
+
if (geofencingEvent.hasError()) return
|
|
44
24
|
|
|
45
|
-
if (GeofenceManagerModule.isWithinGracePeriod(context))
|
|
46
|
-
Log.i(TAG, "BroadcastReceiver.onReceive: skipped — within grace period after addGeofences")
|
|
47
|
-
return
|
|
48
|
-
}
|
|
25
|
+
if (GeofenceManagerModule.isWithinGracePeriod(context)) return
|
|
49
26
|
|
|
50
27
|
val transition = geofencingEvent.geofenceTransition
|
|
51
28
|
val eventName = when (transition) {
|
|
52
29
|
Geofence.GEOFENCE_TRANSITION_ENTER -> "enter"
|
|
53
30
|
Geofence.GEOFENCE_TRANSITION_EXIT -> "exit"
|
|
54
31
|
Geofence.GEOFENCE_TRANSITION_DWELL -> "dwell"
|
|
55
|
-
else ->
|
|
56
|
-
Log.w(TAG, "BroadcastReceiver.onReceive: unknown transition=$transition")
|
|
57
|
-
return
|
|
58
|
-
}
|
|
32
|
+
else -> return
|
|
59
33
|
}
|
|
60
|
-
Log.i(TAG, "BroadcastReceiver.onReceive: transition=$eventName")
|
|
61
34
|
|
|
62
|
-
val triggeringGeofences = geofencingEvent.triggeringGeofences
|
|
63
|
-
if (triggeringGeofences
|
|
64
|
-
Log.w(TAG, "BroadcastReceiver.onReceive: no triggering geofences")
|
|
65
|
-
return
|
|
66
|
-
}
|
|
35
|
+
val triggeringGeofences = geofencingEvent.triggeringGeofences ?: return
|
|
36
|
+
if (triggeringGeofences.isEmpty()) return
|
|
67
37
|
|
|
68
38
|
val reactContext = GeofenceManagerModule.reactContextRef
|
|
69
39
|
val timestamp = System.currentTimeMillis().toDouble()
|
|
70
40
|
val isForeground = reactContext != null && reactContext.hasActiveReactInstance()
|
|
71
|
-
Log.i(
|
|
72
|
-
TAG,
|
|
73
|
-
"BroadcastReceiver.onReceive: ids=${triggeringGeofences.map { it.requestId }} isForeground=$isForeground hasReactContextRef=${reactContext != null}"
|
|
74
|
-
)
|
|
75
41
|
|
|
76
42
|
if (isForeground) {
|
|
77
43
|
val ctx = reactContext!!
|
|
78
44
|
val geofenceIds = triggeringGeofences.map { it.requestId }
|
|
79
45
|
val eventNameForRunnable = eventName
|
|
80
46
|
Handler(Looper.getMainLooper()).postDelayed({
|
|
81
|
-
if (!ctx.hasActiveReactInstance())
|
|
82
|
-
Log.w(TAG, "BroadcastReceiver: foreground path — React instance gone after delay, skipping emit")
|
|
83
|
-
return@postDelayed
|
|
84
|
-
}
|
|
47
|
+
if (!ctx.hasActiveReactInstance()) return@postDelayed
|
|
85
48
|
try {
|
|
86
49
|
val emitter = ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
87
50
|
for (geofenceId in geofenceIds) {
|
|
@@ -96,18 +59,15 @@ class GeofenceBroadcastReceiver : BroadcastReceiver() {
|
|
|
96
59
|
putDouble("longitude", it.longitude)
|
|
97
60
|
putDouble("radius", it.radius.toDouble())
|
|
98
61
|
}
|
|
62
|
+
putString("data", details?.userData ?: "")
|
|
99
63
|
}
|
|
100
|
-
Log.i(TAG, "BroadcastReceiver: emitting onGeofenceTransition id=$geofenceId event=$eventNameForRunnable")
|
|
101
64
|
emitter.emit("onGeofenceTransition", params)
|
|
102
65
|
}
|
|
103
|
-
} catch (
|
|
104
|
-
Log.e(TAG, "BroadcastReceiver: emit to JS failed", e)
|
|
105
|
-
}
|
|
66
|
+
} catch (_: Exception) { }
|
|
106
67
|
}, 50)
|
|
107
68
|
return
|
|
108
69
|
}
|
|
109
70
|
|
|
110
|
-
Log.i(TAG, "BroadcastReceiver: background/headless path — starting GeofenceHeadlessTaskService")
|
|
111
71
|
val appContext = context.applicationContext
|
|
112
72
|
HeadlessJsTaskService.acquireWakeLockNow(appContext)
|
|
113
73
|
for (geofence in triggeringGeofences) {
|
|
@@ -119,15 +79,10 @@ class GeofenceBroadcastReceiver : BroadcastReceiver() {
|
|
|
119
79
|
try {
|
|
120
80
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
121
81
|
appContext.startForegroundService(serviceIntent)
|
|
122
|
-
Log.i(TAG, "BroadcastReceiver: startForegroundService for id=${geofence.requestId}")
|
|
123
82
|
} else {
|
|
124
83
|
appContext.startService(serviceIntent)
|
|
125
|
-
Log.i(TAG, "BroadcastReceiver: startService for id=${geofence.requestId}")
|
|
126
84
|
}
|
|
127
|
-
} catch (
|
|
128
|
-
Log.e(TAG, "BroadcastReceiver: failed to start headless service", e)
|
|
129
|
-
}
|
|
85
|
+
} catch (_: Exception) { }
|
|
130
86
|
}
|
|
131
87
|
}
|
|
132
|
-
|
|
133
88
|
}
|
|
@@ -5,35 +5,19 @@ import android.app.NotificationChannel
|
|
|
5
5
|
import android.app.NotificationManager
|
|
6
6
|
import android.content.Intent
|
|
7
7
|
import android.os.Build
|
|
8
|
-
import android.util.Log
|
|
9
8
|
import com.facebook.react.HeadlessJsTaskService
|
|
10
9
|
import com.facebook.react.bridge.Arguments
|
|
11
10
|
import com.facebook.react.jstasks.HeadlessJsTaskConfig
|
|
12
11
|
|
|
13
12
|
class GeofenceHeadlessTaskService : HeadlessJsTaskService() {
|
|
14
13
|
|
|
15
|
-
/**
|
|
16
|
-
* Quando o app está em background/frozen, reactContext existe mas hasActiveReactInstance()
|
|
17
|
-
* retorna false e a task não roda. Nesse caso chamamos createReactContextAndScheduleTask
|
|
18
|
-
* (via reflexão) em onStartCommand para que dwell/exit sejam executados.
|
|
19
|
-
* startForeground() é chamado para que o sistema inicie o serviço mesmo em background (dwell/exit).
|
|
20
|
-
*/
|
|
21
14
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
22
|
-
Log.i(TAG, "HeadlessTaskService.onStartCommand extras=${intent?.extras}")
|
|
23
15
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
24
16
|
ensureNotificationChannel()
|
|
25
|
-
|
|
26
|
-
startForeground(NOTIFICATION_ID, notification)
|
|
27
|
-
Log.d(TAG, "HeadlessTaskService: startForeground done")
|
|
28
|
-
}
|
|
29
|
-
val taskConfig = getTaskConfig(intent)
|
|
30
|
-
if (taskConfig == null) {
|
|
31
|
-
Log.e(TAG, "HeadlessTaskService: getTaskConfig returned null — check EXTRA_GEOFENCE_ID / EXTRA_EVENT")
|
|
32
|
-
return START_NOT_STICKY
|
|
17
|
+
startForeground(NOTIFICATION_ID, buildNotification())
|
|
33
18
|
}
|
|
19
|
+
val taskConfig = getTaskConfig(intent) ?: return START_NOT_STICKY
|
|
34
20
|
val ctx = reactContext
|
|
35
|
-
val hasInstance = ctx?.hasActiveReactInstance() == true
|
|
36
|
-
Log.i(TAG, "HeadlessTaskService: hasActiveReactInstance=$hasInstance")
|
|
37
21
|
if (ctx != null && !ctx.hasActiveReactInstance()) {
|
|
38
22
|
HeadlessJsTaskService.acquireWakeLockNow(this)
|
|
39
23
|
try {
|
|
@@ -43,33 +27,22 @@ class GeofenceHeadlessTaskService : HeadlessJsTaskService() {
|
|
|
43
27
|
)
|
|
44
28
|
method.isAccessible = true
|
|
45
29
|
method.invoke(this, taskConfig)
|
|
46
|
-
|
|
47
|
-
} catch (e: Exception) {
|
|
48
|
-
Log.e(TAG, "HeadlessTaskService: reflection createReactContextAndScheduleTask failed", e)
|
|
30
|
+
} catch (_: Exception) {
|
|
49
31
|
return super.onStartCommand(intent, flags, startId)
|
|
50
32
|
}
|
|
51
33
|
return START_REDELIVER_INTENT
|
|
52
34
|
}
|
|
53
|
-
Log.i(TAG, "HeadlessTaskService: delegating to super.onStartCommand")
|
|
54
35
|
return super.onStartCommand(intent, flags, startId)
|
|
55
36
|
}
|
|
56
37
|
|
|
57
38
|
override fun getTaskConfig(intent: Intent?): HeadlessJsTaskConfig? {
|
|
58
|
-
if (intent == null)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
val geofenceId = intent.getStringExtra(EXTRA_GEOFENCE_ID)
|
|
63
|
-
val event = intent.getStringExtra(EXTRA_EVENT)
|
|
64
|
-
if (geofenceId == null || event == null) {
|
|
65
|
-
Log.e(TAG, "getTaskConfig: missing geofenceId or event (id=$geofenceId event=$event)")
|
|
66
|
-
return null
|
|
67
|
-
}
|
|
39
|
+
if (intent == null) return null
|
|
40
|
+
val geofenceId = intent.getStringExtra(EXTRA_GEOFENCE_ID) ?: return null
|
|
41
|
+
val event = intent.getStringExtra(EXTRA_EVENT) ?: return null
|
|
68
42
|
val timestamp = intent.getDoubleExtra(EXTRA_TIMESTAMP, 0.0)
|
|
69
43
|
|
|
70
44
|
val details = GeofenceManagerModule.getGeofenceDetails(this, geofenceId)
|
|
71
|
-
|
|
72
|
-
val data = Arguments.createMap().apply {
|
|
45
|
+
val params = Arguments.createMap().apply {
|
|
73
46
|
putString("geofenceId", geofenceId)
|
|
74
47
|
putString("event", event)
|
|
75
48
|
putDouble("timestamp", timestamp)
|
|
@@ -77,11 +50,12 @@ class GeofenceHeadlessTaskService : HeadlessJsTaskService() {
|
|
|
77
50
|
putDouble("latitude", details?.latitude ?: 0.0)
|
|
78
51
|
putDouble("longitude", details?.longitude ?: 0.0)
|
|
79
52
|
putDouble("radius", details?.radius?.toDouble() ?: 0.0)
|
|
53
|
+
putString("data", details?.userData ?: "")
|
|
80
54
|
}
|
|
81
55
|
|
|
82
56
|
return HeadlessJsTaskConfig(
|
|
83
57
|
GeofenceManagerModule.GEOFENCE_HEADLESS_TASK_NAME,
|
|
84
|
-
|
|
58
|
+
params,
|
|
85
59
|
5000L,
|
|
86
60
|
false
|
|
87
61
|
)
|
|
@@ -91,26 +65,24 @@ class GeofenceHeadlessTaskService : HeadlessJsTaskService() {
|
|
|
91
65
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
|
92
66
|
val channel = NotificationChannel(
|
|
93
67
|
CHANNEL_ID,
|
|
94
|
-
"
|
|
68
|
+
"Drogasil",
|
|
95
69
|
NotificationManager.IMPORTANCE_LOW
|
|
96
70
|
).apply { setShowBadge(false) }
|
|
97
71
|
(getSystemService(NOTIFICATION_SERVICE) as NotificationManager)
|
|
98
72
|
.createNotificationChannel(channel)
|
|
99
73
|
}
|
|
100
74
|
|
|
101
|
-
private fun buildNotification(
|
|
102
|
-
val event = intent?.getStringExtra(EXTRA_EVENT) ?: "geofence"
|
|
75
|
+
private fun buildNotification(): Notification {
|
|
103
76
|
val smallIcon = applicationInfo.icon.takeIf { it != 0 } ?: android.R.drawable.ic_dialog_info
|
|
104
77
|
return Notification.Builder(this, CHANNEL_ID)
|
|
105
|
-
.setContentTitle("
|
|
106
|
-
.setContentText("
|
|
78
|
+
.setContentTitle("Drogasil")
|
|
79
|
+
.setContentText("")
|
|
107
80
|
.setSmallIcon(smallIcon)
|
|
108
81
|
.setPriority(Notification.PRIORITY_LOW)
|
|
109
82
|
.build()
|
|
110
83
|
}
|
|
111
84
|
|
|
112
85
|
companion object {
|
|
113
|
-
private const val TAG = "GeofenceManager"
|
|
114
86
|
private const val CHANNEL_ID = "geofence_manager_channel"
|
|
115
87
|
private const val NOTIFICATION_ID = 9001
|
|
116
88
|
const val EXTRA_GEOFENCE_ID = "geofenceId"
|
|
@@ -5,7 +5,6 @@ import android.content.ComponentName
|
|
|
5
5
|
import android.content.Context
|
|
6
6
|
import android.content.Intent
|
|
7
7
|
import android.content.SharedPreferences
|
|
8
|
-
import android.util.Log
|
|
9
8
|
import com.facebook.react.bridge.Promise
|
|
10
9
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
11
10
|
import com.facebook.react.bridge.ReadableArray
|
|
@@ -21,7 +20,6 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
21
20
|
NativeGeofenceManagerSpec(reactContext) {
|
|
22
21
|
|
|
23
22
|
companion object {
|
|
24
|
-
private const val TAG = "GeofenceManager"
|
|
25
23
|
const val NAME = "GeofenceManager"
|
|
26
24
|
const val GEOFENCE_ACTION = "com.geofencemanager.GEOFENCE_TRANSITION"
|
|
27
25
|
const val GEOFENCE_HEADLESS_TASK_NAME = "GeofenceManagerTransition"
|
|
@@ -48,7 +46,8 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
48
46
|
val name: String?,
|
|
49
47
|
val latitude: Double,
|
|
50
48
|
val longitude: Double,
|
|
51
|
-
val radius: Float
|
|
49
|
+
val radius: Float,
|
|
50
|
+
val userData: String?
|
|
52
51
|
)
|
|
53
52
|
|
|
54
53
|
private fun getPrefs(context: Context): SharedPreferences =
|
|
@@ -62,19 +61,20 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
62
61
|
val arr = JSONArray(json)
|
|
63
62
|
for (i in 0 until arr.length()) {
|
|
64
63
|
val o = arr.getJSONObject(i)
|
|
64
|
+
val userData =
|
|
65
|
+
if (!o.has("data") || o.isNull("data")) null else o.optString("data")
|
|
65
66
|
val d = GeofenceDetails(
|
|
66
67
|
id = o.getString("id"),
|
|
67
68
|
name = if (o.has("name")) o.optString("name").takeIf { it.isNotEmpty() } else null,
|
|
68
69
|
latitude = o.getDouble("latitude"),
|
|
69
70
|
longitude = o.getDouble("longitude"),
|
|
70
|
-
radius = o.getDouble("radius").toFloat()
|
|
71
|
+
radius = o.getDouble("radius").toFloat(),
|
|
72
|
+
userData = userData
|
|
71
73
|
)
|
|
72
74
|
geofenceDetailsMap[d.id] = d
|
|
73
75
|
d.name?.let { geofenceNames[d.id] = it }
|
|
74
76
|
}
|
|
75
|
-
} catch (
|
|
76
|
-
Log.w(TAG, "loadDetailsFromPrefs failed", e)
|
|
77
|
-
}
|
|
77
|
+
} catch (_: Exception) { }
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -88,15 +88,8 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
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
91
|
if (reactContext.currentActivity != null) {
|
|
96
92
|
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
93
|
}
|
|
101
94
|
}
|
|
102
95
|
|
|
@@ -106,11 +99,7 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
106
99
|
private var geofencePendingIntent: PendingIntent? = null
|
|
107
100
|
|
|
108
101
|
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")
|
|
102
|
+
geofencePendingIntent?.let { return it }
|
|
114
103
|
val intent = Intent(applicationContext, GeofenceBroadcastReceiver::class.java).apply {
|
|
115
104
|
action = GEOFENCE_ACTION
|
|
116
105
|
setPackage(applicationContext.packageName)
|
|
@@ -128,27 +117,24 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
128
117
|
override fun getName(): String = NAME
|
|
129
118
|
|
|
130
119
|
override fun addGeofences(geofences: ReadableArray, promise: Promise) {
|
|
131
|
-
Log.i(TAG, "addGeofences: start, arraySize=${geofences.size()}")
|
|
132
120
|
try {
|
|
133
121
|
val list = mutableListOf<Geofence>()
|
|
134
122
|
for (i in 0 until geofences.size()) {
|
|
135
|
-
val item = geofences.getMap(i)
|
|
136
|
-
|
|
137
|
-
Log.w(TAG, "addGeofences: index $i skipped (null map)")
|
|
138
|
-
continue
|
|
139
|
-
}
|
|
140
|
-
val id = item.getString("id")
|
|
141
|
-
if (id == null) {
|
|
142
|
-
Log.w(TAG, "addGeofences: index $i skipped (missing id)")
|
|
143
|
-
continue
|
|
144
|
-
}
|
|
123
|
+
val item = geofences.getMap(i) ?: continue
|
|
124
|
+
val id = item.getString("id") ?: continue
|
|
145
125
|
val name = if (item.hasKey("name")) item.getString("name") else null
|
|
146
126
|
val lat = item.getDouble("latitude")
|
|
147
127
|
val lng = item.getDouble("longitude")
|
|
148
128
|
val radius = if (item.hasKey("radius")) item.getDouble("radius").toFloat() else 100f
|
|
129
|
+
val userData = if (item.hasKey("data") && !item.isNull("data")) {
|
|
130
|
+
item.getString("data")
|
|
131
|
+
} else {
|
|
132
|
+
null
|
|
133
|
+
}
|
|
149
134
|
synchronized(GeofenceManagerModule.geofenceNames) {
|
|
150
135
|
if (name != null) GeofenceManagerModule.geofenceNames[id] = name
|
|
151
|
-
GeofenceManagerModule.geofenceDetailsMap[id] =
|
|
136
|
+
GeofenceManagerModule.geofenceDetailsMap[id] =
|
|
137
|
+
GeofenceDetails(id, name, lat, lng, radius, userData)
|
|
152
138
|
}
|
|
153
139
|
list.add(
|
|
154
140
|
Geofence.Builder()
|
|
@@ -161,10 +147,8 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
161
147
|
)
|
|
162
148
|
.build()
|
|
163
149
|
)
|
|
164
|
-
Log.i(TAG, "addGeofences: parsed geofence id=$id lat=$lat lng=$lng radius=$radius")
|
|
165
150
|
}
|
|
166
151
|
if (list.isEmpty()) {
|
|
167
|
-
Log.e(TAG, "addGeofences: no valid geofences — resolving false (check id/latitude/longitude)")
|
|
168
152
|
promise.resolve(false)
|
|
169
153
|
return
|
|
170
154
|
}
|
|
@@ -173,21 +157,15 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
173
157
|
.setInitialTrigger(0)
|
|
174
158
|
.addGeofences(list)
|
|
175
159
|
.build()
|
|
176
|
-
Log.i(TAG, "addGeofences: calling GeofencingClient.addGeofences count=${list.size}")
|
|
177
160
|
geofencingClient.addGeofences(request, getPendingIntent())
|
|
178
161
|
.addOnSuccessListener {
|
|
179
162
|
getPrefs(applicationContext).edit()
|
|
180
163
|
.putLong(PREFS_KEY_LAST_ADD_AT, System.currentTimeMillis())
|
|
181
164
|
.apply()
|
|
182
|
-
Log.i(TAG, "addGeofences: SUCCESS — geofences registered with Play Services")
|
|
183
165
|
promise.resolve(true)
|
|
184
166
|
}
|
|
185
|
-
.addOnFailureListener {
|
|
186
|
-
Log.e(TAG, "addGeofences: FAILURE — ${e.message}", e)
|
|
187
|
-
promise.resolve(false)
|
|
188
|
-
}
|
|
167
|
+
.addOnFailureListener { promise.resolve(false) }
|
|
189
168
|
} catch (e: Exception) {
|
|
190
|
-
Log.e(TAG, "addGeofences: exception", e)
|
|
191
169
|
promise.reject(e)
|
|
192
170
|
}
|
|
193
171
|
}
|
|
@@ -202,6 +180,7 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
202
180
|
put("latitude", d.latitude)
|
|
203
181
|
put("longitude", d.longitude)
|
|
204
182
|
put("radius", d.radius.toDouble())
|
|
183
|
+
put("data", d.userData ?: JSONObject.NULL)
|
|
205
184
|
})
|
|
206
185
|
}
|
|
207
186
|
getPrefs(context).edit().putString(PREFS_KEY_DETAILS, arr.toString()).apply()
|
|
@@ -209,20 +188,13 @@ class GeofenceManagerModule(reactContext: ReactApplicationContext) :
|
|
|
209
188
|
}
|
|
210
189
|
|
|
211
190
|
override fun removeAllGeofences(promise: Promise) {
|
|
212
|
-
Log.i(TAG, "removeAllGeofences: start")
|
|
213
191
|
synchronized(GeofenceManagerModule.geofenceNames) {
|
|
214
192
|
GeofenceManagerModule.geofenceNames.clear()
|
|
215
193
|
GeofenceManagerModule.geofenceDetailsMap.clear()
|
|
216
194
|
}
|
|
217
195
|
getPrefs(applicationContext).edit().remove(PREFS_KEY_DETAILS).apply()
|
|
218
196
|
geofencingClient.removeGeofences(getPendingIntent())
|
|
219
|
-
.addOnSuccessListener {
|
|
220
|
-
|
|
221
|
-
promise.resolve(true)
|
|
222
|
-
}
|
|
223
|
-
.addOnFailureListener { e ->
|
|
224
|
-
Log.e(TAG, "removeAllGeofences: FAILURE — ${e.message}", e)
|
|
225
|
-
promise.resolve(false)
|
|
226
|
-
}
|
|
197
|
+
.addOnSuccessListener { promise.resolve(true) }
|
|
198
|
+
.addOnFailureListener { promise.resolve(false) }
|
|
227
199
|
}
|
|
228
200
|
}
|
package/lib/module/index.js
CHANGED
|
@@ -2,23 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { AppRegistry, DeviceEventEmitter } from 'react-native';
|
|
4
4
|
import NativeGeofenceManager from "./NativeGeofenceManager.js";
|
|
5
|
-
import { geofenceDebugLog, geofenceDebugWarn } from "./geofenceDebugLog.js";
|
|
6
5
|
const EVENT_NAME = 'onGeofenceTransition';
|
|
7
6
|
|
|
8
7
|
/** Nome da headless task para eventos de geofence (app morto/background). Deve ser usado com registerGeofenceHeadlessTask no index do app. */
|
|
9
8
|
export const GEOFENCE_HEADLESS_TASK_NAME = 'GeofenceManagerTransition';
|
|
10
9
|
export function addGeofenceEventListener(callback) {
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
};
|
|
10
|
+
const subscription = DeviceEventEmitter.addListener(EVENT_NAME, payload => callback(payload));
|
|
11
|
+
return () => subscription.remove();
|
|
22
12
|
}
|
|
23
13
|
export function onGeofenceEvent(callback) {
|
|
24
14
|
return addGeofenceEventListener(callback);
|
|
@@ -27,60 +17,15 @@ export function onGeofenceEvent(callback) {
|
|
|
27
17
|
/**
|
|
28
18
|
* Registra o handler da headless task para quando o app é acordado por um evento de geofence
|
|
29
19
|
* (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
20
|
*/
|
|
44
21
|
export function registerGeofenceHeadlessTask(callback) {
|
|
45
|
-
|
|
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
|
-
});
|
|
22
|
+
AppRegistry.registerHeadlessTask(GEOFENCE_HEADLESS_TASK_NAME, () => data => Promise.resolve(callback(data)));
|
|
52
23
|
}
|
|
53
|
-
const addGeofences =
|
|
54
|
-
|
|
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
|
|
62
|
-
});
|
|
63
|
-
if (!ok) {
|
|
64
|
-
geofenceDebugWarn('JS: addGeofences — native returned false (empty list, Geofencing API failure, or permissions)');
|
|
65
|
-
}
|
|
66
|
-
return ok;
|
|
67
|
-
} catch (e) {
|
|
68
|
-
geofenceDebugWarn('JS: addGeofences — threw (TurboModule missing or bridge error)', e);
|
|
69
|
-
throw e;
|
|
70
|
-
}
|
|
24
|
+
const addGeofences = geofences => {
|
|
25
|
+
return NativeGeofenceManager.addGeofences(geofences);
|
|
71
26
|
};
|
|
72
|
-
const removeAllGeofences =
|
|
73
|
-
|
|
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;
|
|
83
|
-
}
|
|
27
|
+
const removeAllGeofences = () => {
|
|
28
|
+
return NativeGeofenceManager.removeAllGeofences();
|
|
84
29
|
};
|
|
85
30
|
export { addGeofences, removeAllGeofences };
|
|
86
31
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AppRegistry","DeviceEventEmitter","NativeGeofenceManager","
|
|
1
|
+
{"version":3,"names":["AppRegistry","DeviceEventEmitter","NativeGeofenceManager","EVENT_NAME","GEOFENCE_HEADLESS_TASK_NAME","addGeofenceEventListener","callback","subscription","addListener","payload","remove","onGeofenceEvent","registerGeofenceHeadlessTask","registerHeadlessTask","data","Promise","resolve","addGeofences","geofences","removeAllGeofences"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,WAAW,EACXC,kBAAkB,QAEb,cAAc;AACrB,OAAOC,qBAAqB,MAAM,4BAAyB;AAS3D,MAAMC,UAAU,GAAG,sBAAsB;;AAEzC;AACA,OAAO,MAAMC,2BAA2B,GAAG,2BAA2B;AAEtE,OAAO,SAASC,wBAAwBA,CACtCC,QAAwC,EAC5B;EACZ,MAAMC,YAA+B,GAAGN,kBAAkB,CAACO,WAAW,CACpEL,UAAU,EACTM,OAAgB,IAAKH,QAAQ,CAACG,OAAwB,CACzD,CAAC;EACD,OAAO,MAAMF,YAAY,CAACG,MAAM,CAAC,CAAC;AACpC;AAEA,OAAO,SAASC,eAAeA,CAC7BL,QAAwC,EAC5B;EACZ,OAAOD,wBAAwB,CAACC,QAAQ,CAAC;AAC3C;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASM,4BAA4BA,CAC1CN,QAAwC,EAClC;EACNN,WAAW,CAACa,oBAAoB,CAC9BT,2BAA2B,EAC3B,MAAOU,IAAa,IAAKC,OAAO,CAACC,OAAO,CAACV,QAAQ,CAACQ,IAAqB,CAAC,CAC1E,CAAC;AACH;AAEA,MAAMG,YAAY,GAAIC,SAA0B,IAAuB;EACrE,OAAOhB,qBAAqB,CAACe,YAAY,CAACC,SAAS,CAAC;AACtD,CAAC;AAED,MAAMC,kBAAkB,GAAGA,CAAA,KAAwB;EACjD,OAAOjB,qBAAqB,CAACiB,kBAAkB,CAAC,CAAC;AACnD,CAAC;AAED,SAASF,YAAY,EAAEE,kBAAkB","ignoreList":[]}
|
|
@@ -7,19 +7,6 @@ export declare function onGeofenceEvent(callback: (event: GeofenceEvent) => void
|
|
|
7
7
|
/**
|
|
8
8
|
* Registra o handler da headless task para quando o app é acordado por um evento de geofence
|
|
9
9
|
* (app morto ou em background). Deve ser chamado no index do app, antes de AppRegistry.registerComponent.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* // index.js
|
|
13
|
-
* import { AppRegistry } from 'react-native';
|
|
14
|
-
* import { registerGeofenceHeadlessTask } from 'react-native-geofence-manager';
|
|
15
|
-
* import App from './App';
|
|
16
|
-
* import { name as appName } from './app.json';
|
|
17
|
-
*
|
|
18
|
-
* registerGeofenceHeadlessTask((event) => {
|
|
19
|
-
* console.log('Geofence (headless):', event.geofenceId, event.event);
|
|
20
|
-
* });
|
|
21
|
-
*
|
|
22
|
-
* AppRegistry.registerComponent(appName, () => App);
|
|
23
10
|
*/
|
|
24
11
|
export declare function registerGeofenceHeadlessTask(callback: (event: GeofenceEvent) => void): void;
|
|
25
12
|
declare const addGeofences: (geofences: GeofenceModel[]) => Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEnE,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,aAAa,GACd,MAAM,gBAAgB,CAAC;AAIxB,8IAA8I;AAC9I,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AAEvE,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GACvC,MAAM,IAAI,CAMZ;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GACvC,MAAM,IAAI,CAEZ;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GACvC,IAAI,CAKN;AAED,QAAA,MAAM,YAAY,GAAI,WAAW,aAAa,EAAE,KAAG,OAAO,CAAC,OAAO,CAEjE,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAO,OAAO,CAAC,OAAO,CAE7C,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -7,5 +7,9 @@ export type GeofenceEvent = {
|
|
|
7
7
|
latitude?: number;
|
|
8
8
|
longitude?: number;
|
|
9
9
|
radius?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Mesmo valor passado em `GeofenceModel.data` ao registrar; string opaca para o app parsear.
|
|
12
|
+
*/
|
|
13
|
+
data?: string;
|
|
10
14
|
};
|
|
11
15
|
//# sourceMappingURL=GeofenceEvent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeofenceEvent.d.ts","sourceRoot":"","sources":["../../../../src/models/GeofenceEvent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,iBAAiB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"GeofenceEvent.d.ts","sourceRoot":"","sources":["../../../../src/models/GeofenceEvent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,iBAAiB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC"}
|
|
@@ -4,5 +4,10 @@ export interface GeofenceModel {
|
|
|
4
4
|
radius?: number;
|
|
5
5
|
latitude: number;
|
|
6
6
|
longitude: number;
|
|
7
|
+
/**
|
|
8
|
+
* String livre (ex.: JSON serializado) repassada em todo `GeofenceEvent` desta geofence.
|
|
9
|
+
* O app faz o parse como quiser.
|
|
10
|
+
*/
|
|
11
|
+
data?: string;
|
|
7
12
|
}
|
|
8
13
|
//# sourceMappingURL=GeofenceModel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeofenceModel.d.ts","sourceRoot":"","sources":["../../../../src/models/GeofenceModel.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"GeofenceModel.d.ts","sourceRoot":"","sources":["../../../../src/models/GeofenceModel.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
type EventSubscription,
|
|
5
5
|
} from 'react-native';
|
|
6
6
|
import NativeGeofenceManager from './NativeGeofenceManager';
|
|
7
|
-
import { geofenceDebugLog, geofenceDebugWarn } from './geofenceDebugLog';
|
|
8
7
|
import type { GeofenceEvent, GeofenceModel } from './models/index';
|
|
9
8
|
|
|
10
9
|
export type {
|
|
@@ -21,20 +20,11 @@ export const GEOFENCE_HEADLESS_TASK_NAME = 'GeofenceManagerTransition';
|
|
|
21
20
|
export function addGeofenceEventListener(
|
|
22
21
|
callback: (event: GeofenceEvent) => void
|
|
23
22
|
): () => void {
|
|
24
|
-
geofenceDebugLog('JS: addGeofenceEventListener — registering listener', {
|
|
25
|
-
eventName: EVENT_NAME,
|
|
26
|
-
});
|
|
27
23
|
const subscription: EventSubscription = DeviceEventEmitter.addListener(
|
|
28
24
|
EVENT_NAME,
|
|
29
|
-
(payload: unknown) =>
|
|
30
|
-
geofenceDebugLog('JS: addGeofenceEventListener — event received', payload);
|
|
31
|
-
callback(payload as GeofenceEvent);
|
|
32
|
-
}
|
|
25
|
+
(payload: unknown) => callback(payload as GeofenceEvent)
|
|
33
26
|
);
|
|
34
|
-
return () =>
|
|
35
|
-
geofenceDebugLog('JS: addGeofenceEventListener — unsubscribed');
|
|
36
|
-
subscription.remove();
|
|
37
|
-
};
|
|
27
|
+
return () => subscription.remove();
|
|
38
28
|
}
|
|
39
29
|
|
|
40
30
|
export function onGeofenceEvent(
|
|
@@ -46,67 +36,22 @@ export function onGeofenceEvent(
|
|
|
46
36
|
/**
|
|
47
37
|
* Registra o handler da headless task para quando o app é acordado por um evento de geofence
|
|
48
38
|
* (app morto ou em background). Deve ser chamado no index do app, antes de AppRegistry.registerComponent.
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* // index.js
|
|
52
|
-
* import { AppRegistry } from 'react-native';
|
|
53
|
-
* import { registerGeofenceHeadlessTask } from 'react-native-geofence-manager';
|
|
54
|
-
* import App from './App';
|
|
55
|
-
* import { name as appName } from './app.json';
|
|
56
|
-
*
|
|
57
|
-
* registerGeofenceHeadlessTask((event) => {
|
|
58
|
-
* console.log('Geofence (headless):', event.geofenceId, event.event);
|
|
59
|
-
* });
|
|
60
|
-
*
|
|
61
|
-
* AppRegistry.registerComponent(appName, () => App);
|
|
62
39
|
*/
|
|
63
40
|
export function registerGeofenceHeadlessTask(
|
|
64
41
|
callback: (event: GeofenceEvent) => void
|
|
65
42
|
): void {
|
|
66
|
-
geofenceDebugLog('JS: registerGeofenceHeadlessTask — registering', {
|
|
67
|
-
taskName: GEOFENCE_HEADLESS_TASK_NAME,
|
|
68
|
-
});
|
|
69
43
|
AppRegistry.registerHeadlessTask(
|
|
70
44
|
GEOFENCE_HEADLESS_TASK_NAME,
|
|
71
|
-
() => (data: unknown) =>
|
|
72
|
-
geofenceDebugLog('JS: headless task invoked', data);
|
|
73
|
-
return Promise.resolve(callback(data as GeofenceEvent));
|
|
74
|
-
}
|
|
45
|
+
() => (data: unknown) => Promise.resolve(callback(data as GeofenceEvent))
|
|
75
46
|
);
|
|
76
47
|
}
|
|
77
48
|
|
|
78
|
-
const addGeofences =
|
|
79
|
-
geofences
|
|
80
|
-
): Promise<boolean> => {
|
|
81
|
-
geofenceDebugLog('JS: addGeofences — calling native', {
|
|
82
|
-
count: geofences.length,
|
|
83
|
-
ids: geofences.map((g) => g.id),
|
|
84
|
-
});
|
|
85
|
-
try {
|
|
86
|
-
const ok = await NativeGeofenceManager.addGeofences(geofences);
|
|
87
|
-
geofenceDebugLog('JS: addGeofences — native result', { success: ok });
|
|
88
|
-
if (!ok) {
|
|
89
|
-
geofenceDebugWarn(
|
|
90
|
-
'JS: addGeofences — native returned false (empty list, Geofencing API failure, or permissions)'
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
return ok;
|
|
94
|
-
} catch (e) {
|
|
95
|
-
geofenceDebugWarn('JS: addGeofences — threw (TurboModule missing or bridge error)', e);
|
|
96
|
-
throw e;
|
|
97
|
-
}
|
|
49
|
+
const addGeofences = (geofences: GeofenceModel[]): Promise<boolean> => {
|
|
50
|
+
return NativeGeofenceManager.addGeofences(geofences);
|
|
98
51
|
};
|
|
99
52
|
|
|
100
|
-
const removeAllGeofences =
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
const ok = await NativeGeofenceManager.removeAllGeofences();
|
|
104
|
-
geofenceDebugLog('JS: removeAllGeofences — native result', { success: ok });
|
|
105
|
-
return ok;
|
|
106
|
-
} catch (e) {
|
|
107
|
-
geofenceDebugWarn('JS: removeAllGeofences — threw', e);
|
|
108
|
-
throw e;
|
|
109
|
-
}
|
|
53
|
+
const removeAllGeofences = (): Promise<boolean> => {
|
|
54
|
+
return NativeGeofenceManager.removeAllGeofences();
|
|
110
55
|
};
|
|
111
56
|
|
|
112
57
|
export { addGeofences, removeAllGeofences };
|
|
@@ -1,22 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"geofenceDebugLog.d.ts","sourceRoot":"","sources":["../../../src/geofenceDebugLog.ts"],"names":[],"mappings":"AAaA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAMnE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAMpE"}
|
package/src/geofenceDebugLog.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logs de diagnóstico da lib. Aparecem no Metro e no Logcat (Android) com filtro "GeofenceManager".
|
|
3
|
-
*/
|
|
4
|
-
const TAG = '[GeofenceManager]';
|
|
5
|
-
|
|
6
|
-
function safeStringify(data: unknown): string {
|
|
7
|
-
try {
|
|
8
|
-
return JSON.stringify(data);
|
|
9
|
-
} catch {
|
|
10
|
-
return String(data);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function geofenceDebugLog(step: string, data?: unknown): void {
|
|
15
|
-
const line =
|
|
16
|
-
data !== undefined
|
|
17
|
-
? `${TAG} ${step} ${safeStringify(data)}`
|
|
18
|
-
: `${TAG} ${step}`;
|
|
19
|
-
console.log(line);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function geofenceDebugWarn(step: string, data?: unknown): void {
|
|
23
|
-
const line =
|
|
24
|
-
data !== undefined
|
|
25
|
-
? `${TAG} ${step} ${safeStringify(data)}`
|
|
26
|
-
: `${TAG} ${step}`;
|
|
27
|
-
console.warn(line);
|
|
28
|
-
}
|