expo-background-tracking 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/FEATURES.md +110 -0
  2. package/README.md +61 -63
  3. package/package.json +1 -1
package/FEATURES.md ADDED
@@ -0,0 +1,110 @@
1
+ # Features
2
+
3
+ ## Core Capabilities
4
+
5
+ ### 🎯 Background Geolocation
6
+ - **Continuous tracking** in foreground and background (dev builds)
7
+ - **Configurable accuracy** levels (DESIRED_ACCURACY_HIGH, etc.)
8
+ - **Distance filtering** to reduce excessive location updates
9
+ - **Native GPS** integration with fallback to software-based tracking
10
+ - **Adaptive accuracy** based on device motion
11
+
12
+ ### 🎪 Geofencing (Unlimited)
13
+ - **Circle geofences** with customizable radius
14
+ - **Polygon geofences** for complex zone detection
15
+ - **Entry/Exit/Dwell events** with configurable delays
16
+ - **Software & native** evaluation modes
17
+ - **Loitering detection** to identify stationary periods
18
+
19
+ ### 📍 Motion Detection
20
+ - **Accelerometer-based** motion sensing
21
+ - **Battery-efficient** detection algorithm
22
+ - **Activity classification** (walking, running, vehicle, stationary)
23
+ - **Automatic pace control** for power optimization
24
+
25
+ ### 💾 Data Persistence
26
+ - **SQLite storage** for offline resilience
27
+ - **Automatic batching** for efficient queries
28
+ - **Configurable retention** (max days, max records)
29
+ - **Full queue visibility** and manual control
30
+
31
+ ### 🌐 HTTP Sync & Server Integration
32
+ - **Native fetch-based** transmission (no Firebase)
33
+ - **Offline queue** with automatic retry on reconnection
34
+ - **Batch transmission** to reduce network overhead
35
+ - **Custom headers & parameters** for auth/context
36
+ - **Template-based payloads** for flexible formatting
37
+ - **JWT authentication** with automatic token refresh
38
+ - **HTTP event tracking** for monitoring uploads
39
+
40
+ ### ⏱️ Scheduling
41
+ - **Weekly schedules** (e.g., "1-5 09:00-17:00" = Mon-Fri 9am-5pm)
42
+ - **Automatic start/stop** based on schedule
43
+ - **Smart scheduling** to save power during off-hours
44
+
45
+ ### 🔋 Battery & Power Management
46
+ - **Battery level reporting** in location data
47
+ - **Charging state detection**
48
+ - **Power save mode** awareness
49
+ - **Motion-based sleep** to reduce sampling when stationary
50
+ - **Efficient foreground service** (Android)
51
+
52
+ ### 📊 Metrics & Diagnostics
53
+ - **Odometer tracking** (distance traveled)
54
+ - **Sensor data collection** (GPS, accelerometer, compass)
55
+ - **Comprehensive logging** with debug output
56
+ - **Provider state monitoring** (GPS, network quality)
57
+ - **Heartbeat events** to confirm app is still tracking
58
+
59
+ ### 🔐 Security & Authentication
60
+ - **Bearer token support** in HTTP headers
61
+ - **JWT-based authentication** with refresh strategy
62
+ - **Custom headers** for API key injection
63
+ - **Secure HTTPS** for all transmissions
64
+
65
+ ## Platform Support
66
+
67
+ ### ✅ Supported Platforms
68
+ - **iOS** (13+) with UIBackgroundModes configuration
69
+ - **Android** (5+) with FOREGROUND_SERVICE permissions
70
+
71
+ ### 📱 Expo Compatibility
72
+ - **Expo Go**: Full foreground tracking, software geofencing
73
+ - **Dev builds**: Full background tracking with native geofencing
74
+ - **Production**: Full background tracking after EAS build
75
+
76
+ ## Performance Characteristics
77
+
78
+ - **Minimal battery drain** with optimized algorithms
79
+ - **Low memory footprint** (~5-10 MB)
80
+ - **Efficient database** queries with indexing
81
+ - **Batched network requests** to reduce data usage
82
+ - **Configurable trade-offs** between accuracy and power consumption
83
+
84
+ ## Integration Options
85
+
86
+ - **Seamless integration** with Expo ecosystem
87
+ - **Cross-platform** code (same logic iOS/Android)
88
+ - **Headless task support** for background processing
89
+ - **Full TypeScript** support with type definitions
90
+ - **Event-driven architecture** for reactive applications
91
+
92
+ ## Data Collection
93
+
94
+ Each location includes:
95
+ - **Coordinates** (latitude, longitude, accuracy)
96
+ - **Movement** (speed, heading, altitude)
97
+ - **Activity** (type, confidence level)
98
+ - **Battery** (level, charging state)
99
+ - **Device** (ID, model, OS)
100
+ - **Timestamp** (ISO 8601)
101
+ - **Odometer** (distance traveled)
102
+ - **Custom extras** (mission, user, etc.)
103
+
104
+ ## No External Dependencies
105
+
106
+ - ✅ No Firebase required
107
+ - ✅ No Google Play Services (uses native APIs)
108
+ - ✅ No paid tracking SDKs
109
+ - ✅ Full control over your data
110
+ - ✅ Custom server backend compatible
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # expo-background-tracking
2
2
 
