Is there a way to check if geolocation has been DECLINED with Javascript?
Asked Answered
A

9

89

I need JavaScript to display a manual entry if geolocation is declined.

What I have tried:

Modernizr.geolocation
navigator.geolocation

Neither describes if user has previously declined access to geolocation.

Armelda answered 23/5, 2011 at 2:55 Comment(1)
Accepted answer changed to @endlessArmelda
H
81

Without prompting the user, you can use the new permission api this is available as such:

navigator.permissions.query({ name: 'geolocation' })
.then(console.log)
Howarth answered 10/6, 2016 at 13:58 Comment(2)
@trev9065 Blink is the browser engine used by Chrome.Nonsectarian
once again safari is the new ie :(Orthopedic
B
150

watchPosition and getCurrentPosition both accept a second callback which is invoked when there is an error. The error callback provides an argument for an error object. For permission denied, error.code would be error.PERMISSION_DENIED (numeric value 1).

Read more here: https://developer.mozilla.org/en/Using_geolocation

Example:

navigator.geolocation.watchPosition(function(position) {
    console.log("i'm tracking you!");
  },
  function(error) {
    if (error.code == error.PERMISSION_DENIED)
      console.log("you denied me :-(");
  });

EDIT: As @Ian Devlin pointed out, it doesn't seem Firefox (4.0.1 at the time of this post) supports this behavior. It works as expected in Chrome and probably Safari etc.

Beitch answered 23/5, 2011 at 2:57 Comment(14)
The permission denied error isn't related to the fact that the person has refused to allow the browser to collect their information.Eyespot
@Ian Devlin: Are you sure? The W3C draft says the PERMISSION_DENIED error is given when "The location acquisition process failed because the document does not have permission to use the Geolocation API." However, I couldn't get this behavior to work in Firefox -- it works as (I) expected in Chrome though.Beitch
No I'm not sure now! :-) I did read somewhere that Firefox doesn't implement this particular bit correctly.Eyespot
@Ian Devlin: Interesting. I've been using this code for Firefox assuming it would work (so much for testing). I'll leave the answer up but edit in this behavior in. Thanks for the heads up.Beitch
As of Aug, 2013 Firefox(23.0) still does not support this. Took me forever to figure this out.Mannuela
@Orin Thanks for posting that! I'm currently in a tight spot so that was helpful. Has anyone found a graceful way of dealing with such a major gap in support?Questionless
Check out the second answer here. This is what I did and it works great. Just set a regular timeout before calling the getCurrentPosition function, then clear the timeout on success: #3398085Mannuela
Working in Firefox 46 as long as the user selects "Never Share Location" instead of "Not Now"Nanete
Is it possible with a variable to mark whether it works or not. Simply by setting a variable on top as FALSE.Athapaskan
Hello this error message will show every time when ever i re lode the page, is there any way to show message only one time just after deny.Bignonia
Hello from 2018! Firefox 61 throws the proper error code when the user denies permission now, regardless of the method (never vs. not now).Barnes
Note, this should only be executed on user interaction. Otherwise it will likely never be called since browser more or less hides intrusive prompts now. For background check use the permission apiHowarth
sorry, I had to change the accepted answer because of navigator.permissions.query({ name: 'geolocation' }).then(console.log) was addedArmelda
@craigmoliver, I have to go with this one now, because navigator.permissions.query({ name: 'geolocation' }).then(console.log) does not seem to work anymore in Firefox 83.0b10. The PermissionStatus being returned is always "prompt" even when being denied. Chrome handles it correctly by returning "denied" as the statusLorettelorgnette
H
81

Without prompting the user, you can use the new permission api this is available as such:

navigator.permissions.query({ name: 'geolocation' })
.then(console.log)
Howarth answered 10/6, 2016 at 13:58 Comment(2)
@trev9065 Blink is the browser engine used by Chrome.Nonsectarian
once again safari is the new ie :(Orthopedic
G
20

According to the W3C geolocation specification, your getCurrentPosition call can return a callback for success and a callback for failure. However, your failure callback will be invoked for any error that occurred, which is one of: (0) unknown; (1) permission denied; (2) position unavailable; or (3) timeout. [Source: Mozilla]

In your case you want to do something specific if the user has explictly denied access. You can check the error.code value in your failure callback, like so:

navigator.geolocation.getCurrentPosition(successCallback,
    errorCallback,
    {
        maximumAge: Infinity,
        timeout:0
    }
);

function errorCallback(error) {
    if (error.code == error.PERMISSION_DENIED) {
        // pop up dialog asking for location
    }
}
Guyon answered 23/5, 2011 at 3:7 Comment(2)
Hello from 2018! Firefox 61 throws the proper error code when the user denies permission now.Barnes
Error codes are documented here: developer.mozilla.org/fr/docs/Web/API/GeolocationPositionErrorHypothermal
Y
8

Inline Permission Check

Possible values are prompt, granted, and denied

const permissionStatus = await navigator?.permissions?.query({name: 'geolocation'})
const hasPermission = permissionStatus?.state // Dynamic value

NOTE: This requires being in an async function

Default Value:

If you want to handle cases that fail, add an optional ?? myDefaultValue to the second line.

Links:

Yager answered 23/8, 2020 at 19:31 Comment(3)
kinda dupl of my own answer appart from all the ?Howarth
Good for show the use of Inline Null Check Tip: @babel/plugin-proposal-optional-chainingGonsalves
Remember that Safari does not support the web permissions API, so you will need a fallback for Apple devices.Collincolline
H
3

To fix the Firefox problem is really easy. In my case I save the geolocation in a global variable on Javascript called geolocation. Before use this variable, I just check if is not undefined, if so I just get the geolocation from the IP.

In my website I don't have any problem getting the location the first time, but I saw in my short example that never has time to get the geolocation on the first time because is too quick.

Anyway this is just an example, you should adapt it in each case.

var geolocation = {};
getLocation();

$(document).ready(function(){
    printLocation(); // First time, hasn't time to get the location
});

function printLocation(){
    if(typeof geolocation.lat === "undefined" || typeof geolocation.long === "undefined"){
        console.log("We cannot get the geolocation (too fast? user/browser blocked it?)");
        // Get location by IP or simply do nothing
    }
    else{
        console.log("LATITUDE => "+geolocation.lat);
        console.log("LONGITUDE => "+geolocation.long);
    }
}

function getLocation() {
    // If the user allow us to get the location from the browser
    if(window.location.protocol == "https:" && navigator.geolocation)
        navigator.geolocation.getCurrentPosition(function(position){
            geolocation["lat"] = position.coords.latitude;
            geolocation["long"] = position.coords.longitude;
            printLocation(); // Second time, will be return the location correctly
        });
    else{
        // We cannot access to the geolocation
    }
}

PS: I don't have enough reputation to comment the above answers so I had to create a new answer. Sorry about that.

Handiness answered 10/6, 2016 at 12:20 Comment(1)
Hello from 2018! Firefox 61 throws the proper error code when the user denies permission now.Wooer
A
2

navigator.geolocation.watchPosition(function(position) {
    console.log("i'm tracking you!");
  },
  function(error) {
    if (error.code == error.PERMISSION_DENIED)
      console.log("you denied me :-(");
  });
Antechoir answered 23/12, 2021 at 12:11 Comment(3)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Ambriz
If you only want a way to check if the location permission is granted/denied, this is not the right way to go. This sets up an unnecessary location watcher, when you should just be able to check once.Collincolline
It also asks for permission, I initially though this approach may get around that.Winonawinonah
D
2

Here is the react.js hook code:

import {useEffect, useState} from 'react';

export const useGetLocationPermissionStatus = () => {
  const [status, setStatus] = useState<'denied' | 'prompt' | 'granted'>('denied');
  useEffect(() => {
    navigator.permissions.query({name: 'geolocation'}).then((result) => {
      const newStatus = result.state;
      setStatus(newStatus);
      result.addEventListener('change', () => {
        setStatus(newStatus);
      });
    });
  }, []);
  return status;
};
Deferred answered 20/4, 2023 at 3:40 Comment(0)
C
1

I needed a way to check the status of the geolocation permission in my web app, so put together this helper function to do it for me.

This initially attempts the Web Permissions API, before falling back to calling the Geolocation API itself since Safari does not support the permissions API.

The helper is written in Typescript, but can be easily changed to JS.

/**
 * Checks the status of the geolocation permission asynchronously.
 *
 * Returns the permission status: `'denied'`, `'granted'`, or `'prompt'`.
 *
 * Includes a fallback for browsers which do not support the Web Permissions API.
 */
async function getGeolocationPermissionStatus(): Promise<'denied' | 'granted' | 'prompt'> {
  if ('permissions' in navigator) {
    return (await navigator.permissions.query({ name: 'geolocation' })).state
  }

  return new Promise(resolve => {
    navigator.geolocation.getCurrentPosition(
      // successfully got location
      () => resolve('granted'),
      error => {
        // permission denied
        if (error.code == error.PERMISSION_DENIED) resolve('denied')

        // some other error, but not one which is related to a denied permission
        resolve('granted')
      },
      {
        maximumAge: Infinity,
        timeout: 0,
      },
    )
  })
}
Collincolline answered 17/5, 2022 at 17:8 Comment(1)
Have you tested on a webview? On a native android app?Pantywaist
A
1

A short and fast copy paste answer:

function getNavGeo() {
  navigator.permissions.query({ name: "geolocation" }).then((result) => {
    if (result.state === "granted") {
      console.log('geo isON'); // Do your awesome stuff.
    } else if (result.state !== "granted") {
    console.log('geo isOFF');  // Don't do anything or something.
    } 
  });
}
//THEN:
getNavGeo();
Anuria answered 24/1 at 5:51 Comment(1)
Safari throws in a bit of confusion! Safary 17.5 will respond with state as prompt if it hasn't yet asked for permission or if the user's given permission but not checked the 'Remember for one day' option. If this checkbox is ticked when granting permission only then state will be granted.Misdo

© 2022 - 2024 — McMap. All rights reserved.