mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 04:41:36 +08:00
BCL: location updates according to API feedback
This commit is contained in:
@ -1,9 +1,13 @@
|
|||||||
import types = require("Location/location_types");
|
import types = require("Location/location_types");
|
||||||
import app_module = require("Application/application");
|
import app_module = require("Application/application");
|
||||||
|
|
||||||
|
// merge types
|
||||||
|
declare var exports;
|
||||||
|
exports.Location = types.Location;
|
||||||
|
exports.Accuracy = types.Accuracy;
|
||||||
|
|
||||||
export class LocationManager {
|
export class LocationManager {
|
||||||
// in meters
|
// in meters
|
||||||
// we might need some predefined values here like 'any' and 'high'
|
|
||||||
public desiredAccuracy: number;
|
public desiredAccuracy: number;
|
||||||
|
|
||||||
// The minimum distance (measured in meters) a device must move horizontally before an update event is generated.
|
// The minimum distance (measured in meters) a device must move horizontally before an update event is generated.
|
||||||
@ -15,7 +19,7 @@ export class LocationManager {
|
|||||||
public isStarted: boolean;
|
public isStarted: boolean;
|
||||||
private androidLocationManager: any;
|
private androidLocationManager: any;
|
||||||
|
|
||||||
private _locationListener: any;
|
private locationListener: any;
|
||||||
|
|
||||||
private static locationFromAndroidLocation(androidLocation: android.location.Location): types.Location {
|
private static locationFromAndroidLocation(androidLocation: android.location.Location): types.Location {
|
||||||
var location = new types.Location();
|
var location = new types.Location();
|
||||||
@ -27,7 +31,7 @@ export class LocationManager {
|
|||||||
location.speed = androidLocation.getSpeed();
|
location.speed = androidLocation.getSpeed();
|
||||||
location.direction = androidLocation.getBearing();
|
location.direction = androidLocation.getBearing();
|
||||||
location.timestamp = new Date(androidLocation.getTime());
|
location.timestamp = new Date(androidLocation.getTime());
|
||||||
location.androidNative = androidLocation;
|
location.android = androidLocation;
|
||||||
//console.dump(location);
|
//console.dump(location);
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
@ -53,42 +57,42 @@ export class LocationManager {
|
|||||||
return androidLocation;
|
return androidLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static isLocationEnabled(): boolean {
|
public static isEnabled(): boolean {
|
||||||
var criteria = new android.location.Criteria();
|
var criteria = new android.location.Criteria();
|
||||||
criteria.setAccuracy(1); // low ? fine ? who knows what 1 means (bug in android docs?)
|
criteria.setAccuracy(1); // low ? fine ? who knows what 1 means (bug in android docs?)
|
||||||
var lm = app_module.Application.current.android.context.getSystemService('location');
|
var lm = app_module.Application.current.android.context.getSystemService(android.content.Context.LOCATION_SERVICE);
|
||||||
return (lm.getBestProvider(criteria, true) != null) ? true : false;
|
return (lm.getBestProvider(criteria, true) != null) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static distanceInMeters(loc1: types.Location, loc2: types.Location): number {
|
public static distance(loc1: types.Location, loc2: types.Location): number {
|
||||||
if (!loc1.androidNative) {
|
if (!loc1.android) {
|
||||||
loc1.androidNative = LocationManager.androidLocationFromLocation(loc1);
|
loc1.android = LocationManager.androidLocationFromLocation(loc1);
|
||||||
}
|
}
|
||||||
if (!loc2.androidNative) {
|
if (!loc2.android) {
|
||||||
loc2.androidNative = LocationManager.androidLocationFromLocation(loc2);
|
loc2.android = LocationManager.androidLocationFromLocation(loc2);
|
||||||
}
|
}
|
||||||
return loc1.androidNative.distanceTo(loc2.androidNative);
|
return loc1.android.distanceTo(loc2.android);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// put some defaults
|
// put some defaults
|
||||||
this.desiredAccuracy = types.DesiredAccuracy.HIGH;
|
this.desiredAccuracy = types.Accuracy.HIGH;
|
||||||
this.updateDistance = 0;
|
this.updateDistance = 0;
|
||||||
this.minimumUpdateTime = 200;
|
this.minimumUpdateTime = 200;
|
||||||
this.isStarted = false;
|
this.isStarted = false;
|
||||||
|
|
||||||
this.androidLocationManager = app_module.Application.current.android.context.getSystemService('location');
|
this.androidLocationManager = app_module.Application.current.android.context.getSystemService(android.content.Context.LOCATION_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// monitoring
|
// monitoring
|
||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
||||||
public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: Error) => any) {
|
public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: Error) => any, options?: types.Options) {
|
||||||
if (!this.isStarted) {
|
if (!this.isStarted) {
|
||||||
var criteria = new android.location.Criteria();
|
var criteria = new android.location.Criteria();
|
||||||
criteria.setAccuracy((this.desiredAccuracy === types.DesiredAccuracy.HIGH) ? 1 : 2);
|
criteria.setAccuracy((this.desiredAccuracy === types.Accuracy.HIGH) ? 1 : 2);
|
||||||
this._locationListener = <any>new android.location.LocationListener({
|
this.locationListener = <any>new android.location.LocationListener({
|
||||||
onLocationChanged: function (location: android.location.Location) {
|
onLocationChanged: function (location: android.location.Location) {
|
||||||
if (this._onLocation) {
|
if (this._onLocation) {
|
||||||
this._onLocation(LocationManager.locationFromAndroidLocation(location));
|
this._onLocation(LocationManager.locationFromAndroidLocation(location));
|
||||||
@ -104,10 +108,20 @@ export class LocationManager {
|
|||||||
onStatusChanged: function (arg1: string, arg2: number, arg3: android.os.Bundle): void {
|
onStatusChanged: function (arg1: string, arg2: number, arg3: android.os.Bundle): void {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._locationListener._onLocation = onLocation;
|
|
||||||
this._locationListener._onError = onError;
|
if (options) {
|
||||||
|
if (options.desiredAccuracy)
|
||||||
|
this.desiredAccuracy = options.desiredAccuracy;
|
||||||
|
if (options.updateDistance)
|
||||||
|
this.updateDistance = options.updateDistance;
|
||||||
|
if (options.minimumUpdateTime)
|
||||||
|
this.minimumUpdateTime = options.minimumUpdateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.locationListener._onLocation = onLocation;
|
||||||
|
this.locationListener._onError = onError;
|
||||||
try {
|
try {
|
||||||
this.androidLocationManager.requestLocationUpdates(long(this.minimumUpdateTime), float(this.updateDistance), criteria, this._locationListener, null);
|
this.androidLocationManager.requestLocationUpdates(long(this.minimumUpdateTime), float(this.updateDistance), criteria, this.locationListener, null);
|
||||||
this.isStarted = true;
|
this.isStarted = true;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
@ -124,7 +138,7 @@ export class LocationManager {
|
|||||||
|
|
||||||
public stopLocationMonitoring() {
|
public stopLocationMonitoring() {
|
||||||
if (this.isStarted) {
|
if (this.isStarted) {
|
||||||
this.androidLocationManager.removeUpdates(this._locationListener);
|
this.androidLocationManager.removeUpdates(this.locationListener);
|
||||||
this.isStarted = false;
|
this.isStarted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,9 +147,9 @@ export class LocationManager {
|
|||||||
// other
|
// other
|
||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
||||||
public getLastKnownLocation(): types.Location {
|
get lastKnownLocation(): types.Location {
|
||||||
var criteria = new android.location.Criteria();
|
var criteria = new android.location.Criteria();
|
||||||
criteria.setAccuracy((this.desiredAccuracy === types.DesiredAccuracy.HIGH) ? 1 : 2);
|
criteria.setAccuracy((this.desiredAccuracy === types.Accuracy.HIGH) ? 1 : 2);
|
||||||
try {
|
try {
|
||||||
var providers = this.androidLocationManager.getProviders(criteria, false);
|
var providers = this.androidLocationManager.getProviders(criteria, false);
|
||||||
var it = providers.iterator();
|
var it = providers.iterator();
|
||||||
|
54
Location/location.d.ts
vendored
54
Location/location.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
export declare enum DesiredAccuracy {
|
export declare enum Accuracy {
|
||||||
// in meters
|
// in meters
|
||||||
ANY,
|
ANY,
|
||||||
HIGH,
|
HIGH,
|
||||||
@ -26,26 +26,11 @@ export declare class Location {
|
|||||||
|
|
||||||
timestamp: Date;
|
timestamp: Date;
|
||||||
|
|
||||||
public androidNative: any; // android Location
|
public android: any; // android Location
|
||||||
public iosNative: any; // iOS CLLocation
|
public ios: any; // iOS CLLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare class RegionChangeListener {
|
export declare class Options {
|
||||||
onRegionEnter(region: LocationRegion);
|
|
||||||
onRegionExit(region: LocationRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
export declare class LocationManager {
|
|
||||||
/**
|
|
||||||
* Report are location services switched ON for this device (on Android) or application (iOS)
|
|
||||||
*/
|
|
||||||
static isLocationEnabled(): boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Measure distance in meters between two locations
|
|
||||||
*/
|
|
||||||
static distanceInMeters(loc1: Location, loc2: Location): number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies desired accuracy in meters. Defaults to DesiredAccuracy.HIGH
|
* Specifies desired accuracy in meters. Defaults to DesiredAccuracy.HIGH
|
||||||
*/
|
*/
|
||||||
@ -60,6 +45,33 @@ export declare class LocationManager {
|
|||||||
* Minimum time interval between location updates, in milliseconds (android only)
|
* Minimum time interval between location updates, in milliseconds (android only)
|
||||||
*/
|
*/
|
||||||
minimumUpdateTime: number;
|
minimumUpdateTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class LocationManager {
|
||||||
|
/**
|
||||||
|
* Report are location services switched ON for this device (on Android) or application (iOS)
|
||||||
|
*/
|
||||||
|
static isEnabled(): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Measure distance in meters between two locations
|
||||||
|
*/
|
||||||
|
static distance(loc1: Location, loc2: Location): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies desired accuracy in meters. Defaults to DesiredAccuracy.HIGH
|
||||||
|
*/
|
||||||
|
desiredAccuracy: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update distance filter in meters. Specifies how often to update. Default on iOS is no filter, on Android it is 0 meters
|
||||||
|
*/
|
||||||
|
updateDistance: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum time interval between location updates, in milliseconds (ignored on iOS)
|
||||||
|
*/
|
||||||
|
minimumUpdateTime: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if location listener is already started. In this case all other start requests will be ignored
|
* True if location listener is already started. In this case all other start requests will be ignored
|
||||||
@ -71,7 +83,7 @@ export declare class LocationManager {
|
|||||||
/**
|
/**
|
||||||
* Starts location monitoring.
|
* Starts location monitoring.
|
||||||
*/
|
*/
|
||||||
startLocationMonitoring(onLocation: (location: Location) => any, onError?: (error: Error) => any);
|
startLocationMonitoring(onLocation: (location: Location) => any, onError?: (error: Error) => any, options?: Options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops location monitoring
|
* Stops location monitoring
|
||||||
@ -83,5 +95,5 @@ export declare class LocationManager {
|
|||||||
/**
|
/**
|
||||||
* Returns last known location from device's location services or null of no known last location
|
* Returns last known location from device's location services or null of no known last location
|
||||||
*/
|
*/
|
||||||
getLastKnownLocation(): Location;
|
lastKnownLocation: Location;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
import types = require("Location/location_types");
|
|
||||||
|
import types = require("Location/location_types");
|
||||||
|
|
||||||
|
// merge types
|
||||||
|
declare var exports;
|
||||||
|
exports.Location = types.Location;
|
||||||
|
exports.Accuracy = types.Accuracy;
|
||||||
|
exports.Options = types.Options;
|
||||||
|
|
||||||
export class LocationManager {
|
export class LocationManager {
|
||||||
|
|
||||||
@ -24,7 +31,7 @@ export class LocationManager {
|
|||||||
location.speed = clLocation.speed;
|
location.speed = clLocation.speed;
|
||||||
location.direction = clLocation.course;
|
location.direction = clLocation.course;
|
||||||
location.timestamp = new Date(clLocation.timestamp.timeIntervalSince1970() * 1000);
|
location.timestamp = new Date(clLocation.timestamp.timeIntervalSince1970() * 1000);
|
||||||
location.iosNative = clLocation;
|
location.ios = clLocation;
|
||||||
//console.dump(location);
|
//console.dump(location);
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
@ -40,29 +47,34 @@ export class LocationManager {
|
|||||||
return iosLocation;
|
return iosLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static isLocationEnabled(): boolean {
|
public static isEnabled(): boolean {
|
||||||
return CoreLocation.CLLocationManager.locationServicesEnabled();
|
if (CoreLocation.CLLocationManager.locationServicesEnabled()) {
|
||||||
|
//return CoreLocation.CLLocationManager.authorizationStatus() === CoreLocation.CLAuthorizationStatus.kCLAuthorizationStatusAuthorized;
|
||||||
|
// FIXME: issue reported https://github.com/telerik/Kimera/issues/122
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static distanceInMeters(loc1: types.Location, loc2: types.Location): number {
|
public static distance(loc1: types.Location, loc2: types.Location): number {
|
||||||
if (!loc1.iosNative) {
|
if (!loc1.ios) {
|
||||||
loc1.iosNative = LocationManager.iosLocationFromLocation(loc1);
|
loc1.ios = LocationManager.iosLocationFromLocation(loc1);
|
||||||
}
|
}
|
||||||
if (!loc2.iosNative) {
|
if (!loc2.ios) {
|
||||||
loc2.iosNative = LocationManager.iosLocationFromLocation(loc2);
|
loc2.ios = LocationManager.iosLocationFromLocation(loc2);
|
||||||
}
|
}
|
||||||
return loc1.iosNative.distanceFromLocation(loc2.iosNative);
|
return loc1.ios.distanceFromLocation(loc2.ios);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.isStarted = false;
|
this.isStarted = false;
|
||||||
this.desiredAccuracy = types.DesiredAccuracy.HIGH;
|
this.desiredAccuracy = types.Accuracy.HIGH;
|
||||||
this.updateDistance = -1; // kCLDistanceFilterNone
|
this.updateDistance = -1; // kCLDistanceFilterNone
|
||||||
this.iosLocationManager = new CoreLocation.CLLocationManager();
|
this.iosLocationManager = new CoreLocation.CLLocationManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
// monitoring
|
// monitoring
|
||||||
public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: Error) => any) {
|
public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: Error) => any, options?: types.Options) {
|
||||||
if (!this.isStarted) {
|
if (!this.isStarted) {
|
||||||
var LocationListener = Foundation.NSObject.extends({
|
var LocationListener = Foundation.NSObject.extends({
|
||||||
setupWithFunctions: function (onLocation, onError) {
|
setupWithFunctions: function (onLocation, onError) {
|
||||||
@ -91,12 +103,20 @@ export class LocationManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
if (options.desiredAccuracy)
|
||||||
|
this.desiredAccuracy = options.desiredAccuracy;
|
||||||
|
if (options.updateDistance)
|
||||||
|
this.updateDistance = options.updateDistance;
|
||||||
|
}
|
||||||
|
|
||||||
this.listener = new LocationListener();
|
this.listener = new LocationListener();
|
||||||
this.listener.setupWithFunctions(onLocation, onError);
|
this.listener.setupWithFunctions(onLocation, onError);
|
||||||
this.iosLocationManager.delegate = this.listener;
|
this.iosLocationManager.delegate = this.listener;
|
||||||
this.iosLocationManager.desiredAccuracy = this.desiredAccuracy;
|
this.iosLocationManager.desiredAccuracy = this.desiredAccuracy;
|
||||||
this.iosLocationManager.distanceFilter = this.updateDistance;
|
this.iosLocationManager.distanceFilter = this.updateDistance;
|
||||||
this.iosLocationManager.startUpdatingLocation();
|
this.iosLocationManager.startUpdatingLocation();
|
||||||
|
this.isStarted = true;
|
||||||
}
|
}
|
||||||
else if (onError) {
|
else if (onError) {
|
||||||
onError(new Error('location monitoring already started'));
|
onError(new Error('location monitoring already started'));
|
||||||
@ -106,13 +126,15 @@ export class LocationManager {
|
|||||||
public stopLocationMonitoring() {
|
public stopLocationMonitoring() {
|
||||||
if (this.isStarted) {
|
if (this.isStarted) {
|
||||||
this.iosLocationManager.stopUpdatingLocation();
|
this.iosLocationManager.stopUpdatingLocation();
|
||||||
|
this.iosLocationManager.delegate = null;
|
||||||
|
this.listener = null;
|
||||||
this.isStarted = false;
|
this.isStarted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// other
|
// other
|
||||||
|
|
||||||
public getLastKnownLocation(): types.Location {
|
get lastKnownLocation(): types.Location {
|
||||||
var clLocation = this.iosLocationManager.location;
|
var clLocation = this.iosLocationManager.location;
|
||||||
if (null != clLocation) {
|
if (null != clLocation) {
|
||||||
return LocationManager.locationFromCLLocation(clLocation);
|
return LocationManager.locationFromCLLocation(clLocation);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export enum DesiredAccuracy {
|
export enum Accuracy {
|
||||||
// in meters
|
// in meters
|
||||||
ANY = 300,
|
ANY = 300,
|
||||||
HIGH = 3,
|
HIGH = 3,
|
||||||
@ -19,8 +19,25 @@ export class Location {
|
|||||||
|
|
||||||
public timestamp: Date;
|
public timestamp: Date;
|
||||||
|
|
||||||
public androidNative: any; // android Location
|
public android: any; // android Location
|
||||||
public iosNative: any; // iOS native location
|
public ios: any; // iOS native location
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Options {
|
||||||
|
/**
|
||||||
|
* Specifies desired accuracy in meters. Defaults to DesiredAccuracy.HIGH
|
||||||
|
*/
|
||||||
|
public desiredAccuracy: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update distance filter in meters. Specifies how often to update. Default on iOS is no filter, on Android it is 0 meters
|
||||||
|
*/
|
||||||
|
public updateDistance: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum time interval between location updates, in milliseconds (ignored on iOS)
|
||||||
|
*/
|
||||||
|
public minimumUpdateTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LocationRegion {
|
export class LocationRegion {
|
||||||
@ -29,11 +46,3 @@ export class LocationRegion {
|
|||||||
|
|
||||||
public raduis: number; // radius in meters
|
public raduis: number; // radius in meters
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This might be implemented with two callbacks, no need of special type.
|
|
||||||
export class RegionChangeListener {
|
|
||||||
onRegionEnter(region: LocationRegion) {
|
|
||||||
}
|
|
||||||
onRegionExit(region: LocationRegion) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user