3
- Tracking GPS & geofencing pour **Expo** (Android + iOS),100 % Expo, **sans Firebase**, sans code natif custom, **compatible Expo Go**.
3
+ GPS tracking & geofencing for **Expo** (Android + iOS), 100% Expo, **no Firebase**, no custom native code, **Expo Go compatible**.
4
4
 
5
- Détection de mouvement économe en batterie (accéléromètre + vitesse GPS), persistance SQLite, synchronisation HTTP avec file offline, geofencing illimité (cercles + polygones), odomètre, planning hebdomadaire.
5
+ Battery-efficient motion detection (accelerometer + GPS speed), SQLite persistence, HTTP sync with offline queue, unlimited geofencing (circles + polygons), odometer, weekly scheduling.
6
6
 
7
7
  ## Installation
8
8
 
@@ -11,18 +11,18 @@ npm install expo-background-tracking
11
11
  npx expo install expo-location expo-task-manager expo-sqlite expo-sensors expo-battery expo-network expo-device expo-constants
12
12
  ```
13
13
 
14
- ## Compatibilité Expo Go
14
+ ## Expo Go Compatibility
15
15
 
16
16
  | | Expo Go | Dev build / production |
17
17
  |---|---|---|
18
- | Tracking app ouverte (foreground) | ✅ | ✅ |
19
- | Tracking app minimisée (background) | ❌* | ✅ |
20
- | Geofencing | ✅ (logiciel, foreground) | ✅ (natif + logiciel) |
21
- | SQLite, HTTP sync, odomètre, scheduler, motion-detection | ✅ | ✅ |
18
+ | Tracking app in foreground | ✅ | ✅ |
19
+ | Tracking app in background | ❌* | ✅ |
20
+ | Geofencing | ✅ (software, foreground) | ✅ (native + software) |
21
+ | SQLite, HTTP sync, odometer, scheduler, motion-detection | ✅ | ✅ |
22
22
 
23
- \* Limitation officielle d'Expo : le background location exige un development build ([docs Expo](https://docs.expo.dev/versions/latest/sdk/location/)). La lib détecte l'environnement automatiquement — **même code partout**, zéro crash dans Expo Go.
23
+ \* Official Expo limitation: background location requires a development build ([Expo docs](https://docs.expo.dev/versions/latest/sdk/location/)). The library automatically detects the environment — **same code everywhere**, zero crashes in Expo Go.
24
24
 
25
- Pour le background complet (dev build), ajoutez dans `app.json` :
25
+ For full background (dev build), add to `app.json`:
26
26
 
27
27
  ```json
