Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 71fe85f

Browse files
author
Dimitar Tachev
authored
Merge pull request #72 from NativeScript/tachev/location-manager-to-google-play-services
Replaced the Android implementation with the recommended one.
2 parents 5605e79 + 3c350f4 commit 71fe85f

File tree

18 files changed

+466
-442
lines changed

18 files changed

+466
-442
lines changed

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ geolocation.enableLocationRequest();
4545

4646
````
4747
// Get current location with high accuracy
48-
geolocation.getCurrentLocation({ desiredAccuracy: Accuracy.high, updateDistance: 0.1, maximumAge: 5000, timeout: 20000 })
48+
geolocation.getCurrentLocation({ desiredAccuracy: Accuracy.high, maximumAge: 5000, timeout: 20000 })
4949
````
5050

5151
## API
@@ -69,10 +69,11 @@ geolocation.getCurrentLocation({ desiredAccuracy: Accuracy.high, updateDistance:
6969
| Property | Default | Description |
7070
| --- | --- | --- |
7171
| desiredAccuracy? | Accuracy.high | Specifies desired accuracy in meters. |
72-
| updateDistance | iOS - no filter, Android - 0 meters | Update distance filter in meters. Specifies how often to update the location. |
73-
| minimumUpdateTime | - | Minimum time interval between location updates, in milliseconds (ignored on iOS). |
72+
| updateDistance | iOS - no filter | Update distance filter in meters. Specifies how often to update the location (ignored on Android). |
73+
| updateTime | 1 minute | Interval between location updates, in milliseconds (ignored on iOS). |
74+
| minimumUpdateTime | 5 secs | Minimum time interval between location updates, in milliseconds (ignored on iOS). |
7475
| maximumAge | - | How old locations to receive in ms. |
75-
| timeout | - | How long to wait for a location in ms. |
76+
| timeout | 5 minutes | How long to wait for a location in ms. |
7677

7778
### Methods
7879

@@ -81,8 +82,8 @@ geolocation.getCurrentLocation({ desiredAccuracy: Accuracy.high, updateDistance:
8182
| getCurrentLocation(options: Options) | Promise<Location> | Get current location applying the specified options (if any). |
8283
| watchLocation(successCallback: successCallbackType, errorCallback: errorCallbackType, options: Options) | number | Monitor for location change. |
8384
| clearWatch(watchId: number) | void | Stop monitoring for location change. Parameter expected is the watchId returned from `watchLocation`. |
84-
| enableLocationRequest(always?: boolean) | Promise<void> | Ask for permissions to use location services. The option `always` is application for iOS only. [Read more about its usage](https://developer.apple.com/documentation/corelocation/cllocationmanager/1620551-requestalwaysauthorization) . |
85-
| isEnabled | boolean| Returns `true` if location services are enabled. |
85+
| enableLocationRequest(always?: boolean) | Promise\<void\> | Ask for permissions to use location services. The option `always` is application for iOS only. [Read more about its usage](https://developer.apple.com/documentation/corelocation/cllocationmanager/1620551-requestalwaysauthorization) . |
86+
| isEnabled | Promise\<boolean\>| Resolves `true` or `false` based on the location services availability. |
8687
| distance(loc1: Location, loc2: Location) | number | Calculate the distance between two locations. Returns the distance in meters. |
8788

8889
## License

demo/.cloud/Build.zip

1.98 MB
Binary file not shown.

demo/app/App_Resources/Android/app.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ android {
1414
additionalParameters "--no-version-vectors"
1515
}
1616
}
17+
18+
def settingsGradlePath = "$projectDir/../../app/App_Resources/Android/settings.gradle";
19+
def settingsGradleFile = new File(settingsGradlePath);
20+
if(settingsGradleFile.exists())
21+
{
22+
apply from: settingsGradleFile;
23+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import groovy.json.JsonSlurper
2+
3+
task replaceSettings {
4+
description "Replaces configuration settings."
5+
def jsonSlurper = new JsonSlurper();
6+
def pathToSettingsJson = "$projectDir/../../app/App_Resources/Android/settings.json";
7+
def settingsJsonFile = file(pathToSettingsJson);
8+
def settingsResolvedPath = settingsJsonFile.getAbsolutePath();
9+
10+
if(settingsJsonFile.exists())
11+
{
12+
println "\t Applying settings from $settingsResolvedPath"
13+
String settingsGradleTemplate = """android {
14+
defaultConfig {
15+
applicationId = "__appId__"
16+
17+
if (__minSdkVersion__) {
18+
minSdkVersion = __minSdkVersion__
19+
}
20+
21+
if (__targetSdkVersion__) {
22+
targetSdkVersion = __targetSdkVersion__
23+
}
24+
}
25+
}"""
26+
27+
def settingsJsonContent = settingsJsonFile.getText("UTF-8");
28+
def settingsMap = jsonSlurper.parseText(settingsJsonContent);
29+
30+
for ( setting in settingsMap ) {
31+
def placeholder = "__${setting.key}__";
32+
def settingValue = setting.value;
33+
34+
if (settingValue == null) {
35+
settingValue = false
36+
}
37+
38+
settingsGradleTemplate = settingsGradleTemplate.replaceAll( placeholder, settingValue as String);
39+
}
40+
41+
new File( './temp_setting.gradle' ).write( settingsGradleTemplate, 'UTF-8');
42+
apply from: './temp_setting.gradle';
43+
}
44+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"appId":"org.nativescript.demo","minSdkVersion":null,"targetSdkVersion":null}

demo/app/main-page.ts

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,68 @@ import { MainViewModel } from "./main-view-model";
66

77
let page: Page;
88
let model = new MainViewModel();
9-
let watchId;
9+
let watchIds = [];
1010

1111
export function pageLoaded(args: EventData) {
1212
page = <Page>args.object;
1313
page.bindingContext = model;
1414
}
1515

1616
export function enableLocationTap() {
17-
if (!geolocation.isEnabled()) {
18-
geolocation.enableLocationRequest();
19-
}
17+
geolocation.isEnabled().then(function (isEnabled) {
18+
if (!isEnabled) {
19+
geolocation.enableLocationRequest().then(function () {
20+
}, function (e) {
21+
console.log("Error: " + (e.message || e));
22+
});
23+
}
24+
}, function (e) {
25+
console.log("Error: " + (e.message || e));
26+
});
2027
}
2128

2229
export function buttonGetLocationTap() {
23-
let location = geolocation.getCurrentLocation({ desiredAccuracy: Accuracy.high, updateDistance: 0.1, maximumAge: 5000, timeout: 20000 })
24-
.then(function(loc) {
30+
let location = geolocation.getCurrentLocation({
31+
desiredAccuracy: Accuracy.high,
32+
maximumAge: 5000,
33+
timeout: 10000
34+
})
35+
.then(function (loc) {
2536
if (loc) {
2637
model.locations.push(loc);
2738
}
28-
}, function(e) {
29-
console.log("Error: " + e.message);
39+
}, function (e) {
40+
console.log("Error: " + (e.message || e));
3041
});
3142
}
3243

3344
export function buttonStartTap() {
34-
watchId = geolocation.watchLocation(
35-
function(loc) {
36-
if (loc) {
37-
model.locations.push(loc);
38-
}
39-
},
40-
function(e) {
41-
console.log("Error: " + e.message);
42-
},
43-
{ desiredAccuracy: Accuracy.high, updateDistance: 0.1, minimumUpdateTime: 100 });
45+
try {
46+
watchIds.push(geolocation.watchLocation(
47+
function (loc) {
48+
if (loc) {
49+
model.locations.push(loc);
50+
}
51+
},
52+
function (e) {
53+
console.log("Error: " + e.message);
54+
},
55+
{
56+
desiredAccuracy: Accuracy.high,
57+
updateDistance: 0.1,
58+
updateTime: 3000,
59+
minimumUpdateTime: 100
60+
}));
61+
} catch (ex) {
62+
console.log("Error: " + ex.message);
63+
}
4464
}
4565

4666
export function buttonStopTap() {
47-
if (watchId) {
67+
let watchId = watchIds.pop();
68+
while (watchId != null) {
4869
geolocation.clearWatch(watchId);
70+
watchId = watchIds.pop();
4971
}
5072
}
5173

demo/app/tests/mock-android.js

Lines changed: 42 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,51 @@ Object.defineProperty(exports, "__esModule", {
22
value: true
33
});
44

5-
var MockLocationManager = (function () {
6-
function MockLocationManager() {
7-
this.MOCK_PROVIDER_NAME = "mockLocationProvider";
8-
}
9-
MockLocationManager.prototype._lastKnownLocation = null;
10-
MockLocationManager.prototype.requestSingleUpdate = function (options, locListener, looper) {
11-
var newLocation = new android.location.Location(this.MOCK_PROVIDER_NAME);
12-
newLocation.setLatitude(this._getRandomCoordinate());
13-
newLocation.setLongitude(this._getRandomCoordinate());
14-
newLocation.setTime((new Date()).getTime());
15-
newLocation.setAccuracy(500);
5+
var geoLocation = require("nativescript-geolocation");
6+
var MockLocationManager = {
7+
};
8+
MockLocationManager.intervalId = null;
9+
MockLocationManager._lastKnownLocation = null;
10+
MockLocationManager._getRandomCoordinate = function () {
11+
var min = -180;
12+
var max = 180;
13+
return Math.floor(Math.random() * (max - min + 1) + min);
14+
};
15+
MockLocationManager.getNewLocation = function () {
16+
var newLocation = new android.location.Location("mockLocationProvider");
17+
var latitude = MockLocationManager._getRandomCoordinate();
18+
var longitude = MockLocationManager._getRandomCoordinate();
19+
newLocation.setLatitude(latitude);
20+
newLocation.setLongitude(longitude);
21+
newLocation.setTime((new Date()).getTime());
22+
newLocation.setAccuracy(500);
1623

17-
MockLocationManager.prototype._lastKnownLocation = newLocation;
24+
return newLocation;
25+
};
26+
MockLocationManager.getLastLocation = function (maximumAge, resolve, reject) {
27+
var lastLocation = MockLocationManager._lastKnownLocation ?
28+
new geoLocation.Location(MockLocationManager._lastKnownLocation) : null;
1829

19-
locListener.onLocationChanged(newLocation);
20-
};
21-
MockLocationManager.prototype.getProviders = function (criteria, enabledOnly) {
22-
var providers = [this.MOCK_PROVIDER_NAME];
23-
providers.index = 0;
24-
providers.size = function () {
25-
return providers.length;
26-
};
27-
providers.iterator = function () {
28-
return {
29-
hasNext: function () {
30-
return providers.index < providers.length;
31-
},
32-
next: function () {
33-
var next = providers[providers.index];
34-
providers.index += 1;
35-
return next;
36-
}
37-
};
38-
}
39-
return providers;
40-
};
41-
MockLocationManager.prototype.removeUpdates = function (listener) {
42-
clearInterval(MockLocationManager.intervalId);
43-
};
44-
MockLocationManager.prototype.requestLocationUpdates = function (minTime, minDistance, criteria, listener, looper) {
45-
var _this = this;
46-
this.removeUpdates(null);
30+
resolve(lastLocation);
31+
};
32+
MockLocationManager.removeLocationUpdates = function (listener) {
33+
clearInterval(MockLocationManager.intervalId);
34+
};
35+
MockLocationManager.requestLocationUpdates = function (locationRequest, locationCallback) {
36+
MockLocationManager.removeLocationUpdates(null);
37+
setTimeout(() => {
4738
MockLocationManager.intervalId = setInterval(function () {
48-
return _this.requestSingleUpdate(null, listener, null);
39+
locationCallback.onLocationResult({
40+
getLastLocation: function () {
41+
MockLocationManager._lastKnownLocation = MockLocationManager.getNewLocation();
42+
return MockLocationManager._lastKnownLocation;
43+
}
44+
});
4945
}, 500);
50-
};
51-
MockLocationManager.prototype.getLastKnownLocation = function () {
52-
return MockLocationManager.prototype._lastKnownLocation;
53-
};
54-
MockLocationManager.prototype._getRandomCoordinate = function () {
55-
var min = -180;
56-
var max = 180;
57-
return Math.floor(Math.random() * (max - min + 1) + min);
58-
};
59-
return MockLocationManager;
60-
}());
46+
}, 50);
47+
};
48+
MockLocationManager.shouldSkipChecks = function () {
49+
return true;
50+
}
6151

6252
exports.MockLocationManager = MockLocationManager;

demo/app/tests/mock-ios.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,4 @@ function locationFromCLLocation(clLocation) {
7474
return location;
7575
};
7676

77-
exports.MockLocationManager = MockLocationManager;
77+
exports.MockLocationManager = new MockLocationManager();

demo/app/tests/tests.js

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,34 @@ var MockLocationManager = require(mockLocationManagerPath).MockLocationManager;
44

55
describe("location class", function () {
66
it("can be instantiated", function () {
7-
8-
var geolocation = require("nativescript-geolocation");
9-
var Location = geolocation.Location;
7+
var geoLocation = require("nativescript-geolocation");
8+
var Location = geoLocation.Location;
9+
var nativeLocation = null;
10+
if (MockLocationManager.getNewLocation) {
11+
nativeLocation = MockLocationManager.getNewLocation();
12+
}
1013

1114
expect(function () {
12-
return new Location();
15+
return new Location(nativeLocation);
1316
}).not.toThrow();
1417

15-
expect(new Location()).toBeDefined();
18+
expect(new Location(nativeLocation)).toBeDefined();
1619
});
1720
});
1821

1922
describe("geolocation", function () {
2023
beforeEach(function () {
2124
geolocation = require("nativescript-geolocation");
22-
geolocation.setCustomLocationManager(new MockLocationManager());
25+
geolocation.setCustomLocationManager(MockLocationManager);
2326
});
2427

2528
it("getCurrentLocation returns fresh location when timeout > 0", function (done) {
2629
var location = geolocation.getCurrentLocation({
27-
desiredAccuracy: Accuracy.high,
28-
updateDistance: 0.1,
29-
maximumAge: 5000,
30-
timeout: 20000
31-
})
30+
desiredAccuracy: Accuracy.high,
31+
updateDistance: 0.1,
32+
maximumAge: 5000,
33+
timeout: 20000
34+
})
3235
.then(function (loc) {
3336
expect(loc).toBeDefined();
3437
expect(180 > loc.latitude > -180).toBeTruthy();
@@ -39,6 +42,21 @@ describe("geolocation", function () {
3942
});
4043
});
4144

45+
it("getCurrentLocation returns timeout when timeout = 20", function (done) {
46+
var location = geolocation.getCurrentLocation({
47+
desiredAccuracy: Accuracy.high,
48+
updateDistance: 0.1,
49+
maximumAge: 5000,
50+
timeout: 20
51+
})
52+
.then(function (loc) {
53+
done.fail("Got location instead of timeout: " + loc);
54+
}, function (e) {
55+
expect(e.message).toEqual('Timeout while searching for location!');
56+
done();
57+
});
58+
});
59+
4260
it("getCurrentLocation returns last known location (if any) when timeout = 0", function (done) {
4361
var getCurrentLocation = function (timeout) {
4462
return geolocation.getCurrentLocation({

demo/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"version": "3.0.1"
66
},
77
"tns-android": {
8-
"version": "3.0.0"
8+
"version": "3.2.0"
99
}
1010
},
1111
"dependencies": {
@@ -29,9 +29,11 @@
2929
"lazy": "1.0.11",
3030
"nativescript-css-loader": "~0.26.0",
3131
"nativescript-dev-typescript": "libs",
32-
"nativescript-dev-webpack": "^0.7.3",
32+
"nativescript-dev-webpack": "0.8.0",
33+
"nativescript-worker-loader": "~0.8.1",
3334
"raw-loader": "~0.5.1",
3435
"resolve-url-loader": "~2.1.0",
36+
"tns-platform-declarations": "^3.2.0",
3537
"tslint": "~5.4.3",
3638
"typescript": "2.3.4",
3739
"webpack": "~3.2.0",

0 commit comments

Comments
 (0)