@capgo/background-geolocation 7.0.10 → 7.0.11
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 +19 -18
- package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocation.java +47 -10
- package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocationService.java +122 -22
- package/dist/docs.json +49 -13
- package/dist/esm/definitions.d.ts +28 -12
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +11 -2
- package/dist/esm/web.js +95 -6
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +95 -6
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +95 -6
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/Plugin.m +1 -1
- package/ios/Plugin/Plugin.swift +148 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,8 +58,6 @@ BackgroundGeolocation.start(
|
|
|
58
58
|
}
|
|
59
59
|
return console.error(error);
|
|
60
60
|
}
|
|
61
|
-
// in case of off-track for example, play a sound:
|
|
62
|
-
BackgroundGeolocation.playSound({soundFile: "assets/myFile.mp3" });
|
|
63
61
|
return console.log(location);
|
|
64
62
|
}
|
|
65
63
|
).then(() => {
|
|
@@ -67,6 +65,10 @@ BackgroundGeolocation.start(
|
|
|
67
65
|
BackgroundGeolocation.stop();
|
|
68
66
|
});
|
|
69
67
|
|
|
68
|
+
// Set a planned route to get a notification sound when a new location arrives and it's not on the route:
|
|
69
|
+
|
|
70
|
+
BackgroundGeolocation.setPlannedRoute({soundFile: "assets/myFile.mp3", route: [[1,2], [3,4]], distance: 30 });
|
|
71
|
+
|
|
70
72
|
// If you just want the current location, try something like this. The longer
|
|
71
73
|
// the timeout, the more accurate the guess will be. I wouldn't go below about 100ms.
|
|
72
74
|
function guessLocation(callback, timeout) {
|
|
@@ -177,7 +179,7 @@ Configration specific to Android can be made in `strings.xml`:
|
|
|
177
179
|
* [`start(...)`](#start)
|
|
178
180
|
* [`stop()`](#stop)
|
|
179
181
|
* [`openSettings()`](#opensettings)
|
|
180
|
-
* [`
|
|
182
|
+
* [`setPlannedRoute(...)`](#setplannedroute)
|
|
181
183
|
* [Interfaces](#interfaces)
|
|
182
184
|
|
|
183
185
|
</docgen-index>
|
|
@@ -235,23 +237,20 @@ Useful for directing users to enable location services or adjust permissions.
|
|
|
235
237
|
--------------------
|
|
236
238
|
|
|
237
239
|
|
|
238
|
-
###
|
|
240
|
+
### setPlannedRoute(...)
|
|
239
241
|
|
|
240
242
|
```typescript
|
|
241
|
-
|
|
243
|
+
setPlannedRoute(options: SetPlannedRouteOptions) => Promise<void>
|
|
242
244
|
```
|
|
243
245
|
|
|
244
|
-
Plays a sound file.
|
|
245
|
-
This should be used to play a sound
|
|
246
|
-
The idea behind this is to allow the user to hear a sound when a new location is available or when going off track.
|
|
247
|
-
If you simply need to play a sound, you can use `@capgo/native-audio` plugin instead.
|
|
248
|
-
For Android, there's a need to start monitoring location updates first, otherwise the sound will not play.
|
|
246
|
+
Plays a sound file when the user deviates from the planned route.
|
|
247
|
+
This should be used to play a sound (in the background too, only for native).
|
|
249
248
|
|
|
250
|
-
| Param | Type
|
|
251
|
-
| ------------- |
|
|
252
|
-
| **`options`** | <code><a href="#
|
|
249
|
+
| Param | Type | Description |
|
|
250
|
+
| ------------- | ------------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
251
|
+
| **`options`** | <code><a href="#setplannedrouteoptions">SetPlannedRouteOptions</a></code> | The options for setting the planned route and sound file |
|
|
253
252
|
|
|
254
|
-
**Since:** 7.0.
|
|
253
|
+
**Since:** 7.0.11
|
|
255
254
|
|
|
256
255
|
--------------------
|
|
257
256
|
|
|
@@ -300,10 +299,12 @@ Extends the standard Error with optional error codes.
|
|
|
300
299
|
| **`code`** | <code>string</code> | Optional error code for more specific error handling. | 7.0.0 |
|
|
301
300
|
|
|
302
301
|
|
|
303
|
-
####
|
|
302
|
+
#### SetPlannedRouteOptions
|
|
304
303
|
|
|
305
|
-
| Prop | Type
|
|
306
|
-
| --------------- |
|
|
307
|
-
| **`soundFile`** | <code>string</code>
|
|
304
|
+
| Prop | Type | Description | Default | Since |
|
|
305
|
+
| --------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------ |
|
|
306
|
+
| **`soundFile`** | <code>string</code> | The name of the sound file to play. Must be a valid sound relative path in the app's public folder to work for both web and native platforms. There's no need to include the public folder in the path. | | 7.0.10 |
|
|
307
|
+
| **`route`** | <code>[number, number][]</code> | The planned route as an array of longitude and latitude pairs. Each pair represents a point on the route. This is used to define a route that the user can follow. The route is used to play a sound when the user deviates from it. | | 7.0.11 |
|
|
308
|
+
| **`distance`** | <code>number</code> | The distance in meters that the user must deviate from the planned route to trigger the sound. This is used to determine how far off the route the user can be before the sound is played. If not specified, a default value of 50 meters is used. | <code>50</code> | 7.0.11 |
|
|
308
309
|
|
|
309
310
|
</docgen-api>
|
package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocation.java
CHANGED
|
@@ -15,7 +15,9 @@ import android.net.Uri;
|
|
|
15
15
|
import android.os.Build;
|
|
16
16
|
import android.os.IBinder;
|
|
17
17
|
import android.provider.Settings;
|
|
18
|
+
import androidx.annotation.Nullable;
|
|
18
19
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
20
|
+
import com.getcapacitor.JSArray;
|
|
19
21
|
import com.getcapacitor.JSObject;
|
|
20
22
|
import com.getcapacitor.Logger;
|
|
21
23
|
import com.getcapacitor.PermissionState;
|
|
@@ -27,6 +29,8 @@ import com.getcapacitor.annotation.Permission;
|
|
|
27
29
|
import com.getcapacitor.annotation.PermissionCallback;
|
|
28
30
|
import com.google.android.gms.location.LocationServices;
|
|
29
31
|
import java.util.concurrent.CompletableFuture;
|
|
32
|
+
import org.json.JSONArray;
|
|
33
|
+
import org.json.JSONException;
|
|
30
34
|
import org.json.JSONObject;
|
|
31
35
|
|
|
32
36
|
@CapacitorPlugin(
|
|
@@ -189,7 +193,7 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
189
193
|
}
|
|
190
194
|
|
|
191
195
|
@PluginMethod
|
|
192
|
-
public void
|
|
196
|
+
public void setPlannedRoute(PluginCall call) {
|
|
193
197
|
String soundFile = call.getString("soundFile");
|
|
194
198
|
if (soundFile == null || soundFile.isEmpty()) {
|
|
195
199
|
call.reject("Sound file is required");
|
|
@@ -202,15 +206,48 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
202
206
|
);
|
|
203
207
|
return;
|
|
204
208
|
}
|
|
205
|
-
|
|
206
|
-
.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
209
|
+
try {
|
|
210
|
+
double[][] javaDoubleArray = getJavaDoubleArray(call.getArray("route"));
|
|
211
|
+
serviceConnectionFuture
|
|
212
|
+
.thenAccept(service -> {
|
|
213
|
+
service.setPlannedRoute(
|
|
214
|
+
soundFile,
|
|
215
|
+
javaDoubleArray,
|
|
216
|
+
call.getFloat("distance", 50f)
|
|
217
|
+
);
|
|
218
|
+
call.resolve();
|
|
219
|
+
})
|
|
220
|
+
.exceptionally(throwable -> {
|
|
221
|
+
call.reject("Failed to set route: " + throwable.getMessage());
|
|
222
|
+
return null;
|
|
223
|
+
});
|
|
224
|
+
} catch (Exception ex) {
|
|
225
|
+
call.reject("Unable to parse route parameters");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private static double[][] getJavaDoubleArray(JSArray jsArray)
|
|
230
|
+
throws JSONException {
|
|
231
|
+
int rows = jsArray.length();
|
|
232
|
+
if (rows == 0) {
|
|
233
|
+
return new double[0][2];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
JSONArray firstRow = jsArray.getJSONArray(0);
|
|
237
|
+
int cols = firstRow.length();
|
|
238
|
+
|
|
239
|
+
var javaDoubleArray = new double[rows][cols];
|
|
240
|
+
|
|
241
|
+
for (int i = 0; i < rows; i++) {
|
|
242
|
+
JSONArray rowArray = jsArray.getJSONArray(i);
|
|
243
|
+
if (rowArray.length() != cols) {
|
|
244
|
+
throw new JSONException("Input array is not a consistent 2D array.");
|
|
245
|
+
}
|
|
246
|
+
for (int j = 0; j < cols; j++) {
|
|
247
|
+
javaDoubleArray[i][j] = rowArray.getDouble(j);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return javaDoubleArray;
|
|
214
251
|
}
|
|
215
252
|
|
|
216
253
|
// Checks if device-wide location services are disabled
|
|
@@ -26,6 +26,8 @@ public class BackgroundGeolocationService extends Service {
|
|
|
26
26
|
(BackgroundGeolocationService.class.getPackage().getName() + ".broadcast");
|
|
27
27
|
private final IBinder binder = new LocalBinder();
|
|
28
28
|
|
|
29
|
+
private static final double EARTH_RADIUS_M = 6371000;
|
|
30
|
+
|
|
29
31
|
// Must be unique for this application.
|
|
30
32
|
private static final int NOTIFICATION_ID = 28351;
|
|
31
33
|
|
|
@@ -34,6 +36,9 @@ public class BackgroundGeolocationService extends Service {
|
|
|
34
36
|
private LocationManager client;
|
|
35
37
|
private LocationListener locationCallback;
|
|
36
38
|
private MediaPlayer mediaPlayer;
|
|
39
|
+
private double[][] route;
|
|
40
|
+
private double distanceThreshold;
|
|
41
|
+
private boolean isOffRoute;
|
|
37
42
|
|
|
38
43
|
@Override
|
|
39
44
|
public IBinder onBind(Intent intent) {
|
|
@@ -83,10 +88,19 @@ public class BackgroundGeolocationService extends Service {
|
|
|
83
88
|
final String notificationMessage,
|
|
84
89
|
float distanceFilter
|
|
85
90
|
) {
|
|
91
|
+
releaseMediaPlayer();
|
|
86
92
|
client = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
|
87
93
|
callbackId = id;
|
|
88
94
|
|
|
89
95
|
locationCallback = location -> {
|
|
96
|
+
if (mediaPlayer != null) {
|
|
97
|
+
double[] point = { location.getLongitude(), location.getLatitude() };
|
|
98
|
+
var offRoute = distancePointToRoute(point) > distanceThreshold;
|
|
99
|
+
if (offRoute == true && isOffRoute == false) {
|
|
100
|
+
mediaPlayer.start();
|
|
101
|
+
}
|
|
102
|
+
isOffRoute = offRoute;
|
|
103
|
+
}
|
|
90
104
|
Intent intent = new Intent(ACTION_BROADCAST);
|
|
91
105
|
intent.putExtra("location", location);
|
|
92
106
|
intent.putExtra("id", callbackId);
|
|
@@ -131,15 +145,23 @@ public class BackgroundGeolocationService extends Service {
|
|
|
131
145
|
client.removeUpdates(locationCallback);
|
|
132
146
|
stopForeground(true);
|
|
133
147
|
stopSelf();
|
|
148
|
+
releaseMediaPlayer();
|
|
134
149
|
return callbackId;
|
|
135
150
|
}
|
|
136
151
|
|
|
137
|
-
void
|
|
152
|
+
void setPlannedRoute(
|
|
153
|
+
String filePath,
|
|
154
|
+
double[][] routeCoordinates,
|
|
155
|
+
float distance
|
|
156
|
+
) {
|
|
157
|
+
route = routeCoordinates;
|
|
158
|
+
distanceThreshold = distance;
|
|
159
|
+
isOffRoute = true;
|
|
138
160
|
try {
|
|
139
|
-
|
|
140
|
-
|
|
161
|
+
if (mediaPlayer != null) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
141
164
|
mediaPlayer = new MediaPlayer();
|
|
142
|
-
|
|
143
165
|
AssetManager am = getApplicationContext().getResources().getAssets();
|
|
144
166
|
AssetFileDescriptor assetFileDescriptor = am.openFd(
|
|
145
167
|
"public/" + filePath
|
|
@@ -152,15 +174,6 @@ public class BackgroundGeolocationService extends Service {
|
|
|
152
174
|
);
|
|
153
175
|
mediaPlayer.setLooping(false);
|
|
154
176
|
|
|
155
|
-
mediaPlayer.setOnCompletionListener(mp -> {
|
|
156
|
-
try {
|
|
157
|
-
mp.release();
|
|
158
|
-
} catch (Exception e) {
|
|
159
|
-
Logger.error("Error releasing MediaPlayer on completion", e);
|
|
160
|
-
}
|
|
161
|
-
mediaPlayer = null;
|
|
162
|
-
});
|
|
163
|
-
|
|
164
177
|
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
|
|
165
178
|
Logger.error("MediaPlayer error: what=" + what + ", extra=" + extra);
|
|
166
179
|
releaseMediaPlayer();
|
|
@@ -168,15 +181,6 @@ public class BackgroundGeolocationService extends Service {
|
|
|
168
181
|
});
|
|
169
182
|
|
|
170
183
|
mediaPlayer.prepareAsync();
|
|
171
|
-
mediaPlayer.setOnPreparedListener(mp -> {
|
|
172
|
-
try {
|
|
173
|
-
mp.start();
|
|
174
|
-
Logger.debug("PlaySound: Successfully started playing sound");
|
|
175
|
-
} catch (Exception e) {
|
|
176
|
-
Logger.error("Error starting MediaPlayer", e);
|
|
177
|
-
releaseMediaPlayer();
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
184
|
} catch (Exception e) {
|
|
181
185
|
Logger.error("PlaySound: Unexpected error", e);
|
|
182
186
|
releaseMediaPlayer();
|
|
@@ -272,4 +276,100 @@ public class BackgroundGeolocationService extends Service {
|
|
|
272
276
|
int id = getAppResourceIdentifier(name, "string", context);
|
|
273
277
|
return id == 0 ? fallback : context.getString(id);
|
|
274
278
|
}
|
|
279
|
+
|
|
280
|
+
private static double haversine(double[] point1, double[] point2) {
|
|
281
|
+
double lon1 = point1[0];
|
|
282
|
+
double lat1 = point1[1];
|
|
283
|
+
double lon2 = point2[0];
|
|
284
|
+
double lat2 = point2[1];
|
|
285
|
+
|
|
286
|
+
double dLat = Math.toRadians(lat2 - lat1);
|
|
287
|
+
double dLon = Math.toRadians(lon2 - lon1);
|
|
288
|
+
|
|
289
|
+
double a =
|
|
290
|
+
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
291
|
+
Math.cos(Math.toRadians(lat1)) *
|
|
292
|
+
Math.cos(Math.toRadians(lat2)) *
|
|
293
|
+
Math.sin(dLon / 2) *
|
|
294
|
+
Math.sin(dLon / 2);
|
|
295
|
+
|
|
296
|
+
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
297
|
+
|
|
298
|
+
return EARTH_RADIUS_M * c;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private static double distancePointToLineSegment(
|
|
302
|
+
double[] point,
|
|
303
|
+
double[] lineStart,
|
|
304
|
+
double[] lineEnd
|
|
305
|
+
) {
|
|
306
|
+
// Calculate the distances between the three points using Haversine
|
|
307
|
+
double dist_A_B = haversine(point, lineStart);
|
|
308
|
+
double dist_A_C = haversine(point, lineEnd);
|
|
309
|
+
double dist_B_C = haversine(lineStart, lineEnd);
|
|
310
|
+
|
|
311
|
+
// Handle the edge case where the line segment is a single point
|
|
312
|
+
if (dist_B_C == 0) {
|
|
313
|
+
return dist_A_B;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Check if the angles at the line segment's endpoints are obtuse.
|
|
317
|
+
// We use the Law of Cosines (c^2 = a^2 + b^2 - 2ab*cos(C))
|
|
318
|
+
// If cos(C) < 0, the angle is obtuse.
|
|
319
|
+
|
|
320
|
+
// Angle at B (lineStart)
|
|
321
|
+
// Use a small epsilon to handle floating point inaccuracies in division by zero
|
|
322
|
+
double cos_B =
|
|
323
|
+
(Math.pow(dist_A_B, 2) + Math.pow(dist_B_C, 2) - Math.pow(dist_A_C, 2)) /
|
|
324
|
+
(2 * dist_A_B * dist_B_C);
|
|
325
|
+
if (cos_B < 0) {
|
|
326
|
+
return dist_A_B;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Angle at C (lineEnd)
|
|
330
|
+
double cos_C =
|
|
331
|
+
(Math.pow(dist_A_C, 2) + Math.pow(dist_B_C, 2) - Math.pow(dist_A_B, 2)) /
|
|
332
|
+
(2 * dist_A_C * dist_B_C);
|
|
333
|
+
if (cos_C < 0) {
|
|
334
|
+
return dist_A_C;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// If both angles are acute, the closest point is on the line segment itself.
|
|
338
|
+
// We can calculate the distance (height of the triangle) using its area.
|
|
339
|
+
|
|
340
|
+
// 1. Calculate the semi-perimeter of the triangle ABC
|
|
341
|
+
double s = (dist_A_B + dist_A_C + dist_B_C) / 2;
|
|
342
|
+
|
|
343
|
+
// 2. Calculate the area using Heron's formula
|
|
344
|
+
double area = Math.sqrt(
|
|
345
|
+
Math.max(0, s * (s - dist_A_B) * (s - dist_A_C) * (s - dist_B_C))
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
// 3. The distance is the height of the triangle from point A to the base BC
|
|
349
|
+
// Area = 0.5 * base * height => height = 2 * Area / base
|
|
350
|
+
return (2 * area) / dist_B_C;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
public double distancePointToRoute(double[] point) {
|
|
354
|
+
// If the polyline has less than 2 points, we can't form a segment.
|
|
355
|
+
if (this.route.length < 2) {
|
|
356
|
+
if (this.route.length == 1) {
|
|
357
|
+
return haversine(point, this.route[0]);
|
|
358
|
+
}
|
|
359
|
+
return Double.POSITIVE_INFINITY; // No line segments to measure against
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
double minDistance = Double.POSITIVE_INFINITY;
|
|
363
|
+
|
|
364
|
+
for (int i = 0; i < this.route.length - 1; i++) {
|
|
365
|
+
double[] lineStart = this.route[i];
|
|
366
|
+
double[] lineEnd = this.route[i + 1];
|
|
367
|
+
double distance = distancePointToLineSegment(point, lineStart, lineEnd);
|
|
368
|
+
if (distance < minDistance) {
|
|
369
|
+
minDistance = distance;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return minDistance;
|
|
374
|
+
}
|
|
275
375
|
}
|
package/dist/docs.json
CHANGED
|
@@ -103,39 +103,39 @@
|
|
|
103
103
|
"slug": "opensettings"
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
|
-
"name": "
|
|
107
|
-
"signature": "(options:
|
|
106
|
+
"name": "setPlannedRoute",
|
|
107
|
+
"signature": "(options: SetPlannedRouteOptions) => Promise<void>",
|
|
108
108
|
"parameters": [
|
|
109
109
|
{
|
|
110
110
|
"name": "options",
|
|
111
|
-
"docs": "The options for
|
|
112
|
-
"type": "
|
|
111
|
+
"docs": "The options for setting the planned route and sound file",
|
|
112
|
+
"type": "SetPlannedRouteOptions"
|
|
113
113
|
}
|
|
114
114
|
],
|
|
115
115
|
"returns": "Promise<void>",
|
|
116
116
|
"tags": [
|
|
117
117
|
{
|
|
118
118
|
"name": "param",
|
|
119
|
-
"text": "options The options for
|
|
119
|
+
"text": "options The options for setting the planned route and sound file"
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
"name": "returns",
|
|
123
|
-
"text": "A promise that resolves when the
|
|
123
|
+
"text": "A promise that resolves when the route is set successfully"
|
|
124
124
|
},
|
|
125
125
|
{
|
|
126
126
|
"name": "since",
|
|
127
|
-
"text": "7.0.
|
|
127
|
+
"text": "7.0.11"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
130
|
"name": "example",
|
|
131
|
-
"text": "await BackgroundGeolocation.
|
|
131
|
+
"text": "await BackgroundGeolocation.setPlannedRoute({\n soundFile: \"notification.mp3\",\n route: [[-74.0060, 40.7128], [-118.2437, 34.0522]]\n});"
|
|
132
132
|
}
|
|
133
133
|
],
|
|
134
|
-
"docs": "Plays a sound file
|
|
134
|
+
"docs": "Plays a sound file when the user deviates from the planned route.\nThis should be used to play a sound (in the background too, only for native).",
|
|
135
135
|
"complexTypes": [
|
|
136
|
-
"
|
|
136
|
+
"SetPlannedRouteOptions"
|
|
137
137
|
],
|
|
138
|
-
"slug": "
|
|
138
|
+
"slug": "setplannedroute"
|
|
139
139
|
}
|
|
140
140
|
],
|
|
141
141
|
"properties": []
|
|
@@ -440,8 +440,8 @@
|
|
|
440
440
|
]
|
|
441
441
|
},
|
|
442
442
|
{
|
|
443
|
-
"name": "
|
|
444
|
-
"slug": "
|
|
443
|
+
"name": "SetPlannedRouteOptions",
|
|
444
|
+
"slug": "setplannedrouteoptions",
|
|
445
445
|
"docs": "",
|
|
446
446
|
"tags": [],
|
|
447
447
|
"methods": [],
|
|
@@ -461,6 +461,42 @@
|
|
|
461
461
|
"docs": "The name of the sound file to play.\nMust be a valid sound relative path in the app's public folder to work for both web and native platforms.\nThere's no need to include the public folder in the path.",
|
|
462
462
|
"complexTypes": [],
|
|
463
463
|
"type": "string"
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
"name": "route",
|
|
467
|
+
"tags": [
|
|
468
|
+
{
|
|
469
|
+
"text": "7.0.11",
|
|
470
|
+
"name": "since"
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"text": "[[-74.0060, 40.7128], [-118.2437, 34.0522]]",
|
|
474
|
+
"name": "example"
|
|
475
|
+
}
|
|
476
|
+
],
|
|
477
|
+
"docs": "The planned route as an array of longitude and latitude pairs.\nEach pair represents a point on the route.\nThis is used to define a route that the user can follow.\nThe route is used to play a sound when the user deviates from it.",
|
|
478
|
+
"complexTypes": [],
|
|
479
|
+
"type": "[number, number][]"
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"name": "distance",
|
|
483
|
+
"tags": [
|
|
484
|
+
{
|
|
485
|
+
"text": "7.0.11",
|
|
486
|
+
"name": "since"
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
"text": "50",
|
|
490
|
+
"name": "default"
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"text": "50",
|
|
494
|
+
"name": "example"
|
|
495
|
+
}
|
|
496
|
+
],
|
|
497
|
+
"docs": "The distance in meters that the user must deviate from the planned route to trigger the sound.\nThis is used to determine how far off the route the user can be before the sound is played.\nIf not specified, a default value of 50 meters is used.",
|
|
498
|
+
"complexTypes": [],
|
|
499
|
+
"type": "number"
|
|
464
500
|
}
|
|
465
501
|
]
|
|
466
502
|
}
|
|
@@ -162,7 +162,7 @@ export interface CallbackError extends Error {
|
|
|
162
162
|
*/
|
|
163
163
|
code?: string;
|
|
164
164
|
}
|
|
165
|
-
export interface
|
|
165
|
+
export interface SetPlannedRouteOptions {
|
|
166
166
|
/**
|
|
167
167
|
* The name of the sound file to play.
|
|
168
168
|
* Must be a valid sound relative path in the app's public folder to work for both web and native platforms.
|
|
@@ -171,6 +171,24 @@ export interface PlaySoundOptions {
|
|
|
171
171
|
* @example "notification.mp3"
|
|
172
172
|
* */
|
|
173
173
|
soundFile: string;
|
|
174
|
+
/**
|
|
175
|
+
* The planned route as an array of longitude and latitude pairs.
|
|
176
|
+
* Each pair represents a point on the route.
|
|
177
|
+
* This is used to define a route that the user can follow.
|
|
178
|
+
* The route is used to play a sound when the user deviates from it.
|
|
179
|
+
* @since 7.0.11
|
|
180
|
+
* @example [[-74.0060, 40.7128], [-118.2437, 34.0522]]
|
|
181
|
+
*/
|
|
182
|
+
route: [number, number][];
|
|
183
|
+
/**
|
|
184
|
+
* The distance in meters that the user must deviate from the planned route to trigger the sound.
|
|
185
|
+
* This is used to determine how far off the route the user can be before the sound is played.
|
|
186
|
+
* If not specified, a default value of 50 meters is used.
|
|
187
|
+
* @since 7.0.11
|
|
188
|
+
* @default 50
|
|
189
|
+
* @example 50
|
|
190
|
+
*/
|
|
191
|
+
distance: number;
|
|
174
192
|
}
|
|
175
193
|
/**
|
|
176
194
|
* Main plugin interface for background geolocation functionality.
|
|
@@ -233,20 +251,18 @@ export interface BackgroundGeolocationPlugin {
|
|
|
233
251
|
*/
|
|
234
252
|
openSettings(): Promise<void>;
|
|
235
253
|
/**
|
|
236
|
-
* Plays a sound file.
|
|
237
|
-
* This should be used to play a sound
|
|
238
|
-
* The idea behind this is to allow the user to hear a sound when a new location is available or when going off track.
|
|
239
|
-
* If you simply need to play a sound, you can use `@capgo/native-audio` plugin instead.
|
|
240
|
-
* For Android, there's a need to start monitoring location updates first, otherwise the sound will not play.
|
|
254
|
+
* Plays a sound file when the user deviates from the planned route.
|
|
255
|
+
* This should be used to play a sound (in the background too, only for native).
|
|
241
256
|
*
|
|
242
|
-
* @param options The options for
|
|
243
|
-
* @returns A promise that resolves when the
|
|
257
|
+
* @param options The options for setting the planned route and sound file
|
|
258
|
+
* @returns A promise that resolves when the route is set successfully
|
|
244
259
|
*
|
|
245
|
-
* @since 7.0.
|
|
260
|
+
* @since 7.0.11
|
|
246
261
|
* @example
|
|
247
|
-
* await BackgroundGeolocation.
|
|
248
|
-
* soundFile: "notification.mp3"
|
|
262
|
+
* await BackgroundGeolocation.setPlannedRoute({
|
|
263
|
+
* soundFile: "notification.mp3",
|
|
264
|
+
* route: [[-74.0060, 40.7128], [-118.2437, 34.0522]]
|
|
249
265
|
* });
|
|
250
266
|
*/
|
|
251
|
-
|
|
267
|
+
setPlannedRoute(options: SetPlannedRouteOptions): Promise<void>;
|
|
252
268
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The options for configuring for location updates.\n *\n * @since 7.0.9\n */\nexport interface StartOptions {\n /**\n * If the \"backgroundMessage\" option is defined, the plugin will\n * provide location updates whether the app is in the background or the\n * foreground. If it is not defined, location updates are only\n * guaranteed in the foreground. This is true on both platforms.\n *\n * On Android, a notification must be shown to continue receiving\n * location updates in the background. This option specifies the text of\n * that notification.\n *\n * @since 7.0.9\n * @example \"Getting your location to provide better service\"\n */\n backgroundMessage?: string;\n /**\n * The title of the notification mentioned above.\n *\n * @since 7.0.9\n * @default \"Using your location\"\n * @example \"Location Service\"\n */\n backgroundTitle?: string;\n /**\n * Whether permissions should be requested from the user automatically,\n * if they are not already granted.\n *\n * @since 7.0.9\n * @default true\n * @example\n * // Auto-request permissions\n * requestPermissions: true\n *\n * // Don't auto-request, handle manually\n * requestPermissions: false\n */\n requestPermissions?: boolean;\n /**\n * If \"true\", stale locations may be delivered while the device\n * obtains a GPS fix. You are responsible for checking the \"time\"\n * property. If \"false\", locations are guaranteed to be up to date.\n *\n * @since 7.0.9\n * @default false\n * @example\n * // Allow stale locations for faster initial response\n * stale: true\n *\n * // Only fresh locations\n * stale: false\n */\n stale?: boolean;\n /**\n * The distance in meters that the device must move before a new location update is triggered.\n * This is used to filter out small movements and reduce the number of updates.\n *\n * @since 7.0.9\n * @default 0\n * @example\n * // Update every 10 meters\n * distanceFilter: 10\n *\n * // Update on any movement\n * distanceFilter: 0\n */\n distanceFilter?: number;\n}\n\n/**\n * Represents a geographical location with various attributes.\n * Contains all the standard location properties returned by GPS/network providers.\n *\n * @since 7.0.0\n */\nexport interface Location {\n /**\n * Latitude in degrees.\n * Range: -90.0 to +90.0\n *\n * @since 7.0.0\n * @example 40.7128\n */\n latitude: number;\n /**\n * Longitude in degrees.\n * Range: -180.0 to +180.0\n *\n * @since 7.0.0\n * @example -74.0060\n */\n longitude: number;\n /**\n * Radius of horizontal uncertainty in metres, with 68% confidence.\n * Lower values indicate more accurate location.\n *\n * @since 7.0.0\n * @example 5.0\n */\n accuracy: number;\n /**\n * Metres above sea level (or null if not available).\n *\n * @since 7.0.0\n * @example 10.5\n */\n altitude: number | null;\n /**\n * Vertical uncertainty in metres, with 68% confidence (or null if not available).\n *\n * @since 7.0.0\n * @example 3.0\n */\n altitudeAccuracy: number | null;\n /**\n * `true` if the location was simulated by software, rather than GPS.\n * Useful for detecting mock locations in development or testing.\n *\n * @since 7.0.0\n * @example false\n */\n simulated: boolean;\n /**\n * Deviation from true north in degrees (or null if not available).\n * Range: 0.0 to 360.0\n *\n * @since 7.0.0\n * @example 45.5\n */\n bearing: number | null;\n /**\n * Speed in metres per second (or null if not available).\n *\n * @since 7.0.0\n * @example 2.5\n */\n speed: number | null;\n /**\n * Time the location was produced, in milliseconds since the unix epoch.\n * Use this to check if a location is stale when using stale: true.\n *\n * @since 7.0.0\n * @example 1640995200000\n */\n time: number | null;\n}\n\n/**\n * Error object that may be passed to the location start callback.\n * Extends the standard Error with optional error codes.\n *\n * @since 7.0.0\n */\nexport interface CallbackError extends Error {\n /**\n * Optional error code for more specific error handling.\n *\n * @since 7.0.0\n * @example \"PERMISSION_DENIED\"\n */\n code?: string;\n}\n\nexport interface
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The options for configuring for location updates.\n *\n * @since 7.0.9\n */\nexport interface StartOptions {\n /**\n * If the \"backgroundMessage\" option is defined, the plugin will\n * provide location updates whether the app is in the background or the\n * foreground. If it is not defined, location updates are only\n * guaranteed in the foreground. This is true on both platforms.\n *\n * On Android, a notification must be shown to continue receiving\n * location updates in the background. This option specifies the text of\n * that notification.\n *\n * @since 7.0.9\n * @example \"Getting your location to provide better service\"\n */\n backgroundMessage?: string;\n /**\n * The title of the notification mentioned above.\n *\n * @since 7.0.9\n * @default \"Using your location\"\n * @example \"Location Service\"\n */\n backgroundTitle?: string;\n /**\n * Whether permissions should be requested from the user automatically,\n * if they are not already granted.\n *\n * @since 7.0.9\n * @default true\n * @example\n * // Auto-request permissions\n * requestPermissions: true\n *\n * // Don't auto-request, handle manually\n * requestPermissions: false\n */\n requestPermissions?: boolean;\n /**\n * If \"true\", stale locations may be delivered while the device\n * obtains a GPS fix. You are responsible for checking the \"time\"\n * property. If \"false\", locations are guaranteed to be up to date.\n *\n * @since 7.0.9\n * @default false\n * @example\n * // Allow stale locations for faster initial response\n * stale: true\n *\n * // Only fresh locations\n * stale: false\n */\n stale?: boolean;\n /**\n * The distance in meters that the device must move before a new location update is triggered.\n * This is used to filter out small movements and reduce the number of updates.\n *\n * @since 7.0.9\n * @default 0\n * @example\n * // Update every 10 meters\n * distanceFilter: 10\n *\n * // Update on any movement\n * distanceFilter: 0\n */\n distanceFilter?: number;\n}\n\n/**\n * Represents a geographical location with various attributes.\n * Contains all the standard location properties returned by GPS/network providers.\n *\n * @since 7.0.0\n */\nexport interface Location {\n /**\n * Latitude in degrees.\n * Range: -90.0 to +90.0\n *\n * @since 7.0.0\n * @example 40.7128\n */\n latitude: number;\n /**\n * Longitude in degrees.\n * Range: -180.0 to +180.0\n *\n * @since 7.0.0\n * @example -74.0060\n */\n longitude: number;\n /**\n * Radius of horizontal uncertainty in metres, with 68% confidence.\n * Lower values indicate more accurate location.\n *\n * @since 7.0.0\n * @example 5.0\n */\n accuracy: number;\n /**\n * Metres above sea level (or null if not available).\n *\n * @since 7.0.0\n * @example 10.5\n */\n altitude: number | null;\n /**\n * Vertical uncertainty in metres, with 68% confidence (or null if not available).\n *\n * @since 7.0.0\n * @example 3.0\n */\n altitudeAccuracy: number | null;\n /**\n * `true` if the location was simulated by software, rather than GPS.\n * Useful for detecting mock locations in development or testing.\n *\n * @since 7.0.0\n * @example false\n */\n simulated: boolean;\n /**\n * Deviation from true north in degrees (or null if not available).\n * Range: 0.0 to 360.0\n *\n * @since 7.0.0\n * @example 45.5\n */\n bearing: number | null;\n /**\n * Speed in metres per second (or null if not available).\n *\n * @since 7.0.0\n * @example 2.5\n */\n speed: number | null;\n /**\n * Time the location was produced, in milliseconds since the unix epoch.\n * Use this to check if a location is stale when using stale: true.\n *\n * @since 7.0.0\n * @example 1640995200000\n */\n time: number | null;\n}\n\n/**\n * Error object that may be passed to the location start callback.\n * Extends the standard Error with optional error codes.\n *\n * @since 7.0.0\n */\nexport interface CallbackError extends Error {\n /**\n * Optional error code for more specific error handling.\n *\n * @since 7.0.0\n * @example \"PERMISSION_DENIED\"\n */\n code?: string;\n}\n\nexport interface SetPlannedRouteOptions {\n /**\n * The name of the sound file to play.\n * Must be a valid sound relative path in the app's public folder to work for both web and native platforms.\n * There's no need to include the public folder in the path.\n * @since 7.0.10\n * @example \"notification.mp3\"\n * */\n soundFile: string;\n /**\n * The planned route as an array of longitude and latitude pairs.\n * Each pair represents a point on the route.\n * This is used to define a route that the user can follow.\n * The route is used to play a sound when the user deviates from it.\n * @since 7.0.11\n * @example [[-74.0060, 40.7128], [-118.2437, 34.0522]]\n */\n route: [number, number][];\n\n /**\n * The distance in meters that the user must deviate from the planned route to trigger the sound.\n * This is used to determine how far off the route the user can be before the sound is played.\n * If not specified, a default value of 50 meters is used.\n * @since 7.0.11\n * @default 50\n * @example 50\n */\n distance: number;\n}\n\n/**\n * Main plugin interface for background geolocation functionality.\n * Provides methods to manage location updates and access device settings.\n *\n * @since 7.0.0\n */\nexport interface BackgroundGeolocationPlugin {\n /**\n * To start listening for changes in the device's location, call this method.\n * A Promise is returned to indicate that it finished the call. The callback will be called every time a new location\n * is available, or if there was an error when calling this method. Don't rely on promise rejection for this.\n *\n * @param options The configuration options\n * @param callback The callback function invoked when a new location is available or an error occurs\n * @returns A promise that resolves when the method is successfully called\n *\n * @since 7.0.9\n * @example\n * await BackgroundGeolocation.start(\n * {\n * backgroundMessage: \"App is using your location in the background\",\n * backgroundTitle: \"Location Service\",\n * requestPermissions: true,\n * stale: false,\n * distanceFilter: 10\n * },\n * (location, error) => {\n * if (error) {\n * console.error('Location error:', error);\n * return;\n * }\n * if (location) {\n * console.log('New location:', location.latitude, location.longitude);\n * }\n * }\n * );\n */\n start(\n options: StartOptions,\n callback: (position?: Location, error?: CallbackError) => void,\n ): Promise<void>;\n\n /**\n * Stops location updates.\n *\n * @returns A promise that resolves when the plugin stops successfully removed\n *\n * @since 7.0.9\n * @example\n * await BackgroundGeolocation.stop();\n */\n stop(): Promise<void>;\n\n /**\n * Opens the device's location settings page.\n * Useful for directing users to enable location services or adjust permissions.\n *\n * @returns A promise that resolves when the settings page is opened\n *\n * @since 7.0.0\n * @example\n * // Direct user to location settings\n * await BackgroundGeolocation.openSettings();\n */\n openSettings(): Promise<void>;\n\n /**\n * Plays a sound file when the user deviates from the planned route.\n * This should be used to play a sound (in the background too, only for native).\n *\n * @param options The options for setting the planned route and sound file\n * @returns A promise that resolves when the route is set successfully\n *\n * @since 7.0.11\n * @example\n * await BackgroundGeolocation.setPlannedRoute({\n * soundFile: \"notification.mp3\",\n * route: [[-74.0060, 40.7128], [-118.2437, 34.0522]]\n * });\n */\n setPlannedRoute(options: SetPlannedRouteOptions): Promise<void>;\n}\n"]}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { WebPlugin } from "@capacitor/core";
|
|
2
|
-
import type { BackgroundGeolocationPlugin, StartOptions, Location, CallbackError,
|
|
2
|
+
import type { BackgroundGeolocationPlugin, StartOptions, Location, CallbackError, SetPlannedRouteOptions } from "./definitions";
|
|
3
3
|
export declare class BackgroundGeolocationWeb extends WebPlugin implements BackgroundGeolocationPlugin {
|
|
4
|
+
private static readonly EARTH_RADIUS_M;
|
|
4
5
|
private watchId;
|
|
6
|
+
private plannedRoute;
|
|
7
|
+
private audio;
|
|
8
|
+
private isOffRoute;
|
|
9
|
+
private distanceThreshold;
|
|
5
10
|
start(options: StartOptions, callback: (position?: Location, error?: CallbackError) => void): Promise<void>;
|
|
6
11
|
stop(): Promise<void>;
|
|
7
12
|
openSettings(): Promise<void>;
|
|
8
|
-
|
|
13
|
+
setPlannedRoute(options: SetPlannedRouteOptions): Promise<void>;
|
|
14
|
+
private toRadians;
|
|
15
|
+
private haversine;
|
|
16
|
+
private distancePointToLineSegment;
|
|
17
|
+
private distancePointToRoute;
|
|
9
18
|
}
|