28
28
  {
@@ -42,7 +42,7 @@ Pour le background complet (dev build), ajoutez dans `app.json` :
42
42
  ```ts
43
43
  import BackgroundGeolocation from 'expo-background-tracking';
44
44
 
45
- // 1. Écouter les événements
45
+ // 1. Listen to events
46
46
  const sub = BackgroundGeolocation.onLocation((location) => {
47
47
  console.log('[location]', location.coords);
48
48
  });
@@ -55,25 +55,25 @@ BackgroundGeolocation.onGeofence(({ identifier, action }) => {
55
55
  console.log('[geofence]', identifier, action);
56
56
  });
57
57
 
58
- // 2. Configurer (ready, une seule fois)
58
+ // 2. Configure (ready, once only)
59
59
  const state = await BackgroundGeolocation.ready({
60
60
  desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
61
61
  distanceFilter: 10,
62
62
  stopTimeout: 5,
63
- url: 'https://your-server.com/locations', // HTTP sync — fetch natif, pas de Firebase
63
+ url: 'https://your-server.com/locations', // HTTP sync — native fetch, no Firebase
64
64
  autoSync: true,
65
65
  batchSync: false,
66
66
  headers: { 'X-API-KEY': 'xyz' },
67
67
  debug: true,
68
68
  });
69
69
 
70
- // 3. Démarrer
70
+ // 3. Start
71
71
  if (!state.enabled) {
72
72
  await BackgroundGeolocation.start();
73
73
  }
74
74
  ```
75
75
 
76
- ### Geofencing (illimité, cercles + polygones)
76
+ ### Geofencing (unlimited, circles + polygons)
77
77
 
78
78
  ```ts
79
79
  await BackgroundGeolocation.addGeofence({
@@ -87,70 +87,70 @@ await BackgroundGeolocation.addGeofence({
87
87
  loiteringDelay: 60000,
88
88
  });
89
89
 
90
- // Polygone (évalué en logiciel)
90
+ // Polygon (software-evaluated)
91
91
  await BackgroundGeolocation.addGeofence({
92
92
  identifier: 'ZONE',
93
93
  vertices: [[48.85, 2.34], [48.86, 2.34], [48.86, 2.36], [48.85, 2.36]],
94
94
  });
95
95
 
96
- await BackgroundGeolocation.startGeofences(); // mode geofences-only
96
+ await BackgroundGeolocation.startGeofences(); // geofences-only mode
97
97
  ```
98
98
 
99
- ## Envoi HTTP des positions vers votre serveur
99
+ ## Sending HTTP locations to your server
100
100
 
101
- La lib embarque un service HTTP complet (basé sur `fetch`, **sans Firebase**) : chaque position est persistée en SQLite puis envoyée à votre `url`. En cas d'échec (hors-ligne, erreur serveur), les positions restent en file et repartent automatiquement à la reconnexion.
101
+ The library includes a complete HTTP service (based on `fetch`, **no Firebase**): each location is persisted in SQLite then sent to your `url`. On failure (offline, server error), locations remain queued and are automatically resent on reconnection.
102
102
 
103
- ### Configuration de base
103
+ ### Basic configuration
104
104
 
105
105
  ```ts
106
106
  await BackgroundGeolocation.ready({
107
- url: 'https://votre-serveur.com/locations', // destination des positions
108
- method: 'POST', // 'POST' (défaut) | 'PUT' | 'OPTIONS'
109
- headers: { // headers HTTP personnalisés
107
+ url: 'https://your-server.com/locations', // destination for locations
108
+ method: 'POST', // 'POST' (default) | 'PUT' | 'OPTIONS'
109
+ headers: { // custom HTTP headers
110
110
  'X-API-KEY': 'abc123',
111
111
  'Authorization': 'Bearer ...',
112
112
  },
113
- params: { // champs ajoutés à la racine du corps JSON
113
+ params: { // fields added at JSON root level
114
114
  device_id: 'phone-01',
115
115
  company_id: 7,
116
116
  },
117
- extras: { // attachés à CHAQUE position envoyée
117
+ extras: { // attached to EVERY location sent
118
118
  user_id: 42,
119
- mission: 'livraison',
119
+ mission: 'delivery',
120
120
  },
121
- autoSync: true, // envoi automatique à chaque position
122
- httpTimeout: 60000, // timeout requête en ms
121
+ autoSync: true, // automatically send each location
122
+ httpTimeout: 60000, // request timeout in ms
123
123
  });
124
124
  ```
125
125
 
126
- ### Contrôler le nombre et la fréquence des envois
126
+ ### Control transmission count and frequency
127
127
 
128
- | Option | Effet |
128
+ | Option | Effect |
129
129
  |---|---|
130
- | `autoSync: true` | Envoie automatiquement chaque nouvelle position |
131
- | `autoSyncThreshold: 10` | N'envoie qu'à partir de **10 positions** accumulées en file |
132
- | `batchSync: true` | Envoie les positions **en lot** (1 requête HTTP = N positions) |
133
- | `maxBatchSize: 50` | Maximum **50 positions par requête** (les lots s'enchaînent) |
134
- | `autoSync: false` + `sync()` | Envoi **100 % manuel**, quand vous le décidez |
130
+ | `autoSync: true` | Automatically send each new location |
131
+ | `autoSyncThreshold: 10` | Only send when **10 locations** accumulate in queue |
132
+ | `batchSync: true` | Send locations **in batches** (1 HTTP request = N locations) |
133
+ | `maxBatchSize: 50` | Maximum **50 locations per request** (batches chain together) |
134
+ | `autoSync: false` + `sync()` | **100% manual** sending, when you decide |
135
135
 
136
136
  ```ts
137
- // Exemple : économiser la batterie/réseau — 1 requête tous les 25 points, par lots
137
+ // Example: save battery/network — 1 request per 25 points, in batches
138
138
  await BackgroundGeolocation.ready({
139
- url: 'https://votre-serveur.com/locations',
139
+ url: 'https://your-server.com/locations',
140
140
  autoSync: true,
141
141
  autoSyncThreshold: 25,
142
142
  batchSync: true,
143
143
  maxBatchSize: 100,
144
144
  });
145
145
 
146
- // Envoi manuel (par ex. sur bouton ou à la fin d'une mission)
146
+ // Manual send (e.g., on button or at mission end)
147
147
  const uploaded = await BackgroundGeolocation.sync();
148
- console.log(`${uploaded.length} positions envoyées`);
148
+ console.log(`${uploaded.length} locations sent`);
149
149
  ```
150
150
 
151
- ### Format du payload reçu par votre serveur
151
+ ### Payload format received by your server
152
152
 
153
- Par défaut (`httpRootProperty: 'location'`) :
153
+ By default (`httpRootProperty: 'location'`):
154
154
 
155
155
  ```json
156
156
  {
@@ -165,28 +165,28 @@ Par défaut (`httpRootProperty: 'location'`) :
165
165
  },
166
166
  "activity": { "activity": "walking", "confidence": 75 },
167
167
  "battery": { "level": 0.82, "is_charging": false },
168
- "extras": { "user_id": 42, "mission": "livraison" }
168
+ "extras": { "user_id": 42, "mission": "delivery" }
169
169
  },
170
170
  "device_id": "phone-01",
171
171
  "company_id": 7
172
172
  }
173
173
  ```
174
174
 
175
- Avec `batchSync: true`, `"location"` devient un **tableau** de positions.
175
+ With `batchSync: true`, `"location"` becomes an **array** of locations.
176
176
 
177
- ### Personnaliser le format
177
+ ### Customize format
178
178
 
179
179
  ```ts
180
180
  await BackgroundGeolocation.ready({
181
181
  url: '…',
182
- httpRootProperty: 'data', // { "data": {...} } — ou '.' pour aucun wrapper
182
+ httpRootProperty: 'data', // { "data": {...} } — or '.' for no wrapper
183
183
  locationTemplate: '{"lat":<%= latitude %>,"lng":<%= longitude %>,"ts":<%= timestamp %>,"batt":<%= battery.level %>}',
184
184
  });
185
185
  ```
186
186
 
187
- Variables de template : `latitude`, `longitude`, `accuracy`, `speed`, `heading`, `altitude`, `timestamp`, `uuid`, `odometer`, `is_moving`, `activity.type`, `activity.confidence`, `battery.level`, `battery.is_charging`.
187
+ Template variables: `latitude`, `longitude`, `accuracy`, `speed`, `heading`, `altitude`, `timestamp`, `uuid`, `odometer`, `is_moving`, `activity.type`, `activity.confidence`, `battery.level`, `battery.is_charging`.
188
188
 
189
- ### Suivre les envois
189
+ ### Track transmissions
190
190
 
191
191
  ```ts
192
192
  BackgroundGeolocation.onHttp((response) => {
@@ -194,27 +194,27 @@ BackgroundGeolocation.onHttp((response) => {
194
194
  });
195
195
  ```
196
196
 
197
- ### Persistance & sync manuel
197
+ ### Persistence & manual sync
198
198
 
199
199
  ```ts
200
- const count = await BackgroundGeolocation.getCount(); // positions en file
201
- const locations = await BackgroundGeolocation.getLocations(); // lire la file
202
- const uploaded = await BackgroundGeolocation.sync(); // envoyer maintenant
203
- await BackgroundGeolocation.destroyLocations(); // vider la file
200
+ const count = await BackgroundGeolocation.getCount(); // queued locations
201
+ const locations = await BackgroundGeolocation.getLocations(); // read queue
202
+ const uploaded = await BackgroundGeolocation.sync(); // send now
203
+ await BackgroundGeolocation.destroyLocations(); // empty queue
204
204
  ```
205
205
 
206
- Options de rétention : `maxDaysToPersist` (défaut 1 jour), `maxRecordsToPersist`, `persistMode` (`ALL` | `LOCATION` | `GEOFENCE` | `NONE`).
206
+ Retention options: `maxDaysToPersist` (default 1 day), `maxRecordsToPersist`, `persistMode` (`ALL` | `LOCATION` | `GEOFENCE` | `NONE`).
207
207
 
208
- ### Planning
208
+ ### Scheduling
209
209
 
210
210
  ```ts
211
211
  await BackgroundGeolocation.ready({
212
- schedule: ['1-5 09:00-17:00', '6 10:00-14:00'], // lun-ven 9h-17h, sam 10h-14h
212
+ schedule: ['1-5 09:00-17:00', '6 10:00-14:00'], // Mon-Fri 9am-5pm, Sat 10am-2pm
213
213
  });
214
214
  await BackgroundGeolocation.startSchedule();
215
215
  ```
216
216
 
217
- ### Odomètre, capteurs, état
217
+ ### Odometer, sensors, state
218
218
 
219
219
  ```ts
220
220
  const km = (await BackgroundGeolocation.getOdometer()) / 1000;
@@ -224,7 +224,7 @@ const providerState = await BackgroundGeolocation.getProviderState();
224
224
  const powerSave = await BackgroundGeolocation.isPowerSaveMode();
225
225
  ```
226
226
 
227
- ### Auth JWT avec refresh automatique (sur 401)
227
+ ### JWT auth with automatic refresh (on 401)
228
228
 
229
229
  ```ts
230
230
  await BackgroundGeolocation.ready({
@@ -239,15 +239,13 @@ await BackgroundGeolocation.ready({
239
239
  BackgroundGeolocation.onAuthorization((event) => console.log(event));
240
240
  ```
241
241
 
242
- ## API complète
242
+ ## Complete API
243
243
 
244
- Événements : `onLocation`, `onMotionChange`, `onActivityChange`, `onGeofence`, `onGeofencesChange`, `onHeartbeat`, `onHttp`, `onProviderChange`, `onConnectivityChange`, `onPowerSaveChange`, `onEnabledChange`, `onSchedule`, `onAuthorization`.
244
+ Events: `onLocation`, `onMotionChange`, `onActivityChange`, `onGeofence`, `onGeofencesChange`, `onHeartbeat`, `onHttp`, `onProviderChange`, `onConnectivityChange`, `onPowerSaveChange`, `onEnabledChange`, `onSchedule`, `onAuthorization`.
245
245
 
246
- Méthodes : `ready`, `start`, `stop`, `startGeofences`, `startSchedule`, `stopSchedule`, `changePace`, `getCurrentPosition`, `watchPosition`, `stopWatchPosition`, `getState`, `setConfig`, `reset`, `getLocations`, `getCount`, `insertLocation`, `destroyLocations`, `destroyLocation`, `sync`, `getOdometer`, `setOdometer`, `resetOdometer`, `addGeofence`, `addGeofences`, `removeGeofence`, `removeGeofences`, `getGeofences`, `getGeofence`, `geofenceExists`, `getSensors`, `getDeviceInfo`, `isPowerSaveMode`, `getProviderState`, `requestPermission`, `requestTemporaryFullAccuracy`, `registerHeadlessTask`, `startBackgroundTask`, `stopBackgroundTask`, `getLog`, `destroyLog`, `emailLog`, `removeListeners`.
246
+ Methods: `ready`, `start`, `stop`, `startGeofences`, `startSchedule`, `stopSchedule`, `changePace`, `getCurrentPosition`, `watchPosition`, `stopWatchPosition`, `getState`, `setConfig`, `reset`, `getLocations`, `getCount`, `insertLocation`, `destroyLocations`, `destroyLocation`, `sync`, `getOdometer`, `setOdometer`, `resetOdometer`, `addGeofence`, `addGeofences`, `removeGeofence`, `removeGeofences`, `getGeofences`, `getGeofence`, `geofenceExists`, `getSensors`, `getDeviceInfo`, `isPowerSaveMode`, `getProviderState`, `requestPermission`, `requestTemporaryFullAccuracy`, `registerHeadlessTask`, `startBackgroundTask`, `stopBackgroundTask`, `getLog`, `destroyLog`, `emailLog`, `removeListeners`.
247
247
 
248
-
249
-
250
- ## App de test
248
+ ## Test app
251
249
 
252
250
  ```bash
253
251
  cd testapp
@@ -255,6 +253,6 @@ npm install
255
253
  npx expo start --clear
256
254
  ```
257
255
 
258
- ## Licence
256
+ ## License
259
257
 
260
258
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-background-tracking",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Background geolocation & geofencing for Expo — battery-conscious motion-detection, SQLite persistence, HTTP sync. Expo Go compatible (foreground), full background in dev builds. No Firebase.",
5
5
  "keywords": [
6
6
  "expo",