Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
cordova-plugin-background-geolocation
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Aksimaya
cordova-plugin-background-geolocation
Commits
eb0d6d80
Commit
eb0d6d80
authored
Nov 09, 2013
by
Chris Scott
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'refactor'
parents
d4d7571f
51857664
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
162 additions
and
102 deletions
+162
-102
CDVBackgroundGeoLocation.h
src/ios/CDVBackgroundGeoLocation.h
+2
-8
CDVBackgroundGeoLocation.m
src/ios/CDVBackgroundGeoLocation.m
+147
-93
BackgroundGeoLocation.js
www/BackgroundGeoLocation.js
+13
-1
No files found.
src/ios/CDVBackgroundGeoLocation.h
View file @
eb0d6d80
...
...
@@ -12,17 +12,11 @@
-
(
void
)
start
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
stop
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
test
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
finish
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
sync
;
-
(
void
)
onSuspend
:(
NSNotification
*
)
notification
;
-
(
void
)
onResume
:(
NSNotification
*
)
notification
;
@property
(
nonatomic
,
retain
)
NSString
*
token
;
@property
(
nonatomic
,
retain
)
NSString
*
url
;
@property
(
nonatomic
,
assign
)
BOOL
enabled
;
@property
(
nonatomic
,
retain
)
NSNumber
*
maxBackgroundHours
;
@property
(
nonatomic
,
strong
)
CLLocationManager
*
locationManager
;
@property
(
nonatomic
,
strong
)
CDVLocationData
*
locationData
;
@property
(
strong
)
NSMutableArray
*
locationCache
;
@property
(
nonatomic
,
retain
)
NSDate
*
suspendedAt
;
@end
src/ios/CDVBackgroundGeoLocation.m
View file @
eb0d6d80
...
...
@@ -8,57 +8,81 @@
#import "CDVBackgroundGeoLocation.h"
#import <Cordova/CDVJSON.h>
@implementation
CDVBackgroundGeoLocation
@synthesize
enabled
,
token
,
url
,
locationManager
,
locationData
,
locationCache
,
suspendedAt
;
@implementation
CDVBackgroundGeoLocation
{
BOOL
enabled
;
NSString
*
token
;
NSString
*
url
;
NSString
*
syncCallbackId
;
UIBackgroundTaskIdentifier
bgTask
;
NSNumber
*
maxBackgroundHours
;
CLLocationManager
*
locationManager
;
CDVLocationData
*
locationData
;
NSMutableArray
*
locationCache
;
NSDate
*
suspendedAt
;
CLCircularRegion
*
myRegion
;
NSInteger
stationaryRadius
;
NSInteger
distanceFilter
;
NSInteger
locationTimeout
;
}
-
(
CDVPlugin
*
)
initWithWebView
:(
UIWebView
*
)
theWebView
{
// background location cache, for when no network is detected.
self
.
locationCache
=
[
NSMutableArray
array
];
locationCache
=
[
NSMutableArray
array
];
locationManager
=
[[
CLLocationManager
alloc
]
init
];
locationManager
.
delegate
=
self
;
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector:
@selector
(
onSuspend
:)
name:
UIApplicationDidEnterBackgroundNotification
object:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
onSuspend
:
)
name
:
UIApplicationDidEnterBackgroundNotification
object
:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector:
@selector
(
onResume
:)
name:
UIApplicationWillEnterForegroundNotification
object:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
onResume
:
)
name
:
UIApplicationWillEnterForegroundNotification
object
:
nil
];
return
self
;
}
-
(
void
)
configure
:(
CDVInvokedUrlCommand
*
)
command
{
self
.
locationManager
=
[[
CLLocationManager
alloc
]
init
];
self
.
locationManager
.
delegate
=
self
;
// in iOS, we call to javascript for HTTP now so token and url should be @deprecated until Android calls out to javascript.
token
=
[
command
.
arguments
objectAtIndex
:
0
];
url
=
[
command
.
arguments
objectAtIndex
:
1
];
// Location filtering.
stationaryRadius
=
[[
command
.
arguments
objectAtIndex
:
2
]
intValue
];
distanceFilter
=
[[
command
.
arguments
objectAtIndex
:
3
]
intValue
];
locationTimeout
=
[[
command
.
arguments
objectAtIndex
:
4
]
intValue
];
syncCallbackId
=
command
.
callbackId
;
self
.
token
=
[
command
.
arguments
objectAtIndex
:
0
];
self
.
url
=
[
command
.
arguments
objectAtIndex
:
1
];
// Set a movement threshold for new events.
locationManager
.
activityType
=
CLActivityTypeOther
;
locationManager
.
pausesLocationUpdatesAutomatically
=
YES
;
locationManager
.
desiredAccuracy
=
kCLLocationAccuracyKilometer
;
locationManager
.
distanceFilter
=
distanceFilter
;
// meters
NSLog
(
@"CDVBackgroundGeoLocation configure"
);
NSLog
(
@" -token: %@"
,
self
.
token
);
NSLog
(
@" -url: %@"
,
self
.
url
);
NSLog
(
@" - token: %@"
,
token
);
NSLog
(
@" - url: %@"
,
url
);
NSLog
(
@" - distanceFilter: %ld"
,
(
long
)
distanceFilter
);
NSLog
(
@" - stationaryRadius: %ld"
,
(
long
)
stationaryRadius
);
NSLog
(
@" - locationTimeout: %ld"
,
(
long
)
locationTimeout
);
}
-
(
void
)
start
:(
CDVInvokedUrlCommand
*
)
command
{
NSLog
(
@"CDVBackgroundGeoLocation start"
);
self
.
enabled
=
YES
;
enabled
=
YES
;
}
-
(
void
)
stop
:(
CDVInvokedUrlCommand
*
)
command
{
NSLog
(
@"CDVBackgroundGeoLocation stop"
);
self
.
enabled
=
NO
;
[
self
.
locationManager
stopMonitoringSignificantLocationChanges
];
enabled
=
NO
;
[
locationManager
stopUpdatingLocation
];
[
locationManager
stopMonitoringSignificantLocationChanges
];
}
-
(
void
)
test
:(
CDVInvokedUrlCommand
*
)
command
{
NSLog
(
@"CDVBackgroundGeoLocation test"
);
[
self
.
locationManager
startMonitoringSignificantLocationChanges
];
if
([
self
.
locationCache
count
]
>
0
){
[
locationManager
startMonitoringSignificantLocationChanges
];
if
([
locationCache
count
]
>
0
){
[
self
sync
];
}
else
{
NSLog
(
@"CDVBackgroundGeoLocation could not find a location to sync"
);
...
...
@@ -67,20 +91,25 @@
-
(
void
)
onSuspend
:(
NSNotification
*
)
notification
{
NSLog
(
@"CDVBackgroundGeoLocation suspend"
);
s
elf
.
s
uspendedAt
=
[
NSDate
date
];
suspendedAt
=
[
NSDate
date
];
if
(
self
.
enabled
)
{
[
self
.
locationManager
startMonitoringSignificantLocationChanges
];
if
(
enabled
)
{
if
(
myRegion
==
nil
)
{
myRegion
=
[
self
createStationaryRegion
];
[
locationManager
startMonitoringForRegion
:
myRegion
];
}
[
locationManager
startMonitoringSignificantLocationChanges
];
}
}
-
(
void
)
onResume
:(
NSNotification
*
)
notification
{
NSLog
(
@"CDVBackgroundGeoLocation resume"
);
if
(
self
.
enabled
)
{
[
self
.
locationManager
stopMonitoringSignificantLocationChanges
];
if
(
enabled
)
{
[
locationManager
stopMonitoringSignificantLocationChanges
];
[
locationManager
stopUpdatingLocation
];
}
// When coming back-to-life, flush the background queue.
if
([
self
.
locationCache
count
]
>
0
){
if
([
locationCache
count
]
>
0
){
[
self
sync
];
}
}
...
...
@@ -93,10 +122,11 @@
// The omitted code should determine whether to reject the location update for being too
// old, too close to the previous one, too inaccurate and so forth according to your own
// application design.
[
self
.
locationCache
addObjectsFromArray
:
locations
];
[
locationCache
addObjectsFromArray
:
locations
];
[
self
sync
];
}
/**
* We are running in the background if this is being executed.
* We can't assume normal network access.
...
...
@@ -104,87 +134,111 @@
*/
-
(
void
)
sync
{
NSLog
(
@"BackgroundGeoLocation sync"
);
NSLog
(
@"- CDVBackgroundGeoLocation sync"
);
// Some voodoo.
// Note that the expiration handler block simply ends the task. It is important that we always
// end tasks that we have started.
UIBackgroundTaskIdentifier
bgTask
=
0
;
UIApplication
*
app
=
[
UIApplication
sharedApplication
];
// Some voodoo.
bgTask
=
[
app
beginBackgroundTaskWithExpirationHandler
:
^
{
[
app
endBackgroundTask
:
bgTask
];
}];
// Prepare a reusable Request instance. We'll reuse it each time we iterate the queue below.
NSMutableURLRequest
*
request
=
[
NSMutableURLRequest
requestWithURL
:[
NSURL
URLWithString
:
self
.
url
]
cachePolicy:
NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:
10
.
0
];
[
request
setHTTPMethod
:
@"POST"
];
[
request
setValue
:
@"application/json"
forHTTPHeaderField
:
@"Accept"
];
[
request
setValue
:
@"application/json"
forHTTPHeaderField
:
@"Content-Type"
];
// The list of successfully recorded locations on server.
NSMutableArray
*
recordedLocations
=
[
NSMutableArray
array
];
// Iterate the queue.
CLLocation
*
location
;
for
(
location
in
self
.
locationCache
)
{
// Build the json-data.
NSString
*
lat
=
[
NSString
stringWithFormat
:
@"%f"
,
location
.
coordinate
.
latitude
];
NSString
*
lng
=
[
NSString
stringWithFormat
:
@"%f"
,
location
.
coordinate
.
longitude
];
NSMutableDictionary
*
params
=
[
NSMutableDictionary
dictionary
];
NSMutableDictionary
*
data
=
[
NSMutableDictionary
dictionary
];
[
params
setValue
:
self
.
token
forKey
:
@"auth_token"
];
[
params
setValue
:
@"true"
forKey
:
@"background_geolocation"
];
[
data
setValue
:
lat
forKey
:
@"latitude"
];
[
data
setValue
:
lng
forKey
:
@"longitude"
];
[
data
setValue
:
[
location
.
timestamp
descriptionWithLocale
:[
NSLocale
systemLocale
]]
forKey
:
@"recorded_at"
];
[
params
setObject
:
data
forKey
:
@"location"
];
NSString
*
json
=
[
params
JSONString
];
NSData
*
requestData
=
[
NSData
dataWithBytes
:[
json
UTF8String
]
length
:[
json
length
]];
[
request
setHTTPBody
:
requestData
];
// Synchronous HTTP request
NSHTTPURLResponse
*
urlResponse
=
nil
;
NSError
*
error
=
[[
NSError
alloc
]
init
];
[
NSURLConnection
sendSynchronousRequest
:
request
returningResponse
:
&
urlResponse
error
:&
error
];
if
([
urlResponse
statusCode
]
==
200
)
{
// Yeehaw!
NSLog
(
@"BackgroundGeoLocation HTTP SUCCESS"
);
[
recordedLocations
addObject
:
location
];
}
else
{
// If any HTTP request fails, break out of emptying queue and try again later.
NSLog
(
@"BackgroundGeoLocation HTTP FAILED"
);
break
;
}
}
// Remove our successfully recorded locations from cache.
[
self
.
locationCache
removeObjectsInArray
:
recordedLocations
];
bgTask
=
[
app
beginBackgroundTaskWithExpirationHandler
:
^
{
[
app
endBackgroundTask
:
bgTask
];
}];
// Fetch last recorded location
CLLocation
*
location
=
[
locationCache
lastObject
];
// Build a resultset for javascript callback.
CDVPluginResult
*
result
=
nil
;
NSMutableDictionary
*
returnInfo
=
[
NSMutableDictionary
dictionaryWithCapacity
:
8
];
NSNumber
*
timestamp
=
[
NSNumber
numberWithDouble
:([
location
.
timestamp
timeIntervalSince1970
]
*
1000
)];
[
returnInfo
setObject
:
timestamp
forKey
:
@"timestamp"
];
[
returnInfo
setObject
:[
NSNumber
numberWithDouble
:
location
.
speed
]
forKey
:
@"velocity"
];
[
returnInfo
setObject
:[
NSNumber
numberWithDouble
:
location
.
verticalAccuracy
]
forKey
:
@"altitudeAccuracy"
];
[
returnInfo
setObject
:[
NSNumber
numberWithDouble
:
location
.
horizontalAccuracy
]
forKey
:
@"accuracy"
];
[
returnInfo
setObject
:[
NSNumber
numberWithDouble
:
location
.
course
]
forKey
:
@"heading"
];
[
returnInfo
setObject
:[
NSNumber
numberWithDouble
:
location
.
altitude
]
forKey
:
@"altitude"
];
[
returnInfo
setObject
:[
NSNumber
numberWithDouble
:
location
.
coordinate
.
latitude
]
forKey
:
@"latitude"
];
[
returnInfo
setObject
:[
NSNumber
numberWithDouble
:
location
.
coordinate
.
longitude
]
forKey
:
@"longitude"
];
result
=
[
CDVPluginResult
resultWithStatus
:
CDVCommandStatus_OK
messageAsDictionary
:
returnInfo
];
[
result
setKeepCallbackAsBool
:
YES
];
// Inform javascript a background-fetch event has occurred.
[
self
.
commandDelegate
sendPluginResult
:
result
callbackId
:
syncCallbackId
];
}
-
(
void
)
finish
:(
CDVInvokedUrlCommand
*
)
command
{
NSLog
(
@"CDVBackgroundGeoLocation finish"
);
//_completionHandler(UIBackgroundFetchResultNewData);
// Finish the voodoo.
if
(
bgTask
!=
UIBackgroundTaskInvalid
)
{
[
app
endBackgroundTask
:
bgTask
];
[
[
UIApplication
sharedApplication
]
endBackgroundTask
:
bgTask
];
bgTask
=
UIBackgroundTaskInvalid
;
}
}
/**
* Called when user exits their stationary radius (ie: they walked ~50m away from their last recorded location.
* - turn on more aggressive location monitoring.
*/
-
(
void
)
locationManager
:(
CLLocationManager
*
)
manager
didExitRegion
:(
CLRegion
*
)
region
{
NSLog
(
@"- CDVBackgroundGeoLocation exit region"
);
if
(
myRegion
!=
nil
)
{
[
locationManager
stopMonitoringSignificantLocationChanges
];
[
locationManager
stopMonitoringForRegion
:
myRegion
];
[
locationManager
startUpdatingLocation
];
myRegion
=
nil
;
}
}
/**
* 1. turn off std location services
* 2. turn on significantChanges API
* 3. create a region and start monitoring exits.
* 4. clear locationCache
*/
-
(
void
)
locationManagerDidPauseLocationUpdates
:(
CLLocationManager
*
)
manager
{
NSLog
(
@"- CDVBackgroundGeoLocation paused location updates"
);
[
locationManager
stopUpdatingLocation
];
[
locationManager
startMonitoringSignificantLocationChanges
];
myRegion
=
[
self
createStationaryRegion
];
[
manager
startMonitoringForRegion
:
myRegion
];
}
/**
* 1. Turn off significantChanges ApI
* 2. turn on std. location services
* 3. nullify myRegion
*/
-
(
void
)
locationManagerDidResumeLocationUpdates
:(
CLLocationManager
*
)
manager
{
NSLog
(
@"- CDVBackgroundGeoLocation resume location updates"
);
[
locationManager
stopMonitoringSignificantLocationChanges
];
[
locationManager
startUpdatingLocation
];
}
-
(
CLCircularRegion
*
)
createStationaryRegion
{
CLCircularRegion
*
region
=
[[
CLCircularRegion
alloc
]
initWithCenter
:
[[
locationManager
location
]
coordinate
]
radius
:
stationaryRadius
identifier
:
@"BackgroundGeoLocation stationary region"
];
region
.
notifyOnExit
=
YES
;
return
region
;
}
// If you don't stopMonitorying when application terminates, the app will be awoken still when a
// new location arrives, essentially monitoring the user's location even when they've killed the app.
// Might be desirable in certain apps.
-
(
void
)
applicationWillTerminate
:(
UIApplication
*
)
application
{
[
self
.
locationManager
stopMonitoringSignificantLocationChanges
];
[
locationManager
stopMonitoringSignificantLocationChanges
];
[
locationManager
stopUpdatingLocation
];
if
(
myRegion
!=
nil
)
{
[
locationManager
stopMonitoringForRegion
:
myRegion
];
}
}
-
(
void
)
dealloc
{
self
.
locationManager
.
delegate
=
nil
;
locationManager
.
delegate
=
nil
;
}
@end
www/BackgroundGeoLocation.js
View file @
eb0d6d80
...
...
@@ -28,11 +28,15 @@ module.exports = {
if
(
!
config
.
auth_token
||
!
config
.
url
)
{
console
.
log
(
"
BackgroundGeoLocation requires an auth_token and url to report to the server
"
);
}
var
stationaryRadius
=
config
.
stationaryRadius
||
50
,
// meters
distanceFilter
=
config
.
distanceFilter
||
500
,
// meters
locationTimeout
=
config
.
locationTimeout
||
60
;
// seconds
exec
(
success
||
function
()
{},
failure
||
function
()
{},
'
BackgroundGeoLocation
'
,
'
configure
'
,
[
config
.
auth_token
,
config
.
url
]);
[
config
.
auth_token
,
config
.
url
,
stationaryRadius
,
distanceFilter
,
locationTimeout
]);
},
start
:
function
(
success
,
failure
,
config
)
{
exec
(
success
||
function
()
{},
...
...
@@ -54,6 +58,14 @@ module.exports = {
'
BackgroundGeoLocation
'
,
'
test
'
,
[]);
},
finish
:
function
(
success
,
failure
)
{
exec
(
success
||
function
()
{},
failure
||
function
()
{},
'
BackgroundGeoLocation
'
,
'
finish
'
,
[]);
}
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment