BCL: updated location to support distance measuring

This commit is contained in:
Stanimir Karoserov
2014-04-17 15:46:38 +03:00
parent b0b0c5f190
commit 95916c52f8
7 changed files with 105 additions and 86 deletions

View File

@ -1,6 +1,8 @@
Initializing location: Initializing location:
``` ```
var LocationManager = require("Location").LocationManager;
console.log('is location enabled: ' + LocationManager.isLocationEnabled()); console.log('is location enabled: ' + LocationManager.isLocationEnabled());
this.locationManager = new LocationManager(); this.locationManager = new LocationManager();

View File

@ -17,6 +17,42 @@ export class LocationManager {
private _locationListener: any; 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 { public static isLocationEnabled(): 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?)
@ -24,6 +60,16 @@ export class LocationManager {
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 {
if (!loc1.androidNative) {
loc1.androidNative = LocationManager.androidLocationFromLocation(loc1);
}
if (!loc2.androidNative) {
loc2.androidNative = LocationManager.androidLocationFromLocation(loc2);
}
return loc1.androidNative.distanceTo(loc2.androidNative);
}
constructor() { constructor() {
// put some defaults // put some defaults
this.desiredAccuracy = types.DesiredAccuracy.HIGH; this.desiredAccuracy = types.DesiredAccuracy.HIGH;
@ -34,37 +80,14 @@ export class LocationManager {
this.androidLocationManager = app_module.Application.current.android.context.getSystemService('location'); 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 // 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) { 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.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 = <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) {
@ -89,12 +112,12 @@ export class LocationManager {
} }
catch (e) { catch (e) {
if (onError) { if (onError) {
onError(e.message); onError(e);
} }
} }
} }
else if (onError) { else if (onError) {
onError('location monitoring already started'); onError(new Error('location monitoring already started'));
} }
} }
@ -106,7 +129,9 @@ export class LocationManager {
} }
} }
////////////////////////
// other // other
////////////////////////
public getLastKnownLocation(): types.Location { public getLastKnownLocation(): types.Location {
var criteria = new android.location.Criteria(); var criteria = new android.location.Criteria();
@ -130,7 +155,4 @@ export class LocationManager {
return null; return null;
} }
public distanceInMeters(loc1: types.Location, loc2: types.Location): number {
return 0;
}
} }

View File

@ -4,22 +4,6 @@
HIGH, 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 { export declare class LocationRegion {
public latitude: number; public latitude: number;
public longitude: number; public longitude: number;
@ -41,11 +25,9 @@ export declare class Location {
direction: number; // in degrees direction: number; // in degrees
timestamp: Date; timestamp: Date;
}
export declare class LocationChangeListener { public androidNative: any; // android Location
onLocationChange(location: Location); public iosNative: any; // iOS native location
onLocationError(error: string);
} }
export declare class RegionChangeListener { export declare class RegionChangeListener {
@ -55,29 +37,18 @@ export declare class RegionChangeListener {
export declare class LocationManager { export declare class LocationManager {
static isLocationEnabled(): boolean; static isLocationEnabled(): boolean;
static distanceInMeters(loc1: Location, loc2: Location): number;
desiredAccuracy: number; desiredAccuracy: number;
updateDistance: number; updateDistance: number;
// minimum time interval between location updates, in milliseconds (android only) // minimum time interval between location updates, in milliseconds (android only)
minimumUpdateTime: number; minimumUpdateTime: number;
isStarted: boolean; isStarted: boolean;
// listeners
locationChangeListener: LocationChangeListener;
/* regionChangeListener: RegionChangeListener;
// regions
addRegion(region: LocationRegion);
removeRegion(region: LocationRegion);
clearRegions();*/
// monitoring // monitoring
startLocationMonitoring(onLocation: (location: Location) => any, onError?: (error: Error) => any);
startLocationMonitoring(onLocation: (location: Location) => any, onError?: (error: string) => any);
stopLocationMonitoring(); stopLocationMonitoring();
// other // other
getLastKnownLocation(): Location; getLastKnownLocation(): Location;
distanceInMeters(loc1: Location, loc2: Location): number;
} }

View File

@ -12,17 +12,6 @@ export class LocationManager {
public isStarted: boolean; public isStarted: boolean;
private iosLocationManager: CoreLocation.CLLocationManager; 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 { private static locationFromCLLocation(clLocation: CoreLocation.CLLocation): types.Location {
var location = new types.Location(); var location = new types.Location();
location.latitude = clLocation.coordinate.latitude; location.latitude = clLocation.coordinate.latitude;
@ -33,12 +22,45 @@ 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;
//console.dump(location); //console.dump(location);
return 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 // 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) { if (!this.isStarted) {
var LocationListener = Foundation.NSObject.extends({ var LocationListener = Foundation.NSObject.extends({
setupWithFunctions: function (onLocation, onError) { setupWithFunctions: function (onLocation, onError) {
@ -59,9 +81,9 @@ export class LocationManager {
}, },
locationManagerDidFailWithError: function (manager, error) { locationManagerDidFailWithError: function (manager, error) {
console.log('location error received ' + error.localizedDescription()); console.error('location error received ' + error.localizedDescription());
if (this.onError) { if (this.onError) {
this.onError(error.localizedDescription()); this.onError(new Error(error.localizedDescription()));
} }
} }
} }
@ -75,7 +97,7 @@ export class LocationManager {
this.iosLocationManager.startUpdatingLocation(); this.iosLocationManager.startUpdatingLocation();
} }
else if (onError) { else if (onError) {
onError('location monitoring already started'); onError(new Error('location monitoring already started'));
} }
} }
@ -95,9 +117,4 @@ export class LocationManager {
} }
return null; return null;
} }
public distanceInMeters(loc1: types.Location, loc2: types.Location): number {
// TODO
return 0;
}
} }

View File

@ -18,6 +18,9 @@ export class Location {
public direction: number; // in degrees public direction: number; // in degrees
public timestamp: Date; public timestamp: Date;
public androidNative: any; // android Location
public iosNative: any; // iOS native location
} }
export class LocationRegion { export class LocationRegion {

View File

@ -90,6 +90,7 @@ declare module Foundation {
} }
export class NSDate { export class NSDate {
static dateWithTimeIntervalSince1970(datetime: number);
timeIntervalSince1970(): number; timeIntervalSince1970(): number;
} }
@ -114,6 +115,7 @@ declare module CoreLocation {
} }
export class CLLocation { export class CLLocation {
static initWithCoordinateAltitudeHorizontalAccuracyVerticalAccuracyCourseSpeedTimestamp(coordinate: any, altitude: number, horizontalAccuracy: number, verticalAccuracy: number, course: number, speed: number, timestamp: Foundation.NSDate);
coordinate: any; coordinate: any;
altitude: number; altitude: number;
horizontalAccuracy: number; horizontalAccuracy: number;
@ -122,4 +124,6 @@ declare module CoreLocation {
speed: number; speed: number;
course: number; course: number;
} }
function CLLocationCoordinate2DMake(latitude: number, longitude: number) : any;
} }

View File

@ -41,7 +41,7 @@ export class http {
// TODO: Accept: application/json header for JSON calls and check the response for Image not url! // 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) { private static get(url: string, successCallback: (result: any) => void, errorCallback?: (e: Error) => void) {
try { 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 context = app_module.Application.current.android.context;
var request = com.koushikdutta.ion.Ion.with(context, url); var request = com.koushikdutta.ion.Ion.with(context, url);