@capgo/background-geolocation 7.0.7 → 7.0.9
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/CapgoBackgroundGeolocation.podspec +15 -12
- package/README.md +2 -2
- package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocation.java +21 -103
- package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocationService.java +121 -59
- package/dist/docs.json +16 -26
- package/dist/esm/definitions.d.ts +7 -11
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +4 -7
- package/dist/esm/web.js +15 -16
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +15 -16
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +15 -16
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/Plugin.m +2 -2
- package/ios/Plugin/Plugin.swift +88 -93
- package/package.json +1 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
require 'json'
|
|
1
2
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapgoBackgroundGeolocation'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '14.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
end
|
package/README.md
CHANGED
|
@@ -208,8 +208,8 @@ Configration specific to Android can be made in `strings.xml`:
|
|
|
208
208
|
|
|
209
209
|
<docgen-index>
|
|
210
210
|
|
|
211
|
-
* [`
|
|
212
|
-
* [`
|
|
211
|
+
* [`start(...)`](#start)
|
|
212
|
+
* [`stop()`](#stop)
|
|
213
213
|
* [`openSettings()`](#opensettings)
|
|
214
214
|
* [Interfaces](#interfaces)
|
|
215
215
|
|
package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocation.java
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
package com.capgo.capacitor_background_geolocation;
|
|
2
2
|
|
|
3
3
|
import android.Manifest;
|
|
4
|
-
import android.app.Notification;
|
|
5
4
|
import android.app.NotificationChannel;
|
|
6
5
|
import android.app.NotificationManager;
|
|
7
|
-
import android.app.PendingIntent;
|
|
8
6
|
import android.content.BroadcastReceiver;
|
|
9
7
|
import android.content.ComponentName;
|
|
10
8
|
import android.content.Context;
|
|
11
9
|
import android.content.Intent;
|
|
12
10
|
import android.content.IntentFilter;
|
|
13
11
|
import android.content.ServiceConnection;
|
|
14
|
-
import android.graphics.Color;
|
|
15
12
|
import android.location.Location;
|
|
16
13
|
import android.location.LocationManager;
|
|
17
14
|
import android.net.Uri;
|
|
@@ -68,7 +65,7 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
68
65
|
}
|
|
69
66
|
|
|
70
67
|
@PluginMethod(returnType = PluginMethod.RETURN_CALLBACK)
|
|
71
|
-
public void
|
|
68
|
+
public void start(final PluginCall call) {
|
|
72
69
|
if (
|
|
73
70
|
getPermissionState("location") != PermissionState.GRANTED &&
|
|
74
71
|
!call.getBoolean("requestPermissions", true)
|
|
@@ -77,6 +74,11 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
77
74
|
return;
|
|
78
75
|
}
|
|
79
76
|
|
|
77
|
+
if (serviceConnectionFuture != null) {
|
|
78
|
+
call.reject("Service already started", "ALREADY_STARTED");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
80
82
|
if (
|
|
81
83
|
getPermissionState("location") != PermissionState.GRANTED &&
|
|
82
84
|
call.getBoolean("requestPermissions", true)
|
|
@@ -84,7 +86,7 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
84
86
|
call.setKeepAlive(true);
|
|
85
87
|
requestLocationPermissions(call)
|
|
86
88
|
.thenRun(() -> {
|
|
87
|
-
|
|
89
|
+
proceedWithStart(call);
|
|
88
90
|
})
|
|
89
91
|
.exceptionally(throwable -> {
|
|
90
92
|
call.reject("User denied location permission", "NOT_AUTHORIZED");
|
|
@@ -101,17 +103,18 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
101
103
|
|
|
102
104
|
// Everything is OK, continuing to adding a watcher
|
|
103
105
|
call.setKeepAlive(true);
|
|
104
|
-
|
|
106
|
+
proceedWithStart(call);
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
private void
|
|
109
|
+
private void proceedWithStart(PluginCall call) {
|
|
108
110
|
if (call.getBoolean("stale", false)) {
|
|
109
111
|
fetchLastLocation(call);
|
|
110
112
|
}
|
|
111
113
|
getServiceConnection().thenAccept(serviceBinder -> {
|
|
112
|
-
serviceBinder.
|
|
114
|
+
serviceBinder.start(
|
|
113
115
|
call.getCallbackId(),
|
|
114
|
-
|
|
116
|
+
call.getString("backgroundTitle", "Using your location"),
|
|
117
|
+
call.getString("backgroundMessage", ""),
|
|
115
118
|
call.getFloat("distanceFilter", 0f)
|
|
116
119
|
);
|
|
117
120
|
});
|
|
@@ -126,67 +129,6 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
126
129
|
return locationPermissionFuture;
|
|
127
130
|
}
|
|
128
131
|
|
|
129
|
-
private Notification createBackgroundNotification(PluginCall call) {
|
|
130
|
-
String backgroundMessage = call.getString("backgroundMessage", "");
|
|
131
|
-
|
|
132
|
-
Notification.Builder builder = new Notification.Builder(getContext())
|
|
133
|
-
.setContentTitle(call.getString("backgroundTitle", "Using your location"))
|
|
134
|
-
.setContentText(backgroundMessage)
|
|
135
|
-
.setOngoing(true)
|
|
136
|
-
.setPriority(Notification.PRIORITY_HIGH)
|
|
137
|
-
.setWhen(System.currentTimeMillis());
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
String name = getAppString(
|
|
141
|
-
"capacitor_background_geolocation_notification_icon",
|
|
142
|
-
"mipmap/ic_launcher"
|
|
143
|
-
);
|
|
144
|
-
String[] parts = name.split("/");
|
|
145
|
-
// It is actually necessary to set a valid icon for the notification to behave
|
|
146
|
-
// correctly when tapped. If there is no icon specified, tapping it will open the
|
|
147
|
-
// app's settings, rather than bringing the application to the foreground.
|
|
148
|
-
builder.setSmallIcon(getAppResourceIdentifier(parts[1], parts[0]));
|
|
149
|
-
} catch (Exception e) {
|
|
150
|
-
Logger.error("Could not set notification icon", e);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
String color = getAppString(
|
|
155
|
-
"capacitor_background_geolocation_notification_color",
|
|
156
|
-
null
|
|
157
|
-
);
|
|
158
|
-
if (color != null) {
|
|
159
|
-
builder.setColor(Color.parseColor(color));
|
|
160
|
-
}
|
|
161
|
-
} catch (Exception e) {
|
|
162
|
-
Logger.error("Could not set notification color", e);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
Intent launchIntent = getContext()
|
|
166
|
-
.getPackageManager()
|
|
167
|
-
.getLaunchIntentForPackage(getContext().getPackageName());
|
|
168
|
-
if (launchIntent != null) {
|
|
169
|
-
launchIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
|
170
|
-
builder.setContentIntent(
|
|
171
|
-
PendingIntent.getActivity(
|
|
172
|
-
getContext(),
|
|
173
|
-
0,
|
|
174
|
-
launchIntent,
|
|
175
|
-
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE
|
|
176
|
-
)
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Set the Channel ID for Android O.
|
|
181
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
182
|
-
builder.setChannelId(
|
|
183
|
-
BackgroundGeolocationService.class.getPackage().getName()
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return builder.build();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
132
|
@PermissionCallback
|
|
191
133
|
private void locationPermissionsCallback(PluginCall call) {
|
|
192
134
|
if (locationPermissionFuture == null) {
|
|
@@ -217,21 +159,19 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
217
159
|
}
|
|
218
160
|
|
|
219
161
|
@PluginMethod
|
|
220
|
-
public void
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
call.reject("Missing id.");
|
|
224
|
-
return;
|
|
162
|
+
public void stop(PluginCall call) {
|
|
163
|
+
if (serviceConnectionFuture == null) {
|
|
164
|
+
call.resolve();
|
|
225
165
|
}
|
|
226
|
-
|
|
227
166
|
getServiceConnection()
|
|
228
167
|
.thenAccept(service -> {
|
|
229
|
-
service.
|
|
168
|
+
var callbackId = service.stop();
|
|
230
169
|
PluginCall savedCall = getBridge().getSavedCall(callbackId);
|
|
231
170
|
if (savedCall != null) {
|
|
232
171
|
savedCall.release(getBridge());
|
|
233
172
|
}
|
|
234
173
|
call.resolve();
|
|
174
|
+
serviceConnectionFuture = null;
|
|
235
175
|
})
|
|
236
176
|
.exceptionally(throwable -> {
|
|
237
177
|
call.reject("Service connection failed: " + throwable.getMessage());
|
|
@@ -321,19 +261,6 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
321
261
|
}
|
|
322
262
|
}
|
|
323
263
|
|
|
324
|
-
// Gets the identifier of the app's resource by name, returning 0 if not found.
|
|
325
|
-
private int getAppResourceIdentifier(String name, String defType) {
|
|
326
|
-
return getContext()
|
|
327
|
-
.getResources()
|
|
328
|
-
.getIdentifier(name, defType, getContext().getPackageName());
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Gets a string from the app's strings.xml file, resorting to a fallback if it is not defined.
|
|
332
|
-
private String getAppString(String name, String fallback) {
|
|
333
|
-
int id = getAppResourceIdentifier(name, "string");
|
|
334
|
-
return id == 0 ? fallback : getContext().getString(id);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
264
|
@Override
|
|
338
265
|
public void load() {
|
|
339
266
|
super.load();
|
|
@@ -346,9 +273,10 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
346
273
|
);
|
|
347
274
|
NotificationChannel channel = new NotificationChannel(
|
|
348
275
|
BackgroundGeolocationService.class.getPackage().getName(),
|
|
349
|
-
getAppString(
|
|
276
|
+
BackgroundGeolocationService.getAppString(
|
|
350
277
|
"capacitor_background_geolocation_notification_channel_name",
|
|
351
|
-
"Background Tracking"
|
|
278
|
+
"Background Tracking",
|
|
279
|
+
getContext()
|
|
352
280
|
),
|
|
353
281
|
NotificationManager.IMPORTANCE_DEFAULT
|
|
354
282
|
);
|
|
@@ -407,21 +335,11 @@ public class BackgroundGeolocation extends Plugin {
|
|
|
407
335
|
return serviceConnectionFuture;
|
|
408
336
|
}
|
|
409
337
|
|
|
410
|
-
@Override
|
|
411
|
-
protected void handleOnResume() {
|
|
412
|
-
super.handleOnResume();
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
@Override
|
|
416
|
-
protected void handleOnPause() {
|
|
417
|
-
super.handleOnPause();
|
|
418
|
-
}
|
|
419
|
-
|
|
420
338
|
@Override
|
|
421
339
|
protected void handleOnDestroy() {
|
|
422
340
|
if (serviceConnectionFuture != null) {
|
|
423
341
|
serviceConnectionFuture.thenAccept(
|
|
424
|
-
BackgroundGeolocationService.LocalBinder::
|
|
342
|
+
BackgroundGeolocationService.LocalBinder::stop
|
|
425
343
|
);
|
|
426
344
|
}
|
|
427
345
|
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
package com.capgo.capacitor_background_geolocation;
|
|
2
2
|
|
|
3
3
|
import android.app.Notification;
|
|
4
|
+
import android.app.PendingIntent;
|
|
4
5
|
import android.app.Service;
|
|
5
6
|
import android.content.Context;
|
|
6
7
|
import android.content.Intent;
|
|
8
|
+
import android.graphics.Color;
|
|
7
9
|
import android.location.LocationListener;
|
|
8
10
|
import android.location.LocationManager;
|
|
9
11
|
import android.os.Binder;
|
|
12
|
+
import android.os.Build;
|
|
10
13
|
import android.os.IBinder;
|
|
11
14
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
12
15
|
import com.getcapacitor.Logger;
|
|
13
|
-
import java.util.HashSet;
|
|
14
16
|
|
|
15
17
|
// A bound and started service that is promoted to a foreground service
|
|
16
18
|
// (showing a persistent notification) when the first background watcher is
|
|
@@ -24,16 +26,10 @@ public class BackgroundGeolocationService extends Service {
|
|
|
24
26
|
// Must be unique for this application.
|
|
25
27
|
private static final int NOTIFICATION_ID = 28351;
|
|
26
28
|
|
|
27
|
-
private
|
|
29
|
+
private String callbackId;
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
public float distanceFilter;
|
|
32
|
-
public LocationListener locationCallback;
|
|
33
|
-
public Notification backgroundNotification;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private HashSet<Watcher> watchers = new HashSet<>();
|
|
31
|
+
private LocationManager client;
|
|
32
|
+
private LocationListener locationCallback;
|
|
37
33
|
|
|
38
34
|
@Override
|
|
39
35
|
public IBinder onBind(Intent intent) {
|
|
@@ -46,59 +42,44 @@ public class BackgroundGeolocationService extends Service {
|
|
|
46
42
|
// service is terminated immediately.
|
|
47
43
|
@Override
|
|
48
44
|
public boolean onUnbind(Intent intent) {
|
|
49
|
-
|
|
50
|
-
watcher.client.removeUpdates(watcher.locationCallback);
|
|
51
|
-
}
|
|
52
|
-
watchers = new HashSet<>();
|
|
45
|
+
client.removeUpdates(locationCallback);
|
|
53
46
|
stopSelf();
|
|
54
47
|
return false;
|
|
55
48
|
}
|
|
56
49
|
|
|
57
|
-
private void requestLocationUpdates(Watcher watcher) {
|
|
58
|
-
try {
|
|
59
|
-
watcher.client.requestLocationUpdates(
|
|
60
|
-
LocationManager.GPS_PROVIDER,
|
|
61
|
-
1000,
|
|
62
|
-
watcher.distanceFilter,
|
|
63
|
-
watcher.locationCallback
|
|
64
|
-
);
|
|
65
|
-
} catch (SecurityException ignore) {
|
|
66
|
-
// According to Android Studio, this method can throw a Security Exception if
|
|
67
|
-
// permissions are not yet granted. Rather than check the permissions, which is fiddly,
|
|
68
|
-
// we simply ignore the exception.
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
50
|
// Handles requests from the activity.
|
|
73
51
|
public class LocalBinder extends Binder {
|
|
74
52
|
|
|
75
|
-
void
|
|
53
|
+
void start(
|
|
76
54
|
final String id,
|
|
77
|
-
|
|
55
|
+
final String notificationTitle,
|
|
56
|
+
final String notificationMessage,
|
|
78
57
|
float distanceFilter
|
|
79
58
|
) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
);
|
|
59
|
+
client = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
|
60
|
+
callbackId = id;
|
|
83
61
|
|
|
84
|
-
|
|
62
|
+
locationCallback = location -> {
|
|
85
63
|
Intent intent = new Intent(ACTION_BROADCAST);
|
|
86
64
|
intent.putExtra("location", location);
|
|
87
|
-
intent.putExtra("id",
|
|
65
|
+
intent.putExtra("id", callbackId);
|
|
88
66
|
LocalBroadcastManager.getInstance(
|
|
89
67
|
getApplicationContext()
|
|
90
68
|
).sendBroadcast(intent);
|
|
91
69
|
};
|
|
92
70
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
71
|
+
try {
|
|
72
|
+
client.requestLocationUpdates(
|
|
73
|
+
LocationManager.GPS_PROVIDER,
|
|
74
|
+
1000,
|
|
75
|
+
distanceFilter,
|
|
76
|
+
locationCallback
|
|
77
|
+
);
|
|
78
|
+
} catch (SecurityException ignore) {
|
|
79
|
+
// According to Android Studio, this method can throw a Security Exception if
|
|
80
|
+
// permissions are not yet granted. Rather than check the permissions, which is fiddly,
|
|
81
|
+
// we simply ignore the exception.
|
|
82
|
+
}
|
|
102
83
|
|
|
103
84
|
// Promote the service to the foreground if necessary.
|
|
104
85
|
// Ideally we would only call 'startForeground' if the service is not already
|
|
@@ -110,28 +91,109 @@ public class BackgroundGeolocationService extends Service {
|
|
|
110
91
|
// This method has been known to fail due to weird
|
|
111
92
|
// permission bugs, so we prevent any exceptions from
|
|
112
93
|
// crashing the app. See issue #86.
|
|
113
|
-
startForeground(
|
|
94
|
+
startForeground(
|
|
95
|
+
NOTIFICATION_ID,
|
|
96
|
+
createBackgroundNotification(notificationTitle, notificationMessage)
|
|
97
|
+
);
|
|
114
98
|
} catch (Exception exception) {
|
|
115
99
|
Logger.error("Failed to foreground service", exception);
|
|
116
100
|
}
|
|
117
101
|
}
|
|
118
102
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
103
|
+
String stop() {
|
|
104
|
+
client.removeUpdates(locationCallback);
|
|
105
|
+
stopForeground(true);
|
|
106
|
+
stopSelf();
|
|
107
|
+
return callbackId;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private Notification createBackgroundNotification(
|
|
112
|
+
String backgroundTitle,
|
|
113
|
+
String backgroundMessage
|
|
114
|
+
) {
|
|
115
|
+
Notification.Builder builder = new Notification.Builder(
|
|
116
|
+
getApplicationContext()
|
|
117
|
+
)
|
|
118
|
+
.setContentTitle(backgroundTitle)
|
|
119
|
+
.setContentText(backgroundMessage)
|
|
120
|
+
.setOngoing(true)
|
|
121
|
+
.setPriority(Notification.PRIORITY_HIGH)
|
|
122
|
+
.setWhen(System.currentTimeMillis());
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
String name = getAppString(
|
|
126
|
+
"capacitor_background_geolocation_notification_icon",
|
|
127
|
+
"mipmap/ic_launcher",
|
|
128
|
+
getApplicationContext()
|
|
129
|
+
);
|
|
130
|
+
String[] parts = name.split("/");
|
|
131
|
+
// It is actually necessary to set a valid icon for the notification to behave
|
|
132
|
+
// correctly when tapped. If there is no icon specified, tapping it will open the
|
|
133
|
+
// app's settings, rather than bringing the application to the foreground.
|
|
134
|
+
builder.setSmallIcon(
|
|
135
|
+
getAppResourceIdentifier(parts[1], parts[0], getApplicationContext())
|
|
136
|
+
);
|
|
137
|
+
} catch (Exception e) {
|
|
138
|
+
Logger.error("Could not set notification icon", e);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
String color = getAppString(
|
|
143
|
+
"capacitor_background_geolocation_notification_color",
|
|
144
|
+
null,
|
|
145
|
+
getApplicationContext()
|
|
146
|
+
);
|
|
147
|
+
if (color != null) {
|
|
148
|
+
builder.setColor(Color.parseColor(color));
|
|
129
149
|
}
|
|
150
|
+
} catch (Exception e) {
|
|
151
|
+
Logger.error("Could not set notification color", e);
|
|
130
152
|
}
|
|
131
153
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
154
|
+
Intent launchIntent = getApplicationContext()
|
|
155
|
+
.getPackageManager()
|
|
156
|
+
.getLaunchIntentForPackage(getApplicationContext().getPackageName());
|
|
157
|
+
if (launchIntent != null) {
|
|
158
|
+
launchIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
|
159
|
+
builder.setContentIntent(
|
|
160
|
+
PendingIntent.getActivity(
|
|
161
|
+
getApplicationContext(),
|
|
162
|
+
0,
|
|
163
|
+
launchIntent,
|
|
164
|
+
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE
|
|
165
|
+
)
|
|
166
|
+
);
|
|
135
167
|
}
|
|
168
|
+
|
|
169
|
+
// Set the Channel ID for Android O.
|
|
170
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
171
|
+
builder.setChannelId(
|
|
172
|
+
BackgroundGeolocationService.class.getPackage().getName()
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return builder.build();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Gets the identifier of the app's resource by name, returning 0 if not found.
|
|
180
|
+
private static int getAppResourceIdentifier(
|
|
181
|
+
String name,
|
|
182
|
+
String defType,
|
|
183
|
+
Context context
|
|
184
|
+
) {
|
|
185
|
+
return context
|
|
186
|
+
.getResources()
|
|
187
|
+
.getIdentifier(name, defType, context.getPackageName());
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Gets a string from the app's strings.xml file, resorting to a fallback if it is not defined.
|
|
191
|
+
public static String getAppString(
|
|
192
|
+
String name,
|
|
193
|
+
String fallback,
|
|
194
|
+
Context context
|
|
195
|
+
) {
|
|
196
|
+
int id = getAppResourceIdentifier(name, "string", context);
|
|
197
|
+
return id == 0 ? fallback : context.getString(id);
|
|
136
198
|
}
|
|
137
199
|
}
|
package/dist/docs.json
CHANGED
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
],
|
|
12
12
|
"methods": [
|
|
13
13
|
{
|
|
14
|
-
"name": "
|
|
15
|
-
"signature": "(options:
|
|
14
|
+
"name": "start",
|
|
15
|
+
"signature": "(options: StartOptions, callback: (position?: Location | undefined, error?: CallbackError | undefined) => void) => Promise<void>",
|
|
16
16
|
"parameters": [
|
|
17
17
|
{
|
|
18
18
|
"name": "options",
|
|
19
19
|
"docs": "The watcher configuration options",
|
|
20
|
-
"type": "
|
|
20
|
+
"type": "StartOptions"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"name": "callback",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"type": "(position?: Location | undefined, error?: CallbackError | undefined) => void"
|
|
26
26
|
}
|
|
27
27
|
],
|
|
28
|
-
"returns": "Promise<
|
|
28
|
+
"returns": "Promise<void>",
|
|
29
29
|
"tags": [
|
|
30
30
|
{
|
|
31
31
|
"name": "param",
|
|
@@ -45,33 +45,23 @@
|
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "example",
|
|
48
|
-
"text": "
|
|
48
|
+
"text": "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);"
|
|
49
49
|
}
|
|
50
50
|
],
|
|
51
51
|
"docs": "Adds a watcher for location updates.\nThe watcher will be invoked with the latest location whenever it is available.\nIf an error occurs, the callback will be invoked with the error.",
|
|
52
52
|
"complexTypes": [
|
|
53
|
-
"
|
|
53
|
+
"StartOptions",
|
|
54
54
|
"Location",
|
|
55
55
|
"CallbackError"
|
|
56
56
|
],
|
|
57
|
-
"slug": "
|
|
57
|
+
"slug": "start"
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
"name": "
|
|
61
|
-
"signature": "(
|
|
62
|
-
"parameters": [
|
|
63
|
-
{
|
|
64
|
-
"name": "options",
|
|
65
|
-
"docs": "Object containing the watcher ID to remove",
|
|
66
|
-
"type": "{ id: string; }"
|
|
67
|
-
}
|
|
68
|
-
],
|
|
60
|
+
"name": "stop",
|
|
61
|
+
"signature": "() => Promise<void>",
|
|
62
|
+
"parameters": [],
|
|
69
63
|
"returns": "Promise<void>",
|
|
70
64
|
"tags": [
|
|
71
|
-
{
|
|
72
|
-
"name": "param",
|
|
73
|
-
"text": "options Object containing the watcher ID to remove"
|
|
74
|
-
},
|
|
75
65
|
{
|
|
76
66
|
"name": "returns",
|
|
77
67
|
"text": "A promise that resolves when the watcher is successfully removed"
|
|
@@ -82,12 +72,12 @@
|
|
|
82
72
|
},
|
|
83
73
|
{
|
|
84
74
|
"name": "example",
|
|
85
|
-
"text": "await BackgroundGeolocation.
|
|
75
|
+
"text": "await BackgroundGeolocation.stop();"
|
|
86
76
|
}
|
|
87
77
|
],
|
|
88
|
-
"docs": "
|
|
78
|
+
"docs": "Stops location updates.",
|
|
89
79
|
"complexTypes": [],
|
|
90
|
-
"slug": "
|
|
80
|
+
"slug": "stop"
|
|
91
81
|
},
|
|
92
82
|
{
|
|
93
83
|
"name": "openSettings",
|
|
@@ -117,9 +107,9 @@
|
|
|
117
107
|
},
|
|
118
108
|
"interfaces": [
|
|
119
109
|
{
|
|
120
|
-
"name": "
|
|
121
|
-
"slug": "
|
|
122
|
-
"docs": "The options for configuring
|
|
110
|
+
"name": "StartOptions",
|
|
111
|
+
"slug": "startoptions",
|
|
112
|
+
"docs": "The options for configuring for location updates.",
|
|
123
113
|
"tags": [
|
|
124
114
|
{
|
|
125
115
|
"text": "1.0.0",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The options for configuring
|
|
2
|
+
* The options for configuring for location updates.
|
|
3
3
|
*
|
|
4
4
|
* @since 1.0.0
|
|
5
5
|
*/
|
|
6
|
-
export interface
|
|
6
|
+
export interface StartOptions {
|
|
7
7
|
/**
|
|
8
8
|
* If the "backgroundMessage" option is defined, the watcher will
|
|
9
9
|
* provide location updates whether the app is in the background or the
|
|
@@ -180,7 +180,7 @@ export interface BackgroundGeolocationPlugin {
|
|
|
180
180
|
*
|
|
181
181
|
* @since 1.0.0
|
|
182
182
|
* @example
|
|
183
|
-
*
|
|
183
|
+
* await BackgroundGeolocation.start(
|
|
184
184
|
* {
|
|
185
185
|
* backgroundMessage: "App is using your location in the background",
|
|
186
186
|
* backgroundTitle: "Location Service",
|
|
@@ -199,21 +199,17 @@ export interface BackgroundGeolocationPlugin {
|
|
|
199
199
|
* }
|
|
200
200
|
* );
|
|
201
201
|
*/
|
|
202
|
-
|
|
202
|
+
start(options: StartOptions, callback: (position?: Location, error?: CallbackError) => void): Promise<void>;
|
|
203
203
|
/**
|
|
204
|
-
*
|
|
205
|
-
* Stops location updates for the specified watcher.
|
|
204
|
+
* Stops location updates.
|
|
206
205
|
*
|
|
207
|
-
* @param options Object containing the watcher ID to remove
|
|
208
206
|
* @returns A promise that resolves when the watcher is successfully removed
|
|
209
207
|
*
|
|
210
208
|
* @since 1.0.0
|
|
211
209
|
* @example
|
|
212
|
-
* await BackgroundGeolocation.
|
|
210
|
+
* await BackgroundGeolocation.stop();
|
|
213
211
|
*/
|
|
214
|
-
|
|
215
|
-
id: string;
|
|
216
|
-
}): Promise<void>;
|
|
212
|
+
stop(): Promise<void>;
|
|
217
213
|
/**
|
|
218
214
|
* Opens the device's location settings page.
|
|
219
215
|
* Useful for directing users to enable location services or adjust permissions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The options for configuring
|
|
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 1.0.0\n */\nexport interface StartOptions {\n /**\n * If the \"backgroundMessage\" option is defined, the watcher 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 1.0.0\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 1.0.0\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 1.0.0\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 1.0.0\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 1.0.0\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 1.0.0\n */\nexport interface Location {\n /**\n * Latitude in degrees.\n * Range: -90.0 to +90.0\n *\n * @since 1.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 1.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 1.0.0\n * @example 5.0\n */\n accuracy: number;\n /**\n * Metres above sea level (or null if not available).\n *\n * @since 1.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 1.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 1.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 1.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 1.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 1.0.0\n * @example 1640995200000\n */\n time: number | null;\n}\n\n/**\n * Error object that may be passed to the location watcher callback.\n * Extends the standard Error with optional error codes.\n *\n * @since 1.0.0\n */\nexport interface CallbackError extends Error {\n /**\n * Optional error code for more specific error handling.\n *\n * @since 1.0.0\n * @example \"PERMISSION_DENIED\"\n */\n code?: string;\n}\n\n/**\n * Main plugin interface for background geolocation functionality.\n * Provides methods to manage location watchers and access device settings.\n *\n * @since 1.0.0\n */\nexport interface BackgroundGeolocationPlugin {\n /**\n * Adds a watcher for location updates.\n * The watcher will be invoked with the latest location whenever it is available.\n * If an error occurs, the callback will be invoked with the error.\n *\n * @param options The watcher 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 to a unique identifier for the watcher ID\n *\n * @since 1.0.0\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 watcher is successfully removed\n *\n * @since 1.0.0\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 1.0.0\n * @example\n * // Direct user to location settings\n * await BackgroundGeolocation.openSettings();\n */\n openSettings(): Promise<void>;\n}\n"]}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { WebPlugin } from "@capacitor/core";
|
|
2
|
-
import type { BackgroundGeolocationPlugin,
|
|
2
|
+
import type { BackgroundGeolocationPlugin, StartOptions, Location, CallbackError } from "./definitions";
|
|
3
3
|
export declare class BackgroundGeolocationWeb extends WebPlugin implements BackgroundGeolocationPlugin {
|
|
4
|
-
private
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
removeWatcher(options: {
|
|
8
|
-
id: string;
|
|
9
|
-
}): Promise<void>;
|
|
4
|
+
private watchId;
|
|
5
|
+
start(options: StartOptions, callback: (position?: Location, error?: CallbackError) => void): Promise<void>;
|
|
6
|
+
stop(): Promise<void>;
|
|
10
7
|
openSettings(): Promise<void>;
|
|
11
8
|
}
|
package/dist/esm/web.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { WebPlugin } from "@capacitor/core";
|
|
2
2
|
export class BackgroundGeolocationWeb extends WebPlugin {
|
|
3
|
-
|
|
4
|
-
super(...arguments);
|
|
5
|
-
this.watchers = new Map();
|
|
6
|
-
this.watcherCounter = 0;
|
|
7
|
-
}
|
|
8
|
-
async addWatcher(options, callback) {
|
|
9
|
-
const watcherId = `watcher_${++this.watcherCounter}`;
|
|
3
|
+
async start(options, callback) {
|
|
10
4
|
if (!navigator.geolocation) {
|
|
11
5
|
callback(undefined, {
|
|
12
6
|
name: "GeolocationError",
|
|
13
7
|
message: "Geolocation is not supported by this browser",
|
|
14
8
|
code: "NOT_SUPPORTED",
|
|
15
9
|
});
|
|
16
|
-
return
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (this.watchId) {
|
|
13
|
+
callback(undefined, {
|
|
14
|
+
name: "GeolocationError",
|
|
15
|
+
message: "Geolocation already started",
|
|
16
|
+
code: "ALREADY_STARTED",
|
|
17
|
+
});
|
|
18
|
+
return;
|
|
17
19
|
}
|
|
18
|
-
|
|
20
|
+
this.watchId = navigator.geolocation.watchPosition((position) => {
|
|
19
21
|
const location = {
|
|
20
22
|
latitude: position.coords.latitude,
|
|
21
23
|
longitude: position.coords.longitude,
|
|
@@ -40,14 +42,11 @@ export class BackgroundGeolocationWeb extends WebPlugin {
|
|
|
40
42
|
timeout: 10000,
|
|
41
43
|
maximumAge: options.stale ? 300000 : 0,
|
|
42
44
|
});
|
|
43
|
-
this.watchers.set(watcherId, { watchId, callback });
|
|
44
|
-
return watcherId;
|
|
45
45
|
}
|
|
46
|
-
async
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.watchers.delete(options.id);
|
|
46
|
+
async stop() {
|
|
47
|
+
if (this.watchId) {
|
|
48
|
+
navigator.geolocation.clearWatch(this.watchId);
|
|
49
|
+
delete this.watchId;
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
52
|
async openSettings() {
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAS5C,MAAM,OAAO,wBACX,SAAQ,SAAS;
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAS5C,MAAM,OAAO,wBACX,SAAQ,SAAS;IAKjB,KAAK,CAAC,KAAK,CACT,OAAqB,EACrB,QAA8D;QAE9D,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;YAC3B,QAAQ,CAAC,SAAS,EAAE;gBAClB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,8CAA8C;gBACvD,IAAI,EAAE,eAAe;aACtB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,QAAQ,CAAC,SAAS,EAAE;gBAClB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,6BAA6B;gBACtC,IAAI,EAAE,iBAAiB;aACxB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,aAAa,CAChD,CAAC,QAAQ,EAAE,EAAE;YACX,MAAM,QAAQ,GAAa;gBACzB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;gBACpC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB;gBAClD,SAAS,EAAE,KAAK;gBAChB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;gBAChC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;gBAC5B,IAAI,EAAE,QAAQ,CAAC,SAAS;aACzB,CAAC;YACF,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACR,MAAM,aAAa,GAAkB;gBACnC,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;aAC5B,CAAC;YACF,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACrC,CAAC,EACD;YACE,kBAAkB,EAAE,IAAI;YACxB,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SACvC,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC9E,CAAC;CACF","sourcesContent":["import { WebPlugin } from \"@capacitor/core\";\n\nimport type {\n BackgroundGeolocationPlugin,\n StartOptions,\n Location,\n CallbackError,\n} from \"./definitions\";\n\nexport class BackgroundGeolocationWeb\n extends WebPlugin\n implements BackgroundGeolocationPlugin\n{\n private watchId: number | undefined;\n\n async start(\n options: StartOptions,\n callback: (position?: Location, error?: CallbackError) => void,\n ): Promise<void> {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n\n this.watchId = navigator.geolocation.watchPosition(\n (position) => {\n const location: Location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n callback(location);\n },\n (error) => {\n const callbackError: CallbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n },\n {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n },\n );\n }\n\n async stop(): Promise<void> {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n\n async openSettings(): Promise<void> {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n}\n"]}
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -7,22 +7,24 @@ const BackgroundGeolocation = core.registerPlugin("BackgroundGeolocation", {
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
class BackgroundGeolocationWeb extends core.WebPlugin {
|
|
10
|
-
|
|
11
|
-
super(...arguments);
|
|
12
|
-
this.watchers = new Map();
|
|
13
|
-
this.watcherCounter = 0;
|
|
14
|
-
}
|
|
15
|
-
async addWatcher(options, callback) {
|
|
16
|
-
const watcherId = `watcher_${++this.watcherCounter}`;
|
|
10
|
+
async start(options, callback) {
|
|
17
11
|
if (!navigator.geolocation) {
|
|
18
12
|
callback(undefined, {
|
|
19
13
|
name: "GeolocationError",
|
|
20
14
|
message: "Geolocation is not supported by this browser",
|
|
21
15
|
code: "NOT_SUPPORTED",
|
|
22
16
|
});
|
|
23
|
-
return
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (this.watchId) {
|
|
20
|
+
callback(undefined, {
|
|
21
|
+
name: "GeolocationError",
|
|
22
|
+
message: "Geolocation already started",
|
|
23
|
+
code: "ALREADY_STARTED",
|
|
24
|
+
});
|
|
25
|
+
return;
|
|
24
26
|
}
|
|
25
|
-
|
|
27
|
+
this.watchId = navigator.geolocation.watchPosition((position) => {
|
|
26
28
|
const location = {
|
|
27
29
|
latitude: position.coords.latitude,
|
|
28
30
|
longitude: position.coords.longitude,
|
|
@@ -47,14 +49,11 @@ class BackgroundGeolocationWeb extends core.WebPlugin {
|
|
|
47
49
|
timeout: 10000,
|
|
48
50
|
maximumAge: options.stale ? 300000 : 0,
|
|
49
51
|
});
|
|
50
|
-
this.watchers.set(watcherId, { watchId, callback });
|
|
51
|
-
return watcherId;
|
|
52
52
|
}
|
|
53
|
-
async
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.watchers.delete(options.id);
|
|
53
|
+
async stop() {
|
|
54
|
+
if (this.watchId) {
|
|
55
|
+
navigator.geolocation.clearWatch(this.watchId);
|
|
56
|
+
delete this.watchId;
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
59
|
async openSettings() {
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n async start(options, callback) {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n this.watchId = navigator.geolocation.watchPosition((position) => {\n const location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n callback(location);\n }, (error) => {\n const callbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n }, {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n });\n }\n async stop() {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n async openSettings() {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,qBAAqB,GAAGA,mBAAc,CAAC,uBAAuB,EAAE;AACtE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,wBAAwB,EAAE,CAAC;AAC5E,CAAC;;ACFM,MAAM,wBAAwB,SAASC,cAAS,CAAC;AACxD,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE;AACnC,QAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;AACpC,YAAY,QAAQ,CAAC,SAAS,EAAE;AAChC,gBAAgB,IAAI,EAAE,kBAAkB;AACxC,gBAAgB,OAAO,EAAE,8CAA8C;AACvE,gBAAgB,IAAI,EAAE,eAAe;AACrC,aAAa,CAAC;AACd,YAAY;AACZ,QAAQ;AACR,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;AAC1B,YAAY,QAAQ,CAAC,SAAS,EAAE;AAChC,gBAAgB,IAAI,EAAE,kBAAkB;AACxC,gBAAgB,OAAO,EAAE,6BAA6B;AACtD,gBAAgB,IAAI,EAAE,iBAAiB;AACvC,aAAa,CAAC;AACd,YAAY;AACZ,QAAQ;AACR,QAAQ,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,QAAQ,KAAK;AACzE,YAAY,MAAM,QAAQ,GAAG;AAC7B,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;AAClD,gBAAgB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;AACpD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;AAClD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;AAClD,gBAAgB,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB;AAClE,gBAAgB,SAAS,EAAE,KAAK;AAChC,gBAAgB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;AAChD,gBAAgB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;AAC5C,gBAAgB,IAAI,EAAE,QAAQ,CAAC,SAAS;AACxC,aAAa;AACb,YAAY,QAAQ,CAAC,QAAQ,CAAC;AAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK;AACtB,YAAY,MAAM,aAAa,GAAG;AAClC,gBAAgB,IAAI,EAAE,kBAAkB;AACxC,gBAAgB,OAAO,EAAE,KAAK,CAAC,OAAO;AACtC,gBAAgB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;AAC3C,aAAa;AACb,YAAY,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;AAC9C,QAAQ,CAAC,EAAE;AACX,YAAY,kBAAkB,EAAE,IAAI;AACpC,YAAY,OAAO,EAAE,KAAK;AAC1B,YAAY,UAAU,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC;AAClD,SAAS,CAAC;AACV,IAAI;AACJ,IAAI,MAAM,IAAI,GAAG;AACjB,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;AAC1B,YAAY,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;AAC1D,YAAY,OAAO,IAAI,CAAC,OAAO;AAC/B,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC;AACnF,QAAQ,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC;AACnF,IAAI;AACJ;;;;;;;;;"}
|
package/dist/plugin.js
CHANGED
|
@@ -6,22 +6,24 @@ var capacitorBackgroundGeolocation = (function (exports, core) {
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
class BackgroundGeolocationWeb extends core.WebPlugin {
|
|
9
|
-
|
|
10
|
-
super(...arguments);
|
|
11
|
-
this.watchers = new Map();
|
|
12
|
-
this.watcherCounter = 0;
|
|
13
|
-
}
|
|
14
|
-
async addWatcher(options, callback) {
|
|
15
|
-
const watcherId = `watcher_${++this.watcherCounter}`;
|
|
9
|
+
async start(options, callback) {
|
|
16
10
|
if (!navigator.geolocation) {
|
|
17
11
|
callback(undefined, {
|
|
18
12
|
name: "GeolocationError",
|
|
19
13
|
message: "Geolocation is not supported by this browser",
|
|
20
14
|
code: "NOT_SUPPORTED",
|
|
21
15
|
});
|
|
22
|
-
return
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (this.watchId) {
|
|
19
|
+
callback(undefined, {
|
|
20
|
+
name: "GeolocationError",
|
|
21
|
+
message: "Geolocation already started",
|
|
22
|
+
code: "ALREADY_STARTED",
|
|
23
|
+
});
|
|
24
|
+
return;
|
|
23
25
|
}
|
|
24
|
-
|
|
26
|
+
this.watchId = navigator.geolocation.watchPosition((position) => {
|
|
25
27
|
const location = {
|
|
26
28
|
latitude: position.coords.latitude,
|
|
27
29
|
longitude: position.coords.longitude,
|
|
@@ -46,14 +48,11 @@ var capacitorBackgroundGeolocation = (function (exports, core) {
|
|
|
46
48
|
timeout: 10000,
|
|
47
49
|
maximumAge: options.stale ? 300000 : 0,
|
|
48
50
|
});
|
|
49
|
-
this.watchers.set(watcherId, { watchId, callback });
|
|
50
|
-
return watcherId;
|
|
51
51
|
}
|
|
52
|
-
async
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.watchers.delete(options.id);
|
|
52
|
+
async stop() {
|
|
53
|
+
if (this.watchId) {
|
|
54
|
+
navigator.geolocation.clearWatch(this.watchId);
|
|
55
|
+
delete this.watchId;
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
async openSettings() {
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n async start(options, callback) {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n this.watchId = navigator.geolocation.watchPosition((position) => {\n const location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n callback(location);\n }, (error) => {\n const callbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n }, {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n });\n }\n async stop() {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n async openSettings() {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,qBAAqB,GAAGA,mBAAc,CAAC,uBAAuB,EAAE;IACtE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,wBAAwB,EAAE,CAAC;IAC5E,CAAC;;ICFM,MAAM,wBAAwB,SAASC,cAAS,CAAC;IACxD,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE;IACnC,QAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;IACpC,YAAY,QAAQ,CAAC,SAAS,EAAE;IAChC,gBAAgB,IAAI,EAAE,kBAAkB;IACxC,gBAAgB,OAAO,EAAE,8CAA8C;IACvE,gBAAgB,IAAI,EAAE,eAAe;IACrC,aAAa,CAAC;IACd,YAAY;IACZ,QAAQ;IACR,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;IAC1B,YAAY,QAAQ,CAAC,SAAS,EAAE;IAChC,gBAAgB,IAAI,EAAE,kBAAkB;IACxC,gBAAgB,OAAO,EAAE,6BAA6B;IACtD,gBAAgB,IAAI,EAAE,iBAAiB;IACvC,aAAa,CAAC;IACd,YAAY;IACZ,QAAQ;IACR,QAAQ,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,QAAQ,KAAK;IACzE,YAAY,MAAM,QAAQ,GAAG;IAC7B,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;IAClD,gBAAgB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;IACpD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;IAClD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;IAClD,gBAAgB,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB;IAClE,gBAAgB,SAAS,EAAE,KAAK;IAChC,gBAAgB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;IAChD,gBAAgB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;IAC5C,gBAAgB,IAAI,EAAE,QAAQ,CAAC,SAAS;IACxC,aAAa;IACb,YAAY,QAAQ,CAAC,QAAQ,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK;IACtB,YAAY,MAAM,aAAa,GAAG;IAClC,gBAAgB,IAAI,EAAE,kBAAkB;IACxC,gBAAgB,OAAO,EAAE,KAAK,CAAC,OAAO;IACtC,gBAAgB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;IAC3C,aAAa;IACb,YAAY,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAC9C,QAAQ,CAAC,EAAE;IACX,YAAY,kBAAkB,EAAE,IAAI;IACpC,YAAY,OAAO,EAAE,KAAK;IAC1B,YAAY,UAAU,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC;IAClD,SAAS,CAAC;IACV,IAAI;IACJ,IAAI,MAAM,IAAI,GAAG;IACjB,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;IAC1B,YAAY,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;IAC1D,YAAY,OAAO,IAAI,CAAC,OAAO;IAC/B,QAAQ;IACR,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC;IACnF,QAAQ,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC;IACnF,IAAI;IACJ;;;;;;;;;;;;;;;"}
|
package/ios/Plugin/Plugin.m
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#import <Capacitor/Capacitor.h>
|
|
3
3
|
|
|
4
4
|
CAP_PLUGIN(BackgroundGeolocation, "BackgroundGeolocation",
|
|
5
|
-
CAP_PLUGIN_METHOD(
|
|
6
|
-
CAP_PLUGIN_METHOD(
|
|
5
|
+
CAP_PLUGIN_METHOD(start, CAPPluginReturnCallback);
|
|
6
|
+
CAP_PLUGIN_METHOD(stop, CAPPluginReturnPromise);
|
|
7
7
|
CAP_PLUGIN_METHOD(openSettings, CAPPluginReturnPromise);
|
|
8
8
|
)
|
package/ios/Plugin/Plugin.swift
CHANGED
|
@@ -33,63 +33,41 @@ func formatLocation(_ location: CLLocation) -> PluginCallResultData {
|
|
|
33
33
|
]
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
class Watcher {
|
|
37
|
-
let callbackId: String
|
|
38
|
-
let locationManager: CLLocationManager = CLLocationManager()
|
|
39
|
-
private let created = Date()
|
|
40
|
-
private let allowStale: Bool
|
|
41
|
-
private var isUpdatingLocation: Bool = false
|
|
42
|
-
init(_ id: String, stale: Bool) {
|
|
43
|
-
callbackId = id
|
|
44
|
-
allowStale = stale
|
|
45
|
-
}
|
|
46
|
-
func start() {
|
|
47
|
-
// Avoid unnecessary calls to startUpdatingLocation, which can
|
|
48
|
-
// result in extraneous invocations of didFailWithError.
|
|
49
|
-
if !isUpdatingLocation {
|
|
50
|
-
locationManager.startUpdatingLocation()
|
|
51
|
-
isUpdatingLocation = true
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
func stop() {
|
|
55
|
-
if isUpdatingLocation {
|
|
56
|
-
locationManager.stopUpdatingLocation()
|
|
57
|
-
isUpdatingLocation = false
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
func isLocationValid(_ location: CLLocation) -> Bool {
|
|
61
|
-
return (
|
|
62
|
-
allowStale ||
|
|
63
|
-
location.timestamp >= created
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
36
|
@objc(BackgroundGeolocation)
|
|
69
37
|
public class BackgroundGeolocation: CAPPlugin, CLLocationManagerDelegate {
|
|
70
|
-
private var
|
|
38
|
+
private var locationManager: CLLocationManager?
|
|
39
|
+
private var created: Date?
|
|
40
|
+
private var allowStale: Bool = false
|
|
41
|
+
private var isUpdatingLocation: Bool = false
|
|
42
|
+
private var activeCallbackId: String?
|
|
71
43
|
|
|
72
44
|
@objc override public func load() {
|
|
73
45
|
UIDevice.current.isBatteryMonitoringEnabled = true
|
|
74
46
|
}
|
|
75
47
|
|
|
76
|
-
@objc func
|
|
48
|
+
@objc func start(_ call: CAPPluginCall) {
|
|
77
49
|
call.keepAlive = true
|
|
78
50
|
|
|
79
51
|
// CLLocationManager requires main thread
|
|
80
52
|
DispatchQueue.main.async {
|
|
53
|
+
// Check if already started
|
|
54
|
+
if self.locationManager != nil {
|
|
55
|
+
return call.reject("Location tracking already started", "ALREADY_STARTED")
|
|
56
|
+
}
|
|
57
|
+
// Create fresh location manager and initialize date
|
|
58
|
+
self.locationManager = CLLocationManager()
|
|
59
|
+
self.locationManager!.delegate = self
|
|
60
|
+
self.created = Date()
|
|
61
|
+
|
|
81
62
|
let background = call.getString("backgroundMessage") != nil
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
let manager = watcher.locationManager
|
|
87
|
-
manager.delegate = self
|
|
63
|
+
self.allowStale = call.getBool("stale") ?? false
|
|
64
|
+
self.activeCallbackId = call.callbackId
|
|
65
|
+
|
|
88
66
|
let externalPower = [
|
|
89
67
|
.full,
|
|
90
68
|
.charging
|
|
91
69
|
].contains(UIDevice.current.batteryState)
|
|
92
|
-
|
|
70
|
+
self.locationManager!.desiredAccuracy = (
|
|
93
71
|
externalPower
|
|
94
72
|
? kCLLocationAccuracyBestForNavigation
|
|
95
73
|
: kCLLocationAccuracyBest
|
|
@@ -100,11 +78,11 @@ public class BackgroundGeolocation: CAPPlugin, CLLocationManagerDelegate {
|
|
|
100
78
|
if distanceFilter == nil || distanceFilter == 0 {
|
|
101
79
|
distanceFilter = kCLDistanceFilterNone
|
|
102
80
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
81
|
+
self.locationManager!.distanceFilter = distanceFilter!
|
|
82
|
+
self.locationManager!.allowsBackgroundLocationUpdates = background
|
|
83
|
+
self.locationManager!.showsBackgroundLocationIndicator = background
|
|
84
|
+
self.locationManager!.pausesLocationUpdatesAutomatically = false
|
|
85
|
+
|
|
108
86
|
if call.getBool("requestPermissions") != false {
|
|
109
87
|
let status = CLLocationManager.authorizationStatus()
|
|
110
88
|
if [
|
|
@@ -114,35 +92,35 @@ public class BackgroundGeolocation: CAPPlugin, CLLocationManagerDelegate {
|
|
|
114
92
|
].contains(status) {
|
|
115
93
|
return (
|
|
116
94
|
background
|
|
117
|
-
?
|
|
118
|
-
:
|
|
95
|
+
? self.locationManager!.requestAlwaysAuthorization()
|
|
96
|
+
: self.locationManager!.requestWhenInUseAuthorization()
|
|
119
97
|
)
|
|
120
98
|
}
|
|
121
99
|
if background && status == .authorizedWhenInUse {
|
|
122
100
|
// Attempt to escalate.
|
|
123
|
-
|
|
101
|
+
self.locationManager!.requestAlwaysAuthorization()
|
|
124
102
|
}
|
|
125
103
|
}
|
|
126
|
-
return
|
|
104
|
+
return self.startUpdatingLocation()
|
|
127
105
|
}
|
|
128
106
|
}
|
|
129
107
|
|
|
130
|
-
@objc func
|
|
108
|
+
@objc func stop(_ call: CAPPluginCall) {
|
|
131
109
|
// CLLocationManager requires main thread
|
|
132
110
|
DispatchQueue.main.async {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
111
|
+
self.stopUpdatingLocation()
|
|
112
|
+
|
|
113
|
+
self.locationManager?.delegate = nil
|
|
114
|
+
self.locationManager = nil
|
|
115
|
+
self.created = nil
|
|
116
|
+
|
|
117
|
+
if let callbackId = self.activeCallbackId {
|
|
140
118
|
if let savedCall = self.bridge?.savedCall(withID: callbackId) {
|
|
141
119
|
self.bridge?.releaseCall(savedCall)
|
|
142
120
|
}
|
|
143
|
-
|
|
121
|
+
self.activeCallbackId = nil
|
|
144
122
|
}
|
|
145
|
-
return call.
|
|
123
|
+
return call.resolve()
|
|
146
124
|
}
|
|
147
125
|
}
|
|
148
126
|
|
|
@@ -169,46 +147,67 @@ public class BackgroundGeolocation: CAPPlugin, CLLocationManagerDelegate {
|
|
|
169
147
|
}
|
|
170
148
|
}
|
|
171
149
|
|
|
150
|
+
private func startUpdatingLocation() {
|
|
151
|
+
// Avoid unnecessary calls to startUpdatingLocation, which can
|
|
152
|
+
// result in extraneous invocations of didFailWithError.
|
|
153
|
+
if !isUpdatingLocation, let manager = locationManager {
|
|
154
|
+
manager.startUpdatingLocation()
|
|
155
|
+
isUpdatingLocation = true
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private func stopUpdatingLocation() {
|
|
160
|
+
if isUpdatingLocation, let manager = locationManager {
|
|
161
|
+
manager.stopUpdatingLocation()
|
|
162
|
+
isUpdatingLocation = false
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private func isLocationValid(_ location: CLLocation) -> Bool {
|
|
167
|
+
guard let created = created else { return allowStale }
|
|
168
|
+
return (
|
|
169
|
+
allowStale ||
|
|
170
|
+
location.timestamp >= created
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
172
174
|
public func locationManager(
|
|
173
175
|
_ manager: CLLocationManager,
|
|
174
176
|
didFailWithError error: Error
|
|
175
177
|
) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
return call.reject(error.localizedDescription, nil, error)
|
|
178
|
+
guard let callbackId = activeCallbackId,
|
|
179
|
+
let call = self.bridge?.savedCall(withID: callbackId) else {
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if let clErr = error as? CLError {
|
|
184
|
+
if clErr.code == .locationUnknown {
|
|
185
|
+
// This error is sometimes sent by the manager if
|
|
186
|
+
// it cannot get a fix immediately.
|
|
187
|
+
return
|
|
188
|
+
} else if clErr.code == .denied {
|
|
189
|
+
stopUpdatingLocation()
|
|
190
|
+
return call.reject(
|
|
191
|
+
"Permission denied.",
|
|
192
|
+
"NOT_AUTHORIZED"
|
|
193
|
+
)
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
+
return call.reject(error.localizedDescription, nil, error)
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
public func locationManager(
|
|
199
200
|
_ manager: CLLocationManager,
|
|
200
201
|
didUpdateLocations locations: [CLLocation]
|
|
201
202
|
) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
}
|
|
203
|
+
guard let location = locations.last,
|
|
204
|
+
let callbackId = activeCallbackId,
|
|
205
|
+
let call = self.bridge?.savedCall(withID: callbackId) else {
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if isLocationValid(location) {
|
|
210
|
+
return call.resolve(formatLocation(location))
|
|
212
211
|
}
|
|
213
212
|
}
|
|
214
213
|
|
|
@@ -220,11 +219,7 @@ public class BackgroundGeolocation: CAPPlugin, CLLocationManagerDelegate {
|
|
|
220
219
|
// it is on iOS 14 when the permissions dialog is presented, we ignore
|
|
221
220
|
// it.
|
|
222
221
|
if status != .notDetermined {
|
|
223
|
-
|
|
224
|
-
where: { $0.locationManager == manager }
|
|
225
|
-
) {
|
|
226
|
-
return watcher.start()
|
|
227
|
-
}
|
|
222
|
+
startUpdatingLocation()
|
|
228
223
|
}
|
|
229
224
|
}
|
|
230
225
|
}
|
package/package.json
CHANGED