-
Notifications
You must be signed in to change notification settings - Fork 0
/
cordova-geolocation-background.js
369 lines (347 loc) · 10.8 KB
/
cordova-geolocation-background.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
// Write your package code here!
/**
* This is an abstraction lib for handling backgrounded processes for GPS updates
*
* Source:
* https://github.com/christocracy/cordova-plugin-background-geolocation
*
* common:
* GeolocationBG.setup()
* [true/false] is this available and setup?
* GeolocationBG.config(options)
* getter/setter
* GeolocationBG.start()
* start background process
* GeolocationBG.stop()
* stop background process
* GeolocationBG.get()
* get the current location (handy shortcut)
*
* internal
* GeolocationBG.setup()
* GeolocationBG.send()
* [internal, non-android]
* GeolocationBG.sendCallbackSuccess()
* POSTs to the configured URL
* submits "data" as JSON content
*/
GeolocationBG = {
// configure these options via GeolocationBG.config()
// - options are passed into the config for Android background process
// - https://github.com/christocracy/cordova-plugin-background-geolocation
// - options are passed into HTTP.get()
// - https://github.com/meteor/meteor/blob/master/packages/http/httpcall_client.js
options: {
// your server url to send locations to
// YOU MUST SET THIS TO YOUR SERVER'S URL
// (see the setup instructions below)
url: 'http://example.com/api/geolocation',
params: {
// will be sent in with 'location' in POST data (root level params)
// these will be added automatically in setup()
//userId: GeolocationBG.userId(),
//uuid: GeolocationBG.uuid(),
//device: GeolocationBG.device()
},
headers: {
// will be sent in with 'location' in HTTP Header data
},
desiredAccuracy: 10,
stationaryRadius: 20,
distanceFilter: 30,
// Android ONLY, customize the title of the notification
notificationTitle: 'Background GPS',
// Android ONLY, customize the text of the notification
notificationText: 'ENABLED',
//
activityType: 'AutomotiveNavigation',
// enable this hear sounds for background-geolocation life-cycle.
debug: false
},
// placeholders
bgGeo: null,
fgGeo: null,
isStarted: false,
// start background service
start: function() {
if (!this.isStarted) {
this.get();
}
if (!this.setup()) {
console.error('GeolocationBG unable to setup, unable to start');
return false;
}
// Turn ON the background-geolocation system. The user will be tracked whenever they suspend the app.
this.bgGeo.start();
this.isStarted = true;
return true;
},
// stop background service
stop: function() {
if (!this.setup()) {
console.error('GeolocationBG unable to setup, unable to stop');
return false;
}
this.bgGeo.stop()
this.isStarted = false;
return true;
},
// where is this plugin available?
// get it whereever we can find it, and assign it to this.bgGeo
getPlugin: function() {
if (_.isObject(this.bgGeo)) {
return this.bgGeo;
}
console.log('backgroundGeoLocation ~ ' + typeof backgroundGeoLocation);
if (typeof backgroundGeoLocation == "object") {
this.bgGeo = backgroundGeoLocation || null;
if (_.isObject(this.bgGeo)) {
return this.bgGeo;
}
}
console.log('window.backgroundGeoLocation ~ ' + typeof window.backgroundGeoLocation);
if (typeof window.backgroundGeoLocation == "object") {
this.bgGeo = window.backgroundGeoLocation || null;
if (_.isObject(this.bgGeo)) {
return this.bgGeo;
}
}
if (typeof window.plugins == "object") {
console.log('window.plugins.backgroundGeoLocation ~ ' + typeof window.plugins.backgroundGeoLocation);
if (typeof window.plugins.backgroundGeoLocation == "object") {
this.bgGeo = window.plugins.backgroundGeoLocation || null;
if (_.isObject(this.bgGeo)) {
return this.bgGeo;
}
}
}
if (typeof cordova != "object") {
console.error('No cordova object in global scope');
return false;
}
console.log('cordova.backgroundGeoLocation ~ ' + typeof cordova.backgroundGeoLocation);
if (typeof cordova.backgroundGeoLocation == "object") {
this.bgGeo = cordova.backgroundGeoLocation || null;
if (_.isObject(this.bgGeo)) {
return this.bgGeo;
}
}
if (typeof cordova.plugins == "object") {
console.log('cordova.plugins.backgroundGeoLocation ~ ' + typeof cordova.plugins.backgroundGeoLocation);
if (typeof cordova.plugins.backgroundGeoLocation == "object") {
this.bgGeo = cordova.plugins.backgroundGeoLocation || null;
if (_.isObject(this.bgGeo)) {
return this.bgGeo;
}
}
}
for (var key in window) {
console.log(' window.' + key + ' ~ ' + typeof window[key]);
}
},
/**
* Configuration getter and setter
*/
config: function(options) {
if (_.isString(options)) {
this.options.url = options;
return this.options;
}
if (!_.isObject(options)) {
return this.options;
}
this.options = _.extend({}, this.options, options);
return this.options;
},
/**
* Setup the common usage for this plugin
*/
setup: function() {
if (!_.isNull(this.bgGeo)) {
return true;
}
this.getPlugin();
if (!_.isObject(this.bgGeo)) {
console.log('GeolocationBG.setup failed = not avail');
return false;
}
// update the options with automatic params
// params will be sent in with 'location' in POST data (root level params)
this.options.params.userId = GeolocationBG.userId();
this.options.params.uuid = GeolocationBG.uuid();
this.options.params.device = GeolocationBG.device();
// This callback will be executed every time a geolocation is recorded in the background.
// not used for Android
var callbackFn = function(location) {
console.log('GeolocationBG: setup: callbackFn: ' + _.values(location).join(','));
console.log('[js] BackgroundGeoLocation callback: ' + location.latitude + ',' + location.longitude);
// Do your HTTP request here to POST location to your server.
GeolocationBG.send(location);
};
// This callback will be executed for error
// not used for Android
var failureFn = function(error) {
console.log('GeolocationBG: setup: failureFn: ' + _.values(error).join(','));
console.log('BackgroundGeoLocation error');
}
// BackgroundGeoLocation is highly configurable.
// (NOTE: Android service is automatic)
GeolocationBG.bgGeo.configure(callbackFn, failureFn, this.options);
console.log('GeolocationBG: setup: end');
return true;
},
/**
* Send the location via AJAX to GeolocationBG.url
*
* @param object location
*/
send: function(location) {
console.log('GeolocationBG: send: init');
console.log(JSON.stringify(location));
if (!_.isObject(location)) {
console.error('GeolocationBG: send: error - location is invalid - not an object');
return;
}
if (_.has(location, 'location')) {
location = location.location;
}
if (_.has(location, 'coords')) {
location = location.coords;
}
if (!_.has(location, 'longitude')) {
console.error('GeolocationBG: send: error - location is invalid - no coords');
return;
}
var options = _.extend({
data: {
longitude: location.longitude,
latitude: location.latitude,
userId: GeolocationBG.userId(),
uuid: GeolocationBG.uuid(),
device: GeolocationBG.device()
}
}, this.options);
HTTP.call('POST', this.options.url, options, function(err, res) {
if (err) {
console.error('HTTP.call() callback error');
console.error(JSON.stringify(err));
return;
}
console.log('[debugging] HTTP.call() callback');
console.error(JSON.stringify(res));
GeolocationBG.sendCallbackSuccess(res);
});
},
/**
* Send the location via AJAX to GeolocationBG.url
*
* @param object location
*/
sendCallbackSuccess: function(res) {
console.log('GeolocationBG: send: success: ' + res);
console.log('[js] BackgroundGeoLocation callback, callback = success' + res);
//
// IMPORTANT: You must execute the #finish method here to inform the native plugin that you're finished,
// and the background-task may be completed. You must do this regardless if your HTTP request is successful or not.
// IF YOU DON'T, ios will CRASH YOUR APP for spending too much time in the background.
//
GeolocationBG.bgGeo.finish();
},
/**
* get the userId
*
* @param object location
*/
userId: function() {
if (!Meteor) {
return 'noMeteorObj';
}
if (!_.has(Meteor, 'userId')) {
return 'noMeteor.userId';
}
if (_.isString(Meteor.userId)) {
return Meteor.userId;
}
try {
return Meteor.userId();
} catch (e) {
return '?';
}
},
/**
* get the device info basics (tie back to user)
*
* @param object location
*/
device: function() {
device = device || {};
if (!_.isObject(device)) {
return 'errDeviceNotObject';
}
if (!_.has(device, 'platform')) {
device.platform = '?';
}
if (!_.has(device, 'model')) {
device.model = '?';
}
if (!_.has(device, 'version')) {
device.version = '?';
}
return device.platform + '(' + device.model + ') [' + device.version + ']';
},
/**
* get the device info basics (tie back to user)
*
* @param object location
*/
uuid: function() {
device = device || {};
if (!_.isObject(device)) {
return 'errDeviceNotObject';
}
if (!_.has(device, 'uuid')) {
device.uuid = '?';
}
return device.uuid;
},
/**
* Get the navigator.geolocation plugin (foreground)
*
*/
getPluginFG: function() {
if (_.isObject(this.fgGeo)) {
return this.fgGeo;
}
this.fgGeo = window.navigator.geolocation || null;
if (_.isObject(this.fgGeo)) {
return this.fgGeo;
}
this.fgGeo = navigator.geolocation || null;
if (_.isObject(this.fgGeo)) {
return this.fgGeo;
}
this.fgGeo = geolocation || null;
if (_.isObject(this.fgGeo)) {
return this.fgGeo;
}
console.error('navigator.geolocation does not exist');
},
/**
* Get the current/realtime location (not in BG)
*
* Your app must execute AT LEAST ONE call for the current position via standard Cordova geolocation,
* in order to prompt the user for Location permission.
*/
get: function() {
console.log('GeolocationBG: get: init');
this.getPluginFG();
if (!_.isObject(this.fgGeo)) {
console.error('GeolocationBG: get: failure... navigator.geolocation not available');
return;
}
this.fgGeo.getCurrentPosition(function(location) {
console.log('GeolocationBG: get: got');
GeolocationBG.send(location);
});
}
}