Phonegap not detecting accurate location - html

I am using HTML5 Geolocation API in phonegap to precisely detect my location. I am working from India I should ideally be able to see my location i.e. Pune, India but it doesn't do so.
It detects 'San Francisco, CA, USA' as my location. What might be the problem?
Thank you all. Help is highly appreciated.
Let me share the code :)
document.addEventListener("deviceready", onDeviceReady, false);
// Cordova is loaded and it is now safe to make calls Cordova methods
//
function onDeviceReady() {
// onSuccess Callback
// This method accepts a `Position` object, which contains
// the current GPS coordinates
//
var onSuccess = function(position) {
var lattitude = position.coords.latitude;
var longitude = position.coords.longitude;
//Ajax Call
$.ajax({
url: 'http://maps.googleapis.com/maps/api/geocode/json?latlng='+lattitude+','+longitude+'&sensor=true',
success: function(data){
alert(data.results[0].formatted_address);
//alert(data.results[1].formatted_address);
},
error: function(data){
alert('error');
}
});//Ajax call ends
};
function onError(error) {
alert('code: '+ error.code + '\n' + 'message: ' + error.message + '\n');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}

If you're using the iOS simulator you will always get SF as the location as it has a static location setting. You can however use this nifty tool to emulate in browser and it will allow you to mess with location settings and more.
http://emulate.phonegap.com/

Related

How to reset coordinates into an Ajax call after having initialized a map?

I inserted a map on my webpage by using the Leaflet library. What I want to do is to show a map zoomed on a specific region according to which city the user types into a text field.
I firstly initialized my map on my JS file:
function initMaps(){
map = L.map('leaflet').setView([0, 0], 13);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
'attribution': 'Map data © OpenStreetMap contributors'
}).addTo(map);
}
My javascript code also has an Ajax call.
What I want to do now is to reset the coordinates on the Ajax call.
I wrote the following:
var readCoordinates = function(){
$.ajax({
url: "https://nominatim.openstreetmap.org/search?q=" + encodeURIComponent($("#inlineFormInputCitta").val()) + "+Italy&format=geocodejson",
dataType: "json",
success: function (data) {
setTimeout(function () {
for (let i = 0; i < data.features.length; i++) {
let coordinate = data.features[i].geometry.coordinates;
console.log(coordinate);
map.setView(coordinate, 13);
console.log("ajax and for loop have been activated");
console.log(coordinate.geometry.coordinates);
};
$("#ristoranti").prop("disabled", false);
}, 1000);
}
});
};
The API I'm referring to in the URL is the following: https://nominatim.openstreetmap.org/search?q=Roma%20Italy&format=geocodejson
What I did is trying to reset the coordinates here: map.setView(coordinate, 13);
after having cycled the elements in the JSON object, see the following:
for (let i = 0; i < data.features.length; i++) {
let coordinate = data.features[i].geometry.coordinates;
I may display several coordinates in the console, see the following:
That's because in the JSON file I get through the API request there are several:
The result of this is the following map, which isn't zoomed anywhere:
Which coordinates should I take in order to display that specific region?
EDIT - - -
I changed the code because I'm trying to get a specific subobject, i.e. the one in the screen below (which has "type" = "city"):
The new snippet is the one below, where I add an if statement:
var readCoordinates = function(){
$.ajax({
url: "https://nominatim.openstreetmap.org/search?q=" + encodeURIComponent($("#inlineFormInputCitta").val()) + "+Italy&format=geocodejson",
dataType: "json",
success: function (data) {
setTimeout(function() {
for (let i = 0; i < data.features.length; i++) {
debugger;
let type = data.features[i].properties.geocoding.type;
if( $(type).val() === "city") {
let coordinate = data.features[i].geometry.coordinates;
let lng = coordinate[0];
let lat = coordinate[1];
map.setView([lng, lat], 13);
console.log("ajax and for loop have been activated");
console.log(coordinate);}
};
$("#ristoranti").prop("disabled", false);
}, 1000);
}
});
};
I'm doing the debugger and get many undefined values:
I would do something like that:
if (typeof data.features[0] !== 'undefined') {
let coordinate = data.features[0].geometry.coordinates;
var latlng = L.latLng(coordinate.reverse());
map.flyTo(latlng, 12)
}
Be sure to have something in your array
Get data from the first item since it should be the correct one in most case
Create a latlng with those coordinates. Be careful, sometime you need to reverse the array to have the correct position.
Use flyTo to have a smooth transition to your coordinates. 12 is the zoom level
You don't need to loop over the data since you need only one position. You can replace the for with that.
You're having two problems here:
The response from the Nominatim API is returning several search results, each of them in one GeoJSON Feature inside the response FeatureCollection. It's up to you to choose which search result you want to focus in the map (the first?), or let the user do so.
You're not aware that GeoJSON uses longitude-latitude (or x-y) coordinates, whereas Leaflet uses latitude-longitude (or y-x)

Get users location in ons.ready not working

I have the following code:
ons.ready( function() {
navigator.geolocation.getCurrentPosition(
function( position ) {
geo.lat = position.coords.latitude;
geo.lon = position.coords.longitude;
}
);
} );
Sometimes, but not all the time I get the following error:
Location access is not available.
Error in Error callbackId: Geolocation54410059
I need the user's location to load data into the main page of my app. Where is the best place to do this?
ons.ready fire when the dom is loaded, you are using a cordova plugin in order to get geolocation position. So you can't use it before cordova is ready.
Just do:
document.addEventListener('deviceready', function () {
// now cordova is ready
navigator.geolocation.getCurrentPosition(function( position ) {
geo.lat = position.coords.latitude;
geo.lon = position.coords.longitude;
});
}, false);
And it will be fine I think.
Edit :
Try adding those options to your function :
navigator.geolocation.getCurrentPosition(function( position ) {
geo.lat = position.coords.latitude;
geo.lon = position.coords.longitude;
}, { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true });
you can put whatever value you want for 'enableHighAccuracy' and 'maximumAge' but you must provide a 'timeout' option because there is some quirks in android:
Android Quirks
If Geolocation service is turned off the onError callback is invoked
after timeout interval (if specified). If timeout parameter is not
specified then no callback is called.

Geolocation data saved in a variable/localstorage

i have a problem with the Geolocation API -.-'
I'm using the FirefoxOS Boilerplate App (https://github.com/robnyman/Firefox-OS-Boilerplate-App) for create a simple html5 app.
The problem is simple: I would like the data (lat/lon) obtained from the API are returned by a function as an array.
All the examples that i have found uses the data on the fly for show the maps or insert in a div (as also this boilerplate).
navigator.geolocation.getCurrentPosition(function (position) {
geolocationDisplay.innerHTML = "<strong>Latitude:</strong> " + position.coords.latitude + ", <strong>Longitude:</strong> " + position.coords.longitude;
geolocationDisplay.style.display = "block";
},
function (position) {
geolocationDisplay.innerHTML = "Failed to get your current location";
geolocationDisplay.style.display = "block";
});
This is the code of the boilerplate for the Geolocation...
I would want a function like get_location that return me the data, but after days of testing/google search I gave up and I ask you who are more experienced with callback/scope in Javascript of me.
The opntions that i have evaluated it's save the data in a hidden div or save with localstorage/cookies.
Thanks for the help!
EDIT 20/11:
function load_location() {
navigator.geolocation.getCurrentPosition(save_location, handleLocationError, {maximumAge: 0, timeout: 1000, enableHighAccuracy: true});
}
function handleLocationError(error) {
alert(error.code + ' - ' + error.message);
}
function save_location(position) {
localStorage.clear();
ls_save('latitude',position.coords.latitude);
ls_save('longitude',position.coords.longitude);
ls_save('accuracy',position.coords.accuracy);
ls_save('altitude',position.coords.altitude);
ls_save('altitudeAccuracy',position.coords.altitudeAccuracy);
ls_save('heading',position.coords.heading);
ls_save('speed',position.coords.speed);
}
function ls_save(key,value) {
localStorage.setItem(key, value);
}
function get_location() {
while(typeof localStorage['latitude'] === 'string') {
return localStorage.getItem("latitude");
}
}
load_location();
//Code
console.log(get_location());
The new code after the comments. I do not know how performance this solution...
I have replaced console.log with alert and i get undefined then in some cases is not asynchronous.
Edit: 22/11:
Fixed the while
You can return the geolocation data as an array, by doing something like this:
function doSomethingWithGeo(geo) {
console.log(geo);
}
function get_location() {
navigator.geolocation.getCurrentPosition(function (position) {
doSomethingWithGeo([[position.coords.latitude, position.coords.longitude]]);
});
}
When you call get_location, it will retrieve the geolocation coordinates, and will call the function doSomethingWithGeo with the array you wanted. If you want to store your data, you can do it in the doSomethingWithGeo function.
Let me know if it's not what you were looking for.

Geolocation in Windows Phone HTML App not working

I'm developing html5 windows phone 8 application and I've run into problem: geolocation doesn't work for me. I have WebBrowser.IsGeolocationEnabled property set to true and in app manifest ID_CAP_LOCATION is also checked. Hovewer even with the geolocation code copy-pasted from various HTML5 learning portals I'm still getting an error telling that site doesn't have geolocation permission.
Thanks for any help
var watchId = navigator.geolocation.watchPosition(scrollMap, handleError);
function scrollMap(position) {
myLoc.setLatLng([position.coords.latitude, position.coords.longitude]);
}
function handleError(error) {
myLoc.setLatLng([0, 0]);
}
I had the same issue, but solved it by totally rewriting my code - simplifying it:
var lng, lat;
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
else { alert("Geolocation is not supported by this browser."); }
}
function showPosition(position) {
alert("Latitude: " + position.coords.latitude +
"\nLongitude: " + position.coords.longitude);
lng = position.coords.longitude;
lat = position.coords.latitude;
}

