From 95916c52f8cafa01a35ee554ba8b971c3d3b89a8 Mon Sep 17 00:00:00 2001 From: Stanimir Karoserov Date: Thu, 17 Apr 2014 15:46:38 +0300 Subject: [PATCH] BCL: updated location to support distance measuring --- Location/Readme.md | 2 + Location/location.android.ts | 84 +++++++++++++++++++++++------------- Location/location.d.ts | 39 +++-------------- Location/location.ios.ts | 57 +++++++++++++++--------- Location/location_types.ts | 3 ++ declarations.ios.d.ts | 4 ++ net/http_client.android.ts | 2 +- 7 files changed, 105 insertions(+), 86 deletions(-) diff --git a/Location/Readme.md b/Location/Readme.md index 50c48df5c..c17243242 100644 --- a/Location/Readme.md +++ b/Location/Readme.md @@ -1,6 +1,8 @@ Initializing location: ``` +var LocationManager = require("Location").LocationManager; + console.log('is location enabled: ' + LocationManager.isLocationEnabled()); this.locationManager = new LocationManager(); diff --git a/Location/location.android.ts b/Location/location.android.ts index f495ff0a2..952e0a90b 100644 --- a/Location/location.android.ts +++ b/Location/location.android.ts @@ -17,6 +17,42 @@ export class LocationManager { private _locationListener: any; + private static locationFromAndroidLocation(androidLocation: android.location.Location): types.Location { + var location = new types.Location(); + location.latitude = androidLocation.getLatitude(); + location.longitude = androidLocation.getLongitude(); + location.altitude = androidLocation.getAltitude(); + location.horizontalAccuracy = androidLocation.getAccuracy(); + location.verticalAccuracy = androidLocation.getAccuracy(); + location.speed = androidLocation.getSpeed(); + location.direction = androidLocation.getBearing(); + location.timestamp = new Date(androidLocation.getTime()); + location.androidNative = androidLocation; + //console.dump(location); + return location; + } + + private static androidLocationFromLocation(location: types.Location): android.location.Location { + var androidLocation = new android.location.Location('custom'); + androidLocation.setLatitude(location.latitude); + androidLocation.setLongitude(location.longitude); + if (location.altitude) + androidLocation.setAltitude(location.altitude); + if (location.speed) + androidLocation.setSpeed(float(location.speed)); + if (location.direction) + androidLocation.setBearing(float(location.direction)); + if (location.timestamp) { + try { + androidLocation.setTime(long(location.timestamp.getTime())); + } + catch (e) { + console.error('invalid location timestamp'); + } + } + return androidLocation; + } + public static isLocationEnabled(): boolean { var criteria = new android.location.Criteria(); criteria.setAccuracy(1); // low ? fine ? who knows what 1 means (bug in android docs?) @@ -24,6 +60,16 @@ export class LocationManager { return (lm.getBestProvider(criteria, true) != null) ? true : false; } + public static distanceInMeters(loc1: types.Location, loc2: types.Location): number { + if (!loc1.androidNative) { + loc1.androidNative = LocationManager.androidLocationFromLocation(loc1); + } + if (!loc2.androidNative) { + loc2.androidNative = LocationManager.androidLocationFromLocation(loc2); + } + return loc1.androidNative.distanceTo(loc2.androidNative); + } + constructor() { // put some defaults this.desiredAccuracy = types.DesiredAccuracy.HIGH; @@ -34,37 +80,14 @@ export class LocationManager { this.androidLocationManager = app_module.Application.current.android.context.getSystemService('location'); } - private static locationFromAndroidLocation(androidLocation: android.location.Location): types.Location { - var location = new types.Location(); - location.latitude = androidLocation.getLatitude(); - location.longitude = androidLocation.getLongitude(); - location.altitude = androidLocation.getAltitude(); - location.horizontalAccuracy = androidLocation.getAccuracy(); - location.verticalAccuracy = androidLocation.getAccuracy(); - location.speed = androidLocation.getSpeed(); - location.direction = androidLocation.getBearing(); - location.timestamp = new Date(androidLocation.getTime()); - //console.dump(location); - return location; - } - + //////////////////////// // monitoring + //////////////////////// - public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: string) => any) { + public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: Error) => any) { if (!this.isStarted) { var criteria = new android.location.Criteria(); criteria.setAccuracy((this.desiredAccuracy === types.DesiredAccuracy.HIGH) ? 1 : 2); -/* // We could provide 'true' for the second parameter here and get only enabled providers. - // However this would exclude the case when user enables the provider later. - // Another option is to get the best provider, but then again, this would - // exclude all other providers matching our criteria - var providers = this.androidLocationManager.getProviders(criteria, false); - var it = providers.iterator(); - while (it.hasNext()) { - var element = it.next(); - console.log('found provider: ' + element); - this.androidLocationManager.requestLocationUpdates(element, 200, 10, this._locationListener); - }*/ this._locationListener = new android.location.LocationListener({ onLocationChanged: function (location: android.location.Location) { if (this._onLocation) { @@ -89,12 +112,12 @@ export class LocationManager { } catch (e) { if (onError) { - onError(e.message); + onError(e); } } } else if (onError) { - onError('location monitoring already started'); + onError(new Error('location monitoring already started')); } } @@ -106,7 +129,9 @@ export class LocationManager { } } + //////////////////////// // other + //////////////////////// public getLastKnownLocation(): types.Location { var criteria = new android.location.Criteria(); @@ -130,7 +155,4 @@ export class LocationManager { return null; } - public distanceInMeters(loc1: types.Location, loc2: types.Location): number { - return 0; - } } \ No newline at end of file diff --git a/Location/location.d.ts b/Location/location.d.ts index c79a99c96..3df9c336a 100644 --- a/Location/location.d.ts +++ b/Location/location.d.ts @@ -4,22 +4,6 @@ HIGH, } -export declare class LocationPoint { - public latitude: number; - public longitude: number; - - public altitude: number; - - public horizontalAccuracy: number; - public verticalAccuracy: number; - - public speed: number; // in m/s ? - - public direction: number; // in degrees - - public timestamp: any; -} - export declare class LocationRegion { public latitude: number; public longitude: number; @@ -41,11 +25,9 @@ export declare class Location { direction: number; // in degrees timestamp: Date; -} -export declare class LocationChangeListener { - onLocationChange(location: Location); - onLocationError(error: string); + public androidNative: any; // android Location + public iosNative: any; // iOS native location } export declare class RegionChangeListener { @@ -55,29 +37,18 @@ export declare class RegionChangeListener { export declare class LocationManager { static isLocationEnabled(): boolean; + static distanceInMeters(loc1: Location, loc2: Location): number; + desiredAccuracy: number; updateDistance: number; // minimum time interval between location updates, in milliseconds (android only) minimumUpdateTime: number; isStarted: boolean; - // listeners - locationChangeListener: LocationChangeListener; - /* regionChangeListener: RegionChangeListener; - - // regions - addRegion(region: LocationRegion); - - removeRegion(region: LocationRegion); - - clearRegions();*/ - // monitoring - - startLocationMonitoring(onLocation: (location: Location) => any, onError?: (error: string) => any); + startLocationMonitoring(onLocation: (location: Location) => any, onError?: (error: Error) => any); stopLocationMonitoring(); // other getLastKnownLocation(): Location; - distanceInMeters(loc1: Location, loc2: Location): number; } \ No newline at end of file diff --git a/Location/location.ios.ts b/Location/location.ios.ts index 71944fd58..483771747 100644 --- a/Location/location.ios.ts +++ b/Location/location.ios.ts @@ -12,17 +12,6 @@ export class LocationManager { public isStarted: boolean; private iosLocationManager: CoreLocation.CLLocationManager; - public static isLocationEnabled(): boolean { - return CoreLocation.CLLocationManager.locationServicesEnabled(); - } - - constructor() { - this.isStarted = false; - this.desiredAccuracy = types.DesiredAccuracy.HIGH; - this.updateDistance = -1; // kCLDistanceFilterNone - this.iosLocationManager = new CoreLocation.CLLocationManager(); - } - private static locationFromCLLocation(clLocation: CoreLocation.CLLocation): types.Location { var location = new types.Location(); location.latitude = clLocation.coordinate.latitude; @@ -33,12 +22,45 @@ export class LocationManager { location.speed = clLocation.speed; location.direction = clLocation.course; location.timestamp = new Date(clLocation.timestamp.timeIntervalSince1970() * 1000); + location.iosNative = clLocation; //console.dump(location); return location; } + private static iosLocationFromLocation(location: types.Location): CoreLocation.CLLocation { + var hAccuracy = location.horizontalAccuracy ? location.horizontalAccuracy : -1; + var vAccuracy = location.verticalAccuracy ? location.verticalAccuracy : -1; + var speed = location.speed ? location.speed : -1; + var course = location.direction ? location.direction : -1; + var altitude = location.altitude ? location.altitude : -1; + var timestamp = location.timestamp ? Foundation.NSDate.dateWithTimeIntervalSince1970(location.timestamp.getTime()) : null; + var iosLocation = CoreLocation.CLLocation.initWithCoordinateAltitudeHorizontalAccuracyVerticalAccuracyCourseSpeedTimestamp(CoreLocation.CLLocationCoordinate2DMake(location.latitude, location.longitude), altitude, hAccuracy, vAccuracy, course, speed, timestamp); + return iosLocation; + } + + public static isLocationEnabled(): boolean { + return CoreLocation.CLLocationManager.locationServicesEnabled(); + } + + public static distanceInMeters(loc1: types.Location, loc2: types.Location): number { + if (!loc1.iosNative) { + loc1.iosNative = LocationManager.iosLocationFromLocation(loc1); + } + if (!loc2.iosNative) { + loc2.iosNative = LocationManager.iosLocationFromLocation(loc2); + } + return loc1.iosNative.distanceFromLocation(loc2.iosNative); + } + + constructor() { + this.isStarted = false; + this.desiredAccuracy = types.DesiredAccuracy.HIGH; + this.updateDistance = -1; // kCLDistanceFilterNone + this.iosLocationManager = new CoreLocation.CLLocationManager(); + } + // monitoring - public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: string) => any) { + public startLocationMonitoring(onLocation: (location: types.Location) => any, onError?: (error: Error) => any) { if (!this.isStarted) { var LocationListener = Foundation.NSObject.extends({ setupWithFunctions: function (onLocation, onError) { @@ -59,9 +81,9 @@ export class LocationManager { }, locationManagerDidFailWithError: function (manager, error) { - console.log('location error received ' + error.localizedDescription()); + console.error('location error received ' + error.localizedDescription()); if (this.onError) { - this.onError(error.localizedDescription()); + this.onError(new Error(error.localizedDescription())); } } } @@ -75,7 +97,7 @@ export class LocationManager { this.iosLocationManager.startUpdatingLocation(); } else if (onError) { - onError('location monitoring already started'); + onError(new Error('location monitoring already started')); } } @@ -95,9 +117,4 @@ export class LocationManager { } return null; } - - public distanceInMeters(loc1: types.Location, loc2: types.Location): number { - // TODO - return 0; - } } diff --git a/Location/location_types.ts b/Location/location_types.ts index dd52740aa..a64bece7c 100644 --- a/Location/location_types.ts +++ b/Location/location_types.ts @@ -18,6 +18,9 @@ export class Location { public direction: number; // in degrees public timestamp: Date; + + public androidNative: any; // android Location + public iosNative: any; // iOS native location } export class LocationRegion { diff --git a/declarations.ios.d.ts b/declarations.ios.d.ts index 5c723df54..3b39a28b5 100644 --- a/declarations.ios.d.ts +++ b/declarations.ios.d.ts @@ -90,6 +90,7 @@ declare module Foundation { } export class NSDate { + static dateWithTimeIntervalSince1970(datetime: number); timeIntervalSince1970(): number; } @@ -114,6 +115,7 @@ declare module CoreLocation { } export class CLLocation { + static initWithCoordinateAltitudeHorizontalAccuracyVerticalAccuracyCourseSpeedTimestamp(coordinate: any, altitude: number, horizontalAccuracy: number, verticalAccuracy: number, course: number, speed: number, timestamp: Foundation.NSDate); coordinate: any; altitude: number; horizontalAccuracy: number; @@ -122,4 +124,6 @@ declare module CoreLocation { speed: number; course: number; } + + function CLLocationCoordinate2DMake(latitude: number, longitude: number) : any; } diff --git a/net/http_client.android.ts b/net/http_client.android.ts index ff9bfeeeb..337852033 100644 --- a/net/http_client.android.ts +++ b/net/http_client.android.ts @@ -41,7 +41,7 @@ export class http { // TODO: Accept: application/json header for JSON calls and check the response for Image not url! private static get(url: string, successCallback: (result: any) => void, errorCallback?: (e: Error) => void) { try { - var isImage = url.match(/\.(jpeg|jpg|gif|png)$/) != null; + var isImage = url.match(/\.(jpeg|jpg|gif|png)$/i) != null; var context = app_module.Application.current.android.context; var request = com.koushikdutta.ion.Ion.with(context, url);