navigator.geolocation.getCurrentPosition() never returns in WebView on Android

后端 未结 8 1268
萌比男神i
萌比男神i 2021-02-18 16:27

I am trying to access the HTML Geolocation API available in Android WebView (using SDK version 24).

The main problem is that the call to navigator.geolocat

相关标签:
8条回答
  • 2021-02-18 16:58

    Actually, navigator is a child of browser global object, the window. you should first access to window then call the navigator. In some modern browsers, In addition to the window, some child object is presented like a global object, for example: location, navigator and etc.

    The WebView has no global object window. So you can add it manually, for this action please read this medium article.

    Maybe your code will be like below:

    my_web_view.evaluateJavascript("javascript: " + "updateFromAndroid(\"" + edit_text_to_web.text + "\")", null);
    

    And then add JavaScript interface, like the window object, to this evaluator:

    my_web_view.addJavascriptInterface(JavaScriptInterface(), JAVASCRIPT_OBJ); //JAVASCRIPT_OBJ: like window, like navigator, like location and etc.
    
    0 讨论(0)
  • 2021-02-18 16:59

    I experienced this problem on Android 8. The error callback was called with error.code==1 "PERMISSION_DENIED".

    https://developers.google.com/web/updates/2016/04/geolocation-on-secure-contexts-only Geolocation API Removed from Unsecured Origins in Chrome 50

    Meaning, the URL of your app must begin with https:// for the call to work.

    0 讨论(0)
  • 2021-02-18 17:02

    In case some of you are still experiencing this issue, I was able to get the navigator.geolocation.getCurrentPosition() to work for me by setting some values for the options parameter, as follows:

    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(  
          async (p) => {
            await this.workMyCurrentPosition(p);
          },
          (e) => this.navigatorError(e),
          { timeout: 7000, enableHighAccuracy: true, maximumAge: 0 }
        );
    }
    

    Hope it works for you!

    0 讨论(0)
  • 2021-02-18 17:05

    Try with options to set timeout (source):

    var options = {
        enableHighAccuracy: true,
        timeout: 10000,
        maximumAge: 0
    };
    
    navigator.geolocation.getCurrentPosition(success, error, options);
    

    If it fails then try to override getCurrentPosition (source):

    (function() {
    
    if (navigator.geolocation) {
        function PositionError(code, message) {
            this.code = code;
            this.message = message;
        }
    
        PositionError.PERMISSION_DENIED = 1;
        PositionError.POSITION_UNAVAILABLE = 2;
        PositionError.TIMEOUT = 3;
        PositionError.prototype = new Error();
    
        navigator.geolocation._getCurrentPosition = navigator.geolocation.getCurrentPosition;
    
        navigator.geolocation.getCurrentPosition = function(success, failure, options) {
            var successHandler = function(position) {
                if ((position.coords.latitude == 0 && position.coords.longitude == 0) ||
                    (position.coords.latitude == 37.38600158691406 && position.coords.longitude == -122.08200073242188)) 
                    return failureHandler(new PositionError(PositionError.POSITION_UNAVAILABLE, 'Position unavailable')); 
    
                failureHandler = function() {};
                success(position);
            }
    
            var failureHandler = function(error) {
                failureHandler = function() {};
                failure(error);
            }
    
            navigator.geolocation._getCurrentPosition(successHandler, failureHandler, options);
    
            window.setTimeout(function() { failureHandler(new PositionError(PositionError.TIMEOUT, 'Timed out')) }, 10000);
        }
    }
    })();
    

    As a third option annotate with @JavascriptInterface (source) in EmbeddedChromeClient

    Also add at the proper place in your code:

    mWebSettings.setJavaScriptEnabled(true);
    //...
    mWebSettings.setSupportZoom(true);
    webView.addJavascriptInterface(new EmbeddedChromeClient(webView), "injectedObject");
    webView.loadData("html here", "text/html", null);
    

    The last option is just to use tags in html, load the html from disk storage, replace tags in the calling function, load the html/string in the webView. I have used this approach before in Android when positioning frustrated me too much. Then you don't have to worry about https either.

    0 讨论(0)
  • 2021-02-18 17:16

    Change your request for permission like this,

    ActivityCompat.requestPermissions(this, new String[]{
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION
        },0);
    

    This seems to work.

    0 讨论(0)
  • 2021-02-18 17:23

    There is an extensive post on this subject:

    navigator.geolocation.getCurrentPosition sometimes works sometimes doesn't

    Apparently the solution is to check on navigator.geolocation then make the call:

    if(navigator.geolocation) { // dummy call
        navigator.geolocation.getCurrentPosition(success, error)
    }
    
    0 讨论(0)
提交回复
热议问题