Is there a way to prompt user for geolocation again on some trigger, after they denied the location sharing?
navigator.geolocation.getCurrentPosition
fires it once, consecutive calls do not produce the same result. Cant find the answer anywhere/
Take a look at this Code Snippet and this SO Answer: What is the best JQuery plugin that handles HTML5 location?
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}else{
errorFunction();
}
function successFunction(position) { //uses HTML5 if available
var lat = position.coords.latitude;
var lng = position.coords.longitude;
}
function errorFunction(){ //uses IP if no HTML5
$.getJSON("http://freegeoip.net/json/", function(res){
var lat = res.latitude;
var lng = res.longitude;
});
}
Take a Look at this Fiddle Link also
JQuery Geolocator Plugin
In Geolocation API? No.
If user clicks deny permission it simply means "No, and don't bother me again..."
However user can do it by deleting Location-share-settings, then of course the prompt pops out again.
Or user can just change the settings if browser allows it, however e.g. Chrome manages these settings as exceptions (no matter whether user've allowed or denied permission) so user have to delete the settings, resp. exception anyway.
What now?
Your only option is to catch the error and use e.g. some external API to find the user's location by IP. You can program it by yourself or there are of course existing solutions as #Venkat suggested.
But be aware IP geolocation is a tricky one - sometimes it has an adress-number-accuracy sometimes it's just state-accuracy.
This examle from Mozilla's docs shows a nice example how to handle Geolocation errors:
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
function success(pos) {
var crd = pos.coords;
console.log('Your current position is:');
console.log('Latitude : ' + crd.latitude);
console.log('Longitude: ' + crd.longitude);
console.log('More or less ' + crd.accuracy + ' meters.');
};
function error(err) {
/*
CALL EXTERNAL API HERE
*/
console.warn('ERROR(' + err.code + '): ' + err.message);
};
navigator.geolocation.getCurrentPosition(success, error, options);
The best option for this is to setup a geolocation subdomain, and load it in a iframe.
geo-0.domain.com
geo-1.domain.com
geo-2.domain.com
geo-3.domain.com
geo-4.domain.com
geo-N.domain.com
This will allow you unlimited attempts on every browser, all you need to do is program in your own retry logic.
Related
I am working on a GMail add-on that connects to a third-party service through OAuth2. To obtain the authorization code the following redirect URI is used: https://script.google.com/macros/d/[SCRIPT_ID]/usercallback .
Here's a snippet that triggers authorization:
var stateToken = ScriptApp.newStateToken()
.withMethod( "authCallback" )
.withTimeout( 120 )
.createToken();
var authUrl = _authBaseUrl
+ "&client_id=" + encodeURIComponent( _clientId )
+ "&redirect_uri=" + encodeURIComponent( _redirectUri )
+ "&state=" + stateToken;
CardService.newAuthorizationException()
.setAuthorizationUrl( authUrl )
.setResourceDisplayName( "Resource" )
.throwException();
And here's the callback function (the HTML snippet is taken from here):
function authCallback( request )
{
createAccessToken( request.parameter.code );
return HtmlService.createHtmlOutput('Success! <script>setTimeout(function() { top.window.close() }, 1);</script>');
}
The createAccessToken function gets successfully invoked and the add-on gets an access token. However, the HTML is not served in the popover window. Instead, there's a placeholder with the following error: "The script completed but did not return anything."
As a result, I am stuck with an error window which can't be closed automatically and doesn't tell user that they have to close the window to continue working with the add-on.
Is there anything wrong I am doing or this is some kind of bug or a dropped feature? Thanks for any suggestions.
UPD:
The error looks like this
Turns out the HtmlService actually works in that case. I had a function name collision for authCallback, so the proper one wasn't invoked. Sorry for misinformation. If anyone has trouble handling the callback window, do as described in the question.
I use the geolocation plugin in Cordova 3.5. And I have coded as follow:
navigator.geolocation.getCurrentPosition(function(pos) {
var lat = pos.coords.latitude;
var lng = pos.coords.longitude;
alert("lat : "+lat+" lng : " +lng");
});
I am wandering whether this code can work to get lat lng without Internet connection and GPS on. If not, is there any solution to do so? Thank for your help.
Without Internet connection, there are still sources like Cell ID's, RFID and MAC addresses of devices you are connected to (e. g. WIFI routers, Bluetooth)
The code should work, but you can add a few things (Eventlistener and error alert in case that the position cannot be found):
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
function onSuccess(pos) {
var lat = pos.coords.latitude;
var lng = pos.coords.longitude;
alert("lat : " + lat + " lng : " + lng);
}
function onError(error) {
alert('code: ' + error.code + '\n' + 'message: ' + error.message + '\n');
}
I know that for example the Google location API uses a cache for the latest known location, which can be read out anytime.
I am not sure if Cordova also uses something similar but it could be.
check if geolocation is properly installed or not
restart your phone (silly solution but it works sometimes.I faced it once)
check if your geo permissions & settings are turned on in device
test with this code
options = { enableHighAccuracy: true };
navigator.geolocation.getCurrentPosition(onSuccess, onError, options);
If you're using android, try to get the error with eclipse logcat.
On iOS this will always work one way or the other. If the plugin fails, the browser's own Geolocation API will be used. There's some undesired side effects with the fallback though:
The permission dialog that pop's up has the html file's name in the title instead of the app name
Granted permissions will only persist as long as the app is running
On Android it only works if you have set the correct permissions in app/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
As #jcesarmobile pointed out here Cordova geolocation plugin not getting location from GPS for Android:
They are using HTML5 geolocation implementation instead of native
code. They removed the android java code on release 0.3.7 of the
plugin
### 0.3.7 (Apr 17, 2014)
* CB-6422: [windows8] use cordova/exec/proxy
* CB-6212: [iOS] fix warnings compiled under arm64 64-bit
* CB-5977: [android] Removing the Android Geolocation Code. Mission Accomplished.
* CB-6460: Update license headers
* Add NOTICE file
Hope this helps
Currently I can determine if a user has Allowed or Denied browser location services. But how do I detect if a user's browser has previously allowed the permission? I don't want to show the "setting message" to the user again.
$("#updateLocation").click(function(e){
e.preventdefault;
navigator.geolocation.getCurrentPosition(allowLocation,deniedLocation);
return false;
});
function allowLocation(position){
// codes
}
function deniedLocation(){
// codes
}
I also facing the same problem. And, after I search and experiment I finally found the answer
You can add this JS code :
navigator.permissions.query({name:'geolocation'}).then(function(result) {
// Will return ['granted', 'prompt', 'denied']
console.log(result.state);
});
Then you can use your custom code as needed.
source : https://developer.mozilla.org/en-US/docs/Web/API/Navigator/permissions
You can do this simply by making use of HTML5 localstorage which allows you to create key-value pairs:
$("#updateLocation").click(function(e){
e.preventdefault;
if(localStorage.location == undefined){
var ip-located-geo-location = navigator.geolocation.getCurrentPosition();
// code to get ip-located geolocation
var user_defined_location = prompt("Please enter your location", ip-located-geo-location);
localStorage.location = user_defined_location;
}
else{
// use localStorage.location
}
return false;
});
If the location is not previously saved then it asks for user_defined_location, also displaying the ip-located-position, and thereby updates the localStorage, so that the next time the user doesn't have to reset the location according to his preference.
i have a problem about HTML5 geolocation feature. I use the code below to get location data. I use "enableHighAccuracy: false" option to work with Cell Based GPS feature. Accurancy is low but response it too fast. But some people always use Built-in GPS with their mobile phone, so this code does not work for them. Bu if i change accurency option as "enableHighAccuracy: true" it works for them. But this time, the code uses only built-in GPS. not CELL based GPS.
The question -> How can i do that : First, try to get position from Built-in GPS with timeout (e.g. 5000ms ) if position cannot be got in this time just look for Cell Based position for timeout (e.g. 10000ms) if position cannot be get in this time, return an error message .
Here is the code that i use now.
Thanks in advance.
function getLocationfromGoogle() {
navigator.geolocation.getCurrentPosition(
function(pos) {
$("#lat_field").val(pos.coords.latitude);
$("#long_field").val(pos.coords.longitude);
var geocoder = new google.maps.Geocoder();
var latLng = new google.maps.LatLng(pos.coords.latitude,pos.coords.longitude);
geocoder.geocode({ 'latLng': latLng}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//console.log(results[0].formatted_address);
$("#adresim").val(results[0].formatted_address);
}
else {
alert('Google convertion is not succesfully done.');
}
});
},function error(msg){
alert('Please enable your GPS position future.');
},{maximumAge:600000, timeout:5000, enableHighAccuracy: false}
);
}
You should also be aware that the implementation of this varies from phone OS to phone OS - what works on Android may or may not work on iOS, BlackBerry, WindowsPhone, etc.
You're almost there, you just need to:
Specify enableHighAccuracy: true (you have it set to false)
Handle the timeout error case in the error handler. If the error from the high accuracy query is timeout, then try it again with enableHighAccuracy: false.
Have a look at this sample code.
You should also note that when testing this on a few devices, it returns location derived from WiFi even when enableHighAccuracy: true.
The code mentioned here: http://jsfiddle.net/CvSW4/ did not work for me during error handling.
The reason is that the error functions accept a parameter named 'position' but use an object in the functions called 'error'.
function errorCallback_highAccuracy(position) { ... }
function errorCallback_lowAccuracy(position) { ... }
The solution to fix this was to switch the error methods to accept the input value as a parameter named 'error' and not 'position', since the error callbacks do not accept a position and throw an error object instead.
function errorCallback_highAccuracy(error) { ... }
function errorCallback_lowAccuracy(error) { ... }
I mention it here, because I could not post on the resulting example page and also, this is the location where I linked through to find the code sample mentioned above.
I am using the HTML5 geolocation API. I recently decided to shift from polling user position to
using the watchPosition method, which is supposed to fire its "success" function, once the device position changes.
But instead, it is filling up my database with the same position over and over again. Relevant code posted below:
updateLocation = navigator.geolocation.watchPosition(success, failed, {enableHighAccuracy:true, maximumAge:30000, timeout:27000});
function success(){
showGPS(position);
}
function showGPS(position) {
var lng = position.coords.longitude;
var lat = position.coords.latitude;
gpsText.innerText = "Latitude: "+ lat +"\nLongitude: "+ lng + "\nAccuracy: "+ position.coords.accuracy + "\nSpeed:" + (position.coords.speed*3.6) + "\nAltitude:" + position.coords.altitude;
getData("http://databaseEntryURL/gpsReceiver.aspx?string=" + gpsText.innerText);
}
The getData gets called about 5 times a second. I'm sure the latlng is not changing. I'm using android 2.2, to load this page. How do i make it call the success function ONLY if the device position changes?
Maybe it's just caused by some bug, so even when the location has no change (or the change is so small) your callback is still triggered.
One way to solve it is storing the last location and using it to compare with the current location. If there's no change (or the change is too small), do nothing in the callback. This will save you bandwidth and database space.
If you need to save battery life for the phone then you need to optimize the options, for example, changing enableHighAccuracy to false.
A more efficient way would be to set the watchPosition as a variable and call clearWatch() on it once you've received the first response:
var watchID = navigator.geolocation.watchPosition(onSuccess, onFailed);
function onSuccess(position) {
navigator.geolocation.clearWatch(watchID);
};