I am currently learning react-native and I am working on a an application that uses Geolocation to find and update my current location and I am following a tutorial for that and in the tutorial I had to use a property with the timeout and maximumAge options.
navigator.geolocation.getCurrentPosition((pozitie)=>{
var lat = parseFloat(position.coords.latitude)
var long = parseFloat(position.coords.longitude)
// create an object with the current position taken from the geolocation chip
var initialLocation = {
latitude = lat,
longitude = long,
// Delta is the viewing angle on the location of the user
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA
}
// Now we are seting initial position to the initial location
this.setState({initialPositionOnTheMap: initialLocation})
// we set the marker to the initial location and then the display follows the marker
// by using the initialLocaiton object that will receive the users current location
this.setState({positionOfTheMarker: initialLocation})
},
// make a function call if an error happens
// we make an allert that parses the error message
(error) => alert(JSON.stringify(error)),
// propertie
{enableHighAccuracy: true, timeout: 2000, maximumAge: 1000})
but it didn't explain what does timeout and maximumAge mean, why do we use them.
I know that these options are used in two methods provided by react-native: getCurrentPosition(Invokes a callback with the latest location) and watchPosition(Invokes a callback whenever the location has changed) but I don't understand what are they doing exactly.
I have asked the creator of the tutorial, and he responded:
Timeout: is a positive value that indicates the maximum time the device is allowed to return a position.
MaximumAge: is a positive value indicating the maximum age in milliseconds of a possible cached position that is acceptable to return. In other words, how old can cached locations be before I should start getting the current location to return.
Related
I have a tracking function but it doesn't update location while in background.
1st case: Tracking while app is in the foreground -> the tracking is actually happening but doesn't get precise coordinates. I will change to locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation to see if improves accuracy of the tracking.
2nd case: Tracking while screen is off -> the tracking is a straight line from a to b, tracking doesn't update coordinates.
3rd case: Tracking while app is in back ground(pressed home button) -> tracking is happening as case 1.
I found a post that explains that if authorisation is set to always you have to specify you want to keep updating location while in background, but nothing has changed. This is the code and info.plist :
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
// locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
// locationManager.allowsBackgroundLocationUpdates = true //for getting user location in background mode as well
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow //map following user
configureLocationServices()
addDoubleTap() // enabling duble tap gesture recognizer
// mapView.isUserInteractionEnabled = true
let location = locationManager.location?.coordinate
let region = MKCoordinateRegionMakeWithDistance(location!, 1000, 1000) // set mapView based on user location coordinates
mapView.setRegion(region, animated: true)
centerMapOnLocation()
// alerts coordinates to post to Firebase
let alertDrawLatitude = alertDrawCoordinates?.latitude // not used ?
let alertDrawLomgitude = alertDrawCoordinates?.longitude
let title: String? = alertNotificationType
var subtitle: String? = alertNotificationType
// user alert notification. takes coordinates from alertNotificationArray( populated with firebase returning coordinate for all alerts
displayAlerts()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let mostRecentLocation = locations.last else { return }
self.actualRouteInUseCoordinatesArray.append(mostRecentLocation.coordinate)
}
func configureLocationServices() {
if authorizationStatus == .notDetermined{
locationManager.requestAlwaysAuthorization()
} else if authorizationStatus == .authorizedAlways {
locationManager.showsBackgroundLocationIndicator = true //set update location even if in background. very imposrtant!!
}
}
UPDATE:
changing the accuracy only made things worse.
with AccuracyBest:
and with AccuracyBestForNAvigation
second tracking is actually worse.. how can navigation apps rely on this kind of tracking? is there anything wrong with my code for LocationManager?
SECOND UPDATE:
it now get updated location when in background, but is way off..I never passed the yellow street and it shows like I waked for 10 minutes after it..
THIRD EDIT:
I found out that I should filter out GPS raw data, so I'm using a Kalman filter, and it really smooths out the resulting tracking.
So I'm fine tuning two parameters, and in order to be able to change those parameters I added two textfields #IBOutlet weak var filterValueTextField: UITextField! and #IBOutlet weak var horizontalAccuracyTextField: UITextField!and connected those to the parameters
hcKalmanFilter?.rValue = Double(String( describing:filterValueTextField?.text!))! and guard mostRecentLocation.horizontalAccuracy < Double(String( describing: horizontalAccuracyTextField?.text!))! else { return }.
My problem is now that it finds nil while unwrapping value in the horizontalAccuracy parameter.
If in horizontalAccuracy I just put a value it accepts an integer, but when I take it from the texField converting the textfield.text to Int, compiler throws an error Binary operator '<' cannot be applied to operands of type 'CLLocationAccuracy' (aka 'Double') and 'Int', while if I convert it to Double doesn't, but it finds nil.
Why the filterValue finds a value from it's textField, and the horizontal Accuracy doesn't? they're declared, and use the same way.
Any idea?
First of all you have limited time while your app goes to background, and that time is depend upon load on your device's OS, but most probably it is approx. 30 seconds. So this is the reason your are not getting location updates while your screen is off or while your app goes to background.
But Apple allows app to run in background for some tasks and location update is one of them, so you can fetch location updates even if your app goes to background by enabling Background Fetch capability for your app.
For more details please follow below official doc. of Apple:
https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/handling_location_events_in_the_background
And secondly try to maintain your locationmanager object in global scope of your app like you can place it in AppDelegate or in Singleton class if you are maintaining any for your app, so it will always be available.
Sometimes location that you receive does not have desired accuracy, especially when you've just started tracking, first couple of locations are going to be well off. You can use location's horizontal accuracy property to filter location witch have, for example, less then 50m accuracy
Hi guys I need some help on how to get the coordinates of the user when you enable the
followUserLocation
on
MapView
. Is there a way on how to do this or are there any possible alternatives to this?
I already did something like this:
import {DeviceEventEmitter} from 'react-native';
import RNALocation from 'react-native-android-location';
import MapView from 'react-native-maps';
componentDidMount() {
DeviceEventEmitter.addListener('updateLocation', function(e: Event) {
console.log(e);
this.setState({lng: e.Longitude, lat: e.Latitude });
}.bind(this));
RNALocation.getLocation();
}
Already used React Native Geolocation https://facebook.github.io/react-native/docs/geolocation.html
but nothing seems to work. It only gives me the initial location of the user and it does not give me some updates when there are changes on user location.
I even used setInterval to keep on calling the API so it can give me new updates on the user location but the coordinates still does not change.
I used fake GPS to move my location or mock my location . . please help thanks a lot.
You can use navigator.geolocation.watchPosition (https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition)
const options = options = {
enableHighAccuracy: false,
timeout: 5000,
maximumAge: 0
};
navigator.geolocation.watchPosition((lastPosition) => {
this.setState({lng: lastPosition.coords.longitude, lat: lastPosition.coords.latitude });
}, (error) => {
console.log('Error', error)
}, options);
Anyways, I got it all sorted out. Since there is no way I can listen to user location using the GPS of the mobile device. What I did was I used the code from React Native geolocation
navigator.geolocation.getCurrentPosition(
(position) => {
var initialPosition = JSON.stringify(position);
this.setState({initialPosition});
},
(error) => alert(JSON.stringify(error)),
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
);
Loop through it every 1 second and then update the coordinate states (lat and long) if there is a change in coordinates. So far it works smoothly. :)
I'm writing an app, that has to do some calculations every time the phone moves. I've read every question here, but couldn't get the Accelerometer to gather data in the background (after the user navigates away from the app). I've set the Location updates flag in the Plist.info. This is the code I'm using:
let motionManager = CMMotionManager()
func startMotionUpdates() {
var timestamps = [NSDate]()
if motionManager.accelerometerAvailable {
motionManager.accelerometerUpdateInterval = 1
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue(), withHandler: { (data: CMAccelerometerData?, error: NSError?) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let time = NSDate(timeIntervalSince1970: data!.timestamp)
timestamps.append(time)
print(timestamps)
})
})
}
}
I tried every combination out there, I've tried using CMDeviceMotion, I've tried using CLLocationManager.startUpdatingLocation() to simulate background activity, but nothing works. Does anybody have any ideas?
You cannot be woken up every time the accelerometer changes. You can be woken up whenever the location of the device changes significantly (at least several meters) using CLLocationManager, and that's what "location" means in the background modes.
To track finer-grained motion information, you need to ask the system to start recording the data using CMSensorRecorder, and then later you can ask for the data and compute what you want from it. But you won't be allowed to run in the background continuously watching every jiggle of the device. That would eat too much battery.
See also CMPedometer which addresses certain use cases more directly.
Platform: iOS6/OSx Lion.
I'm trying to puzzle out the way Phonegap/Cordova work with navigator.geolocation.watchPosition.
The docs says that the option "maximumAge" is the one that ask the system for retrieve the position.
So with these options:
{ maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }
I espect the position request will be fired every 3 seconds?
And no matter what maximumAge I put the success is fired every 1 second...
Anyone can explain please?
Thanks Bye
Rob
I am currently working around this issue by using getCurrentPosition with a setInterval. I'm not sure what the consequences may be, but this seems to give me the most control and appears to be the most consistent method across platforms.
// call this once
setupWatch(3000);
// sets up the interval at the specified frequency
function setupWatch(freq) {
// global var here so it can be cleared on logout (or whenever).
activeWatch = setInterval(watchLocation, freq);
}
// this is what gets called on the interval.
function watchLocation() {
var gcp = navigator.geolocation.getCurrentPosition(
updateUserLoc, onLocationError, {
enableHighAccuracy: true
});
// console.log(gcp);
}
// do something with the results
function updateUserLoc(position) {
var location = {
lat : position.coords.latitude,
lng : position.coords.longitude
};
console.log(location.lat);
console.log(location.lng);
}
// stop watching
function logout() {
clearInterval(activeWatch);
}
var initialLocation;
var siberia = new google.maps.LatLng(60, 105);
var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
var browserSupportFlag = new Boolean(); // Try W3C Geolocation (Preferred)
if (navigator.geolocation) {
browserSupportFlag = true;
navigator.geolocation.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
},
function() {
handleNoGeolocation(browserSupportFlag);
}); // Try Google Gears Geolocation
} else if (google.gears) {
browserSupportFlag = true;
var geo = google.gears.factory.create('beta.geolocation');
geo.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.latitude, position.longitude); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
},
function() {
handleNoGeoLocation(browserSupportFlag);
}); // Browser doesn't support Geolocation
} else {
browserSupportFlag = false;
handleNoGeolocation(browserSupportFlag);
}
function handleNoGeolocation(errorFlag) {
if (errorFlag == true) {
initialLocation = new google.maps.LatLng(geoip_latitude(), geoip_longitude()); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
navigator.notification.alert('Geolocation service failed', // message
'Geolocation Error!', // title
'OK' // buttonName
);
} else {
initialLocation = new google.maps.LatLng(geoip_latitude(), geoip_longitude()); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
navigator.notification.alert("Your browser doesn't support geolocation. We've placed you in Siberia.", // message
'Browser Error!', // title
'OK' // buttonName
);
} // THERES OUR LAT/LONG VALUES
}
This is code we use in our Sencha Touch application to get the users current position. Now, I tested this code using a 3G connection on my Droid HTC Eris, and it gave me a location 6 miles away from myself, which is fine, I can live with that, I could probably even live with a little bit more.
However, testing on an iPod Touch using Wifi, connecting to our in home router, it put us 147 miles from our current location. Now, this might make sense if our router here had some weird IP address or something like that (w/e this code actually uses to find location if it doesn't fall back to IP), but I testing geolocation straight from google from a laptop also hooked up to our wifi here and it puts us less than 1 mile from overhead.
What kind of situation could make this happen? Is this something we are just going to have to live with until geolocation further advances? If so, that's fine, I just want to know if there's something we could do to improve this. 147 miles away is a little crazy, considering every other source we've tried puts us within 10 max.
The only thing I can think of is that google has some correction listings in it's own databases. What is probably happening is your ip is registered to a holdco which is 147 miles away from you. For example if whois my IP it is registered to a holding company which is about 50 miles away from me. Non-corrected databases (such as the ones you typically buy online) show me in that town. Google, whoever does not.