Latitude and longitude can find zip code?

I am using Google geocoder for lat and lon and my question is, is there a way you can find out zipcode with latitude and longitude?
It's good to note that Google Maps has a new version since this solultion was presented.
Reference: https://developers.google.com/maps/documentation/geocoding/?csw=1#ReverseGeocoding
Here's an updated example for Google Maps v3. It makes use of the Address Components that JIssak mentions above. I should note that there is no fallback. If it fails to find a zip code, it does nothing. This may or may not be important to your script.
var latlng = new google.maps.LatLng(p.coords.latitude, p.coords.longitude);
geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
for (j = 0; j < results[0].address_components.length; j++) {
if (results[0].address_components[j].types[0] == 'postal_code')
alert("Zip Code: " + results[0].address_components[j].short_name);
}
}
} else {
alert("Geocoder failed due to: " + status);
}
});
I think what you are looking for is the address_components[] in the results array. Maybe something like this would work, just typing the below so it might have errors in it but I think you will get the idea.
http://code.google.com/apis/maps/documentation/geocoding/#Results
function (request, response) {
geocoder.geocode({ 'address': request.term, 'latLng': centLatLng, 'region': 'US' }, function (results, status) {
response($.map(results, function (item) {
return {
item.address_components.postal_code;//This is what you want to look at
}
}
[Removed non-working solution for google - see #hblackorby's solution.]
Here's a version that uses openstreetmap.org, much simpler than google's api - coffeescript, then javascript:
getZip = (cb) ->
# try to populate zip from geolocation/google geocode api
if document.location.protocol == 'http:' && navigator.geolocation?
navigator.geolocation.getCurrentPosition (pos) ->
coords = pos.coords
url = "http://nominatim.openstreetmap.org/reverse?format=json&lat=#{ coords.latitude }&lon=#{ coords.longitude }&addressdetails=1"
$.ajax({
url: url,
dataType: 'jsonp',
jsonp: 'json_callback',
cache: true,
}).success (data) ->
cb(data.address.postcode)
Here's the compiled javascript:
getZip = function(cb) {
if (document.location.protocol === 'http:' && (navigator.geolocation != null)) {
return navigator.geolocation.getCurrentPosition(function(pos) {
var coords, url;
coords = pos.coords;
url = "http://nominatim.openstreetmap.org/reverse?format=json&lat=" + coords.latitude + "&lon=" + coords.longitude + "&addressdetails=1";
return $.ajax({
url: url,
dataType: 'jsonp',
jsonp: 'json_callback',
cache: true
}).success(function(data) {
return cb(data.address.postcode);
});
});
}
};
Use it like this:
getZip(function(zipcode){ console.log("zip code found:" + zipcode); });
Yahoo's PlaceFinder API provides a good wat to lookup location data by lat/lng:
http://developer.yahoo.com/geo/placefinder/
Here's an example url that they use:
http://where.yahooapis.com/geocode?q=38.898717,+-77.035974&gflags=R
It would seem so:
Source: Google Maps API Service
Geocoding is the process of converting addresses (like "1600
Amphitheatre Parkway, Mountain View, CA") into geographic coordinates
(like latitude 37.423021 and longitude -122.083739), which you can use
to place markers or position the map. The Google Geocoding API
provides a direct way to access a geocoder via an HTTP request.
Additionally, the service allows you to perform the converse operation
(turning coordinates into addresses); this process is known as
"reverse geocoding."
You should also check out this documentation which has some sample code:
Reverse Geocoding
I made a generic function to look for the type that you want. Not always the address_component has zipcode, country, etc and if they do not always are in the same index. Sometimes your array is lenght 8, 6 or whatever. I did it in Typescript, just change a few things to make it vanilla JS.
getPlaceTypeValue(addressComponents: Places[], type: string): string {
let value = null;
for (const [i] of addressComponents.entries()) {
if (addressComponents[i].types.includes(type)) {
value = addressComponents[i].long_name;
break;
}
}
return value;
}
OR
getPlaceTypeValue(addressComponents: any[], type: string): string {
return (addressComponents.find(({ types }) => types.includes(type)) || {}).long_name || null;
}
Example of usage:
this.placesService.getPlaceTypeValue(address.address_components, 'postal_code');
this.placesService.getPlaceTypeValue(address.address_components, 'country');