Search code examples
ioscordovageolocationphonegap-buildcordova-plugins

Cordova/Phonegap Build geolocation on iOS timeout


I have been experiencing the same issue, and have tried in the past 2 weeks numerous solutions found online for this with no success, any help appreciated :)

I am writing a simple app using Cordova for IOS and Android and building it using Phonegap build. The problem is that I cannot get the "navigator.geolocation.getCurrentPosition" (or navigator.geolocation.watchPosition) calls to return anything except a timeout error on iOS. (works perfectly on Android)

Additionally, the location services dialog never appears (requesting user permission to allow GPS for the app)

To add to this strange behavior, it seems that i have to touch the screen after the app is loaded to initiate the geolocation call, on most cases the app just sits there and does nothing until the screen is touched.

Testing this on iPhone 5 with iOS 9

Things I tried:

  1. Changing timeout settings (up to 30 seconds)
  2. Setting enableHighAccuracy true/false
  3. Running code with or without the geolocation plugin
  4. Manually adding the NSLocationWhenInUseUsageDescription/NSLocationAlwaysUsageDescription settings (or both) to the plist file
  5. Installing different plugin versions for the geolocation plugin
  6. Changing Content Security Policy meta tag
  7. Trying to add or remove the <plugin> declaration from root config.xml

Current plugins installed ($cordova plugin list):

cordova-plugin-dialogs 1.2.0 "Notification"
cordova-plugin-geolocation 1.0.1 "Geolocation"
cordova-plugin-whitelist 1.2.0 "Whitelist"
cordova.plugins.diagnostic 2.3.5 "Diagnostic"

Root config.xml:

<?xml version='1.0' encoding='utf-8'?>
<widget id="info.test" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>App name</name>
    <description>
        App Name
    </description>
    <author email="[email protected]" href="http://test.com">
        App Team
    </author>
    <content src="index.html" />
    <plugin name="cordova-plugin-whitelist" spec="1" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <platform name="android">
        <allow-intent href="market:*" />
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
</widget>

index.js

var geo = {
    getGeo: function() {        
        navigator.geolocation.getCurrentPosition(
              geo.onSuccess,
              geo.onError,
              {maximumAge:0, timeout: 5000, enableHighAccuracy: false});        

    },
    onSuccess: function(position) {
        alert('GOT location');

        alert(position.coords.latitude + ' --- ' + position.coords.longitude);
    },
    onError: function(error) {
        alert('error getting geo!');
    }   
};

 var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
        geo.getGeo();
    }
};

app.initialize();

iOS Plist file:

    <key>NSLocationAlwaysUsageDescription</key>
    <string>This app requires constant access to your location in order to track your position, even when the screen is off.</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string/>

Index.html:

<html>
    <head>
        <!--
        Customize this policy to fit your own app's needs. For more guidance, see:
            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
        Some notes:
            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
                * Enable inline JS: add 'unsafe-inline' to default-src
        -->
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Hello World</title>
    </head>
    <body>
        <div class="app">
            <h1>Apache Cordova</h1>
            <div id="deviceready" class="blink">
                <p class="event listening">Connecting to Device</p>
                <p class="event received">Device is Ready</p>
            </div>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Any help in the right direction appreciated!


Solution

  • @daddio
    Oh. that's it. I should be more dogmatic on this. This should take care of the problem.

    It is not advisable to use Phonegap CLI to make your Phonegap Build build project. Phonegap build requires that index.html and config.xml both sit in the root directory. All the extra files that you are required to use with Phonegap CLI, never are created or needed with Phonegap Build.

    So, I'm going to give you one of my working demos. Notice that all the files are in one (1) directory.

    Notice how the compiler version is set to:

    <preference name="phonegap-version" value="cli-5.2.0" />

    Notice, if you change cli-5.2.0 to 3.7.0, nothing appears to change.

    Basically for Phonegap Build, you need index.html and config.xml - that's it. Then for security reasons (as of Cordova Tools 5.0.0), it is advisable to create a css file and a javascript file. However, I'll show you how to get around this.

    Here is my complete list of Demo Apps.

    YOUR FIX

    This is my working code, test with 3.5.0 and cli-5.1.1 and cli5.2.0

    On Your fix, notice how the version is set to: <preference name="phonegap-version" value="3.5.0" />

    Okay, I trust all of this will work for you. As such, your documentation is here: https://build.phonegap.com/docs

    There are some special rules for adding plugins, but I'll give you those when your program is running.

    How to add Plugins with Phonegap Build

    1. FOR THE MOST IMMEDIATE FUTURE, get your *core* plugins from this list: http://cordova.apache.org/docs/en/5.4.0/cordova/plugins/pluginapis.html

    2. Get your 3rd-party plugin from this source: http://cordova.apache.org/plugins/

    3. When using Phonegap Build, sometimes the pluins get fixed (or updated) and this breaks Phonegap Build. This is because the "fixes" require the latest version of the compiler, and Phonegap Build is always at least one version behind.

    There are two ways to deal with 3; see 4 and 5.

    1. I have created this Worksheet. You may want to make a copy or just use it as a reference. I use this worksheet to create my demos, I so know the list is good. I am working on cli-5.2.0 right now. (Should finish by Monday or so.) However, I do not test ALL 3rd-party plugins; there are 800+ plugins.

    2. If you fail to set the version number on a plugin, you will get the latest version. If your build fails, then set the version. If the build still fails, try the previous two or three version to find one that works. NOTE, these older plugins may have bugs that prevent you from using them. So, try an even earlier version.

    Lastly, if you think you have hit a bug, then here is a page with links to the Bug respository for each plugin. Last Update is on the top left. Best of Luck.