@capgo/background-geolocation 7.0.14 → 7.0.19
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 +4 -3
- package/Package.swift +28 -0
- package/README.md +19 -2
- package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocation.java +270 -336
- package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocationService.java +267 -329
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +4 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +2 -2
- package/dist/esm/web.js +16 -24
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +16 -24
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +16 -24
- package/dist/plugin.js.map +1 -1
- package/ios/{Plugin/Plugin.swift → Sources/CapgoBackgroundGeolocationPlugin/CapgoCapacitorBackgroundGeolocationPlugin.swift} +9 -1
- package/ios/Tests/CapgoBackgroundGeolocationPluginTests/CapgoBackgroundGeolocationPluginTests.swift +15 -0
- package/package.json +11 -10
- package/ios/Plugin/Info.plist +0 -24
- package/ios/Plugin/Plugin.h +0 -10
- package/ios/Plugin/Plugin.m +0 -9
package/android/src/main/java/com/capgo/capacitor_background_geolocation/BackgroundGeolocation.java
CHANGED
|
@@ -34,382 +34,316 @@ import org.json.JSONException;
|
|
|
34
34
|
import org.json.JSONObject;
|
|
35
35
|
|
|
36
36
|
@CapacitorPlugin(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Manifest.permission.ACCESS_FINE_LOCATION,
|
|
43
|
-
},
|
|
44
|
-
alias = "location"
|
|
45
|
-
),
|
|
46
|
-
@Permission(
|
|
47
|
-
strings = { Manifest.permission.POST_NOTIFICATIONS },
|
|
48
|
-
alias = "notification"
|
|
49
|
-
),
|
|
50
|
-
}
|
|
37
|
+
name = "BackgroundGeolocation",
|
|
38
|
+
permissions = {
|
|
39
|
+
@Permission(strings = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }, alias = "location"),
|
|
40
|
+
@Permission(strings = { Manifest.permission.POST_NOTIFICATIONS }, alias = "notification")
|
|
41
|
+
}
|
|
51
42
|
)
|
|
52
43
|
public class BackgroundGeolocation extends Plugin {
|
|
53
44
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
68
|
-
} catch (SecurityException ignore) {}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
@PluginMethod(returnType = PluginMethod.RETURN_CALLBACK)
|
|
72
|
-
public void start(final PluginCall call) {
|
|
73
|
-
if (
|
|
74
|
-
getPermissionState("location") != PermissionState.GRANTED &&
|
|
75
|
-
!call.getBoolean("requestPermissions", true)
|
|
76
|
-
) {
|
|
77
|
-
call.reject("User denied location permission", "NOT_AUTHORIZED");
|
|
78
|
-
return;
|
|
45
|
+
private CompletableFuture<BackgroundGeolocationService.LocalBinder> serviceConnectionFuture;
|
|
46
|
+
private CompletableFuture<Void> locationPermissionFuture;
|
|
47
|
+
|
|
48
|
+
private void fetchLastLocation(PluginCall call) {
|
|
49
|
+
try {
|
|
50
|
+
LocationServices.getFusedLocationProviderClient(getContext())
|
|
51
|
+
.getLastLocation()
|
|
52
|
+
.addOnSuccessListener(getActivity(), (location) -> {
|
|
53
|
+
if (location != null) {
|
|
54
|
+
call.resolve(formatLocation(location));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
} catch (SecurityException ignore) {}
|
|
79
58
|
}
|
|
80
59
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
60
|
+
@PluginMethod(returnType = PluginMethod.RETURN_CALLBACK)
|
|
61
|
+
public void start(final PluginCall call) {
|
|
62
|
+
if (getPermissionState("location") != PermissionState.GRANTED && !call.getBoolean("requestPermissions", true)) {
|
|
63
|
+
call.reject("User denied location permission", "NOT_AUTHORIZED");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
85
66
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
call.setKeepAlive(true);
|
|
91
|
-
requestLocationPermissions(call)
|
|
92
|
-
.thenRun(() -> {
|
|
93
|
-
proceedWithStart(call);
|
|
94
|
-
})
|
|
95
|
-
.exceptionally(throwable -> {
|
|
96
|
-
call.reject("User denied location permission", "NOT_AUTHORIZED");
|
|
97
|
-
return null;
|
|
98
|
-
});
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
67
|
+
if (serviceConnectionFuture != null) {
|
|
68
|
+
call.reject("Service already started", "ALREADY_STARTED");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
101
71
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
72
|
+
if (getPermissionState("location") != PermissionState.GRANTED && call.getBoolean("requestPermissions", true)) {
|
|
73
|
+
call.setKeepAlive(true);
|
|
74
|
+
requestLocationPermissions(call)
|
|
75
|
+
.thenRun(() -> {
|
|
76
|
+
proceedWithStart(call);
|
|
77
|
+
})
|
|
78
|
+
.exceptionally((throwable) -> {
|
|
79
|
+
call.reject("User denied location permission", "NOT_AUTHORIZED");
|
|
80
|
+
return null;
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
107
84
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
85
|
+
// location permission granted.
|
|
86
|
+
if (!isLocationEnabled(getContext())) {
|
|
87
|
+
call.reject("Location services disabled.", "NOT_AUTHORIZED");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
112
90
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
91
|
+
// Everything is OK, continuing to adding a watcher
|
|
92
|
+
call.setKeepAlive(true);
|
|
93
|
+
proceedWithStart(call);
|
|
116
94
|
}
|
|
117
|
-
getServiceConnection().thenAccept(serviceBinder -> {
|
|
118
|
-
serviceBinder.start(
|
|
119
|
-
call.getCallbackId(),
|
|
120
|
-
call.getString("backgroundTitle", "Using your location"),
|
|
121
|
-
call.getString("backgroundMessage", ""),
|
|
122
|
-
call.getFloat("distanceFilter", 0f)
|
|
123
|
-
);
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
95
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return;
|
|
96
|
+
private void proceedWithStart(PluginCall call) {
|
|
97
|
+
if (call.getBoolean("stale", false)) {
|
|
98
|
+
fetchLastLocation(call);
|
|
99
|
+
}
|
|
100
|
+
getServiceConnection().thenAccept((serviceBinder) -> {
|
|
101
|
+
serviceBinder.start(
|
|
102
|
+
call.getCallbackId(),
|
|
103
|
+
call.getString("backgroundTitle", "Using your location"),
|
|
104
|
+
call.getString("backgroundMessage", ""),
|
|
105
|
+
call.getFloat("distanceFilter", 0f)
|
|
106
|
+
);
|
|
107
|
+
});
|
|
140
108
|
}
|
|
141
109
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
locationPermissionFuture.completeExceptionally(
|
|
150
|
-
new SecurityException("User denied location permission")
|
|
151
|
-
);
|
|
152
|
-
locationPermissionFuture = null;
|
|
153
|
-
return;
|
|
110
|
+
private CompletableFuture<Void> requestLocationPermissions(PluginCall call) {
|
|
111
|
+
if (locationPermissionFuture != null) {
|
|
112
|
+
return locationPermissionFuture;
|
|
113
|
+
}
|
|
114
|
+
locationPermissionFuture = new CompletableFuture<>();
|
|
115
|
+
requestPermissionForAlias("location", call, "locationPermissionsCallback");
|
|
116
|
+
return locationPermissionFuture;
|
|
154
117
|
}
|
|
155
118
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
119
|
+
@PermissionCallback
|
|
120
|
+
private void locationPermissionsCallback(PluginCall call) {
|
|
121
|
+
if (locationPermissionFuture == null) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
159
124
|
|
|
160
|
-
|
|
161
|
-
private void notificationPermissionsCallback(PluginCall call) {
|
|
162
|
-
Logger.debug("notification permission callback");
|
|
163
|
-
}
|
|
125
|
+
requestPermissionForAlias("notification", call, "notificationPermissionsCallback");
|
|
164
126
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
getServiceConnection()
|
|
171
|
-
.thenAccept(service -> {
|
|
172
|
-
var callbackId = service.stop();
|
|
173
|
-
PluginCall savedCall = getBridge().getSavedCall(callbackId);
|
|
174
|
-
if (savedCall != null) {
|
|
175
|
-
savedCall.release(getBridge());
|
|
127
|
+
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
128
|
+
locationPermissionFuture.completeExceptionally(new SecurityException("User denied location permission"));
|
|
129
|
+
locationPermissionFuture = null;
|
|
130
|
+
return;
|
|
176
131
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
.exceptionally(throwable -> {
|
|
181
|
-
call.reject("Service connection failed: " + throwable.getMessage());
|
|
182
|
-
return null;
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
@PluginMethod
|
|
187
|
-
public void openSettings(PluginCall call) {
|
|
188
|
-
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
|
189
|
-
Uri uri = Uri.fromParts("package", getContext().getPackageName(), null);
|
|
190
|
-
intent.setData(uri);
|
|
191
|
-
getContext().startActivity(intent);
|
|
192
|
-
call.resolve();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
@PluginMethod
|
|
196
|
-
public void setPlannedRoute(PluginCall call) {
|
|
197
|
-
String soundFile = call.getString("soundFile");
|
|
198
|
-
if (soundFile == null || soundFile.isEmpty()) {
|
|
199
|
-
call.reject("Sound file is required");
|
|
200
|
-
return;
|
|
132
|
+
|
|
133
|
+
locationPermissionFuture.complete(null);
|
|
134
|
+
locationPermissionFuture = null;
|
|
201
135
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
"
|
|
206
|
-
);
|
|
207
|
-
return;
|
|
136
|
+
|
|
137
|
+
@PermissionCallback
|
|
138
|
+
private void notificationPermissionsCallback(PluginCall call) {
|
|
139
|
+
Logger.debug("notification permission callback");
|
|
208
140
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
141
|
+
|
|
142
|
+
@PluginMethod
|
|
143
|
+
public void stop(PluginCall call) {
|
|
144
|
+
if (serviceConnectionFuture == null) {
|
|
145
|
+
call.resolve();
|
|
146
|
+
}
|
|
147
|
+
getServiceConnection()
|
|
148
|
+
.thenAccept((service) -> {
|
|
149
|
+
var callbackId = service.stop();
|
|
150
|
+
PluginCall savedCall = getBridge().getSavedCall(callbackId);
|
|
151
|
+
if (savedCall != null) {
|
|
152
|
+
savedCall.release(getBridge());
|
|
153
|
+
}
|
|
154
|
+
call.resolve();
|
|
155
|
+
serviceConnectionFuture = null;
|
|
156
|
+
})
|
|
157
|
+
.exceptionally((throwable) -> {
|
|
158
|
+
call.reject("Service connection failed: " + throwable.getMessage());
|
|
159
|
+
return null;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@PluginMethod
|
|
164
|
+
public void openSettings(PluginCall call) {
|
|
165
|
+
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
|
166
|
+
Uri uri = Uri.fromParts("package", getContext().getPackageName(), null);
|
|
167
|
+
intent.setData(uri);
|
|
168
|
+
getContext().startActivity(intent);
|
|
169
|
+
call.resolve();
|
|
226
170
|
}
|
|
227
|
-
}
|
|
228
171
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
172
|
+
@PluginMethod
|
|
173
|
+
public void setPlannedRoute(PluginCall call) {
|
|
174
|
+
String soundFile = call.getString("soundFile");
|
|
175
|
+
if (soundFile == null || soundFile.isEmpty()) {
|
|
176
|
+
call.reject("Sound file is required");
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (serviceConnectionFuture == null) {
|
|
180
|
+
call.reject("Service not started, make sure to call start() first", "NOT_STARTED");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
double[][] javaDoubleArray = getJavaDoubleArray(call.getArray("route"));
|
|
185
|
+
serviceConnectionFuture
|
|
186
|
+
.thenAccept((service) -> {
|
|
187
|
+
service.setPlannedRoute(soundFile, javaDoubleArray, call.getFloat("distance", 50f));
|
|
188
|
+
call.resolve();
|
|
189
|
+
})
|
|
190
|
+
.exceptionally((throwable) -> {
|
|
191
|
+
call.reject("Failed to set route: " + throwable.getMessage());
|
|
192
|
+
return null;
|
|
193
|
+
});
|
|
194
|
+
} catch (Exception ex) {
|
|
195
|
+
call.reject("Unable to parse route parameters");
|
|
196
|
+
}
|
|
234
197
|
}
|
|
235
198
|
|
|
236
|
-
|
|
237
|
-
|
|
199
|
+
private static double[][] getJavaDoubleArray(JSArray jsArray) throws JSONException {
|
|
200
|
+
int rows = jsArray.length();
|
|
201
|
+
if (rows == 0) {
|
|
202
|
+
return new double[0][2];
|
|
203
|
+
}
|
|
238
204
|
|
|
239
|
-
|
|
205
|
+
JSONArray firstRow = jsArray.getJSONArray(0);
|
|
206
|
+
int cols = firstRow.length();
|
|
240
207
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
208
|
+
var javaDoubleArray = new double[rows][cols];
|
|
209
|
+
|
|
210
|
+
for (int i = 0; i < rows; i++) {
|
|
211
|
+
JSONArray rowArray = jsArray.getJSONArray(i);
|
|
212
|
+
if (rowArray.length() != cols) {
|
|
213
|
+
throw new JSONException("Input array is not a consistent 2D array.");
|
|
214
|
+
}
|
|
215
|
+
for (int j = 0; j < cols; j++) {
|
|
216
|
+
javaDoubleArray[i][j] = rowArray.getDouble(j);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return javaDoubleArray;
|
|
249
220
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
Settings.Secure.getInt(
|
|
263
|
-
context.getContentResolver(),
|
|
264
|
-
Settings.Secure.LOCATION_MODE,
|
|
265
|
-
Settings.Secure.LOCATION_MODE_OFF
|
|
266
|
-
) !=
|
|
267
|
-
Settings.Secure.LOCATION_MODE_OFF
|
|
268
|
-
);
|
|
221
|
+
|
|
222
|
+
// Checks if device-wide location services are disabled
|
|
223
|
+
private static Boolean isLocationEnabled(Context context) {
|
|
224
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
225
|
+
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
|
226
|
+
return lm != null && lm.isLocationEnabled();
|
|
227
|
+
} else {
|
|
228
|
+
return (
|
|
229
|
+
Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) !=
|
|
230
|
+
Settings.Secure.LOCATION_MODE_OFF
|
|
231
|
+
);
|
|
232
|
+
}
|
|
269
233
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
234
|
+
|
|
235
|
+
private static JSObject formatLocation(Location location) {
|
|
236
|
+
JSObject obj = new JSObject();
|
|
237
|
+
obj.put("latitude", location.getLatitude());
|
|
238
|
+
obj.put("longitude", location.getLongitude());
|
|
239
|
+
// The docs state that all Location objects have an accuracy, but then why is there a
|
|
240
|
+
// hasAccuracy method? Better safe than sorry.
|
|
241
|
+
obj.put("accuracy", location.hasAccuracy() ? location.getAccuracy() : JSONObject.NULL);
|
|
242
|
+
obj.put("altitude", location.hasAltitude() ? location.getAltitude() : JSONObject.NULL);
|
|
243
|
+
if (Build.VERSION.SDK_INT >= 26 && location.hasVerticalAccuracy()) {
|
|
244
|
+
obj.put("altitudeAccuracy", location.getVerticalAccuracyMeters());
|
|
245
|
+
} else {
|
|
246
|
+
obj.put("altitudeAccuracy", JSONObject.NULL);
|
|
247
|
+
}
|
|
248
|
+
// In addition to mocking locations in development, Android allows the
|
|
249
|
+
// installation of apps which have the power to simulate location
|
|
250
|
+
// readings in other apps.
|
|
251
|
+
obj.put("simulated", location.isFromMockProvider());
|
|
252
|
+
obj.put("speed", location.hasSpeed() ? location.getSpeed() : JSONObject.NULL);
|
|
253
|
+
obj.put("bearing", location.hasBearing() ? location.getBearing() : JSONObject.NULL);
|
|
254
|
+
obj.put("time", location.getTime());
|
|
255
|
+
return obj;
|
|
290
256
|
}
|
|
291
|
-
// In addition to mocking locations in development, Android allows the
|
|
292
|
-
// installation of apps which have the power to simulate location
|
|
293
|
-
// readings in other apps.
|
|
294
|
-
obj.put("simulated", location.isFromMockProvider());
|
|
295
|
-
obj.put(
|
|
296
|
-
"speed",
|
|
297
|
-
location.hasSpeed() ? location.getSpeed() : JSONObject.NULL
|
|
298
|
-
);
|
|
299
|
-
obj.put(
|
|
300
|
-
"bearing",
|
|
301
|
-
location.hasBearing() ? location.getBearing() : JSONObject.NULL
|
|
302
|
-
);
|
|
303
|
-
obj.put("time", location.getTime());
|
|
304
|
-
return obj;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Receives messages from the service.
|
|
308
|
-
private class ServiceReceiver extends BroadcastReceiver {
|
|
309
257
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
258
|
+
// Receives messages from the service.
|
|
259
|
+
private class ServiceReceiver extends BroadcastReceiver {
|
|
260
|
+
|
|
261
|
+
@Override
|
|
262
|
+
public void onReceive(Context context, Intent intent) {
|
|
263
|
+
String id = intent.getStringExtra("id");
|
|
264
|
+
PluginCall call = getBridge().getSavedCall(id);
|
|
265
|
+
if (call == null) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
Location location = intent.getParcelableExtra("location");
|
|
269
|
+
if (location != null) {
|
|
270
|
+
call.resolve(formatLocation(location));
|
|
271
|
+
} else {
|
|
272
|
+
Logger.debug("No locations received");
|
|
273
|
+
}
|
|
274
|
+
}
|
|
323
275
|
}
|
|
324
|
-
}
|
|
325
276
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
277
|
+
@Override
|
|
278
|
+
public void load() {
|
|
279
|
+
super.load();
|
|
280
|
+
|
|
281
|
+
// Android O requires a Notification Channel.
|
|
282
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
283
|
+
NotificationManager manager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
|
284
|
+
NotificationChannel channel = new NotificationChannel(
|
|
285
|
+
BackgroundGeolocationService.class.getPackage().getName(),
|
|
286
|
+
BackgroundGeolocationService.getAppString(
|
|
287
|
+
"capacitor_background_geolocation_notification_channel_name",
|
|
288
|
+
"Background Tracking",
|
|
289
|
+
getContext()
|
|
290
|
+
),
|
|
291
|
+
NotificationManager.IMPORTANCE_DEFAULT
|
|
292
|
+
);
|
|
293
|
+
channel.enableLights(false);
|
|
294
|
+
channel.enableVibration(false);
|
|
295
|
+
channel.setSound(null, null);
|
|
296
|
+
manager.createNotificationChannel(channel);
|
|
297
|
+
}
|
|
329
298
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
(NotificationManager) getContext().getSystemService(
|
|
334
|
-
Context.NOTIFICATION_SERVICE
|
|
299
|
+
LocalBroadcastManager.getInstance(this.getContext()).registerReceiver(
|
|
300
|
+
new ServiceReceiver(),
|
|
301
|
+
new IntentFilter(BackgroundGeolocationService.ACTION_BROADCAST)
|
|
335
302
|
);
|
|
336
|
-
NotificationChannel channel = new NotificationChannel(
|
|
337
|
-
BackgroundGeolocationService.class.getPackage().getName(),
|
|
338
|
-
BackgroundGeolocationService.getAppString(
|
|
339
|
-
"capacitor_background_geolocation_notification_channel_name",
|
|
340
|
-
"Background Tracking",
|
|
341
|
-
getContext()
|
|
342
|
-
),
|
|
343
|
-
NotificationManager.IMPORTANCE_DEFAULT
|
|
344
|
-
);
|
|
345
|
-
channel.enableLights(false);
|
|
346
|
-
channel.enableVibration(false);
|
|
347
|
-
channel.setSound(null, null);
|
|
348
|
-
manager.createNotificationChannel(channel);
|
|
349
303
|
}
|
|
350
304
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
private CompletableFuture<
|
|
358
|
-
BackgroundGeolocationService.LocalBinder
|
|
359
|
-
> getServiceConnection() {
|
|
360
|
-
if (
|
|
361
|
-
serviceConnectionFuture != null &&
|
|
362
|
-
!serviceConnectionFuture.isCompletedExceptionally()
|
|
363
|
-
) {
|
|
364
|
-
return serviceConnectionFuture;
|
|
365
|
-
}
|
|
305
|
+
private CompletableFuture<BackgroundGeolocationService.LocalBinder> getServiceConnection() {
|
|
306
|
+
if (serviceConnectionFuture != null && !serviceConnectionFuture.isCompletedExceptionally()) {
|
|
307
|
+
return serviceConnectionFuture;
|
|
308
|
+
}
|
|
366
309
|
|
|
367
|
-
|
|
310
|
+
serviceConnectionFuture = new CompletableFuture<>();
|
|
368
311
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
} else {
|
|
376
|
-
this.getContext().startService(serviceIntent);
|
|
377
|
-
}
|
|
312
|
+
Intent serviceIntent = new Intent(this.getContext(), BackgroundGeolocationService.class);
|
|
313
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
314
|
+
this.getContext().startForegroundService(serviceIntent);
|
|
315
|
+
} else {
|
|
316
|
+
this.getContext().startService(serviceIntent);
|
|
317
|
+
}
|
|
378
318
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return serviceConnectionFuture;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
@Override
|
|
401
|
-
protected void handleOnDestroy() {
|
|
402
|
-
if (serviceConnectionFuture != null) {
|
|
403
|
-
serviceConnectionFuture.thenAccept(
|
|
404
|
-
BackgroundGeolocationService.LocalBinder::stop
|
|
405
|
-
);
|
|
319
|
+
this.getContext().bindService(
|
|
320
|
+
serviceIntent,
|
|
321
|
+
new ServiceConnection() {
|
|
322
|
+
@Override
|
|
323
|
+
public void onServiceConnected(ComponentName name, IBinder binder) {
|
|
324
|
+
serviceConnectionFuture.complete((BackgroundGeolocationService.LocalBinder) binder);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
@Override
|
|
328
|
+
public void onServiceDisconnected(ComponentName name) {
|
|
329
|
+
serviceConnectionFuture = null;
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
Context.BIND_AUTO_CREATE
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
return serviceConnectionFuture;
|
|
406
336
|
}
|
|
407
337
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
338
|
+
@Override
|
|
339
|
+
protected void handleOnDestroy() {
|
|
340
|
+
if (serviceConnectionFuture != null) {
|
|
341
|
+
serviceConnectionFuture.thenAccept(BackgroundGeolocationService.LocalBinder::stop);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (locationPermissionFuture != null && !locationPermissionFuture.isDone()) {
|
|
345
|
+
locationPermissionFuture.cancel(true);
|
|
346
|
+
}
|
|
347
|
+
super.handleOnDestroy();
|
|
412
348
|
}
|
|
413
|
-
super.handleOnDestroy();
|
|
414
|
-
}
|
|
415
349
|
}
|