Merge branch 'master' of https://github.com/guillaumedev/cordova-plugin-geolocation
diff --git a/.gitignore b/.gitignore
index 52b558e..6964ea0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,7 +12,7 @@
*.swp
*.user
-
+node_modules
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..df32482
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,17 @@
+{
+ "browser": true
+ , "devel": true
+ , "bitwise": true
+ , "undef": true
+ , "trailing": true
+ , "quotmark": false
+ , "indent": 4
+ , "unused": "vars"
+ , "latedef": "nofunc"
+ , "globals": {
+ "module": false,
+ "exports": false,
+ "require": false,
+ "cordova": true
+ }
+}
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b9af4c5
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+sudo: false
+node_js:
+ - "4.2"
diff --git a/README.md b/README.md
index 74695ea..81b5bcf 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
+---
+title: Geolocation
+description: Access GPS data.
+---
<!--
# license: Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
@@ -17,6 +21,8 @@
# under the License.
-->
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-geolocation.svg?branch=master)](https://travis-ci.org/apache/cordova-plugin-geolocation)
+
# cordova-plugin-geolocation
This plugin provides information about the device's location, such as
@@ -43,7 +49,7 @@
so already). That notice should provide the same information noted
above, as well as obtaining the user's permission (e.g., by presenting
choices for __OK__ and __No Thanks__). For more information, please
-see the Privacy Guide.
+see the [Privacy Guide](http://cordova.apache.org/docs/en/latest/guide/appdev/privacy/index.html).
This plugin defines a global `navigator.geolocation` object (for platforms
where it is otherwise missing).
@@ -51,11 +57,15 @@
Although the object is in the global scope, features provided by this plugin
are not available until after the `deviceready` event.
+```javascript
+
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log("navigator.geolocation works well");
}
+```
+
## Installation
This requires cordova 5.0+ ( current stable 1.0.0 )
@@ -79,7 +89,6 @@
- iOS
- Tizen
- Windows Phone 7 and 8
-- Windows 8
- Windows
## Methods
@@ -116,6 +125,8 @@
### Example
+```javascript
+
// onSuccess Callback
// This method accepts a Position object, which contains the
// current GPS coordinates
@@ -140,6 +151,8 @@
navigator.geolocation.getCurrentPosition(onSuccess, onError);
+```
+
### Android Quirks
If Geolocation service is turned off the `onError` callback is invoked after `timeout` interval (if specified).
@@ -171,6 +184,8 @@
### Example
+```javascript
+
// onSuccess Callback
// This method accepts a `Position` object, which contains
// the current GPS coordinates
@@ -193,6 +208,7 @@
//
var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 });
+```
## geolocationOptions
@@ -227,6 +243,8 @@
### Example
+```javascript
+
// Options: watch for changes in position, and use the most
// accurate position acquisition method available.
//
@@ -236,6 +254,8 @@
navigator.geolocation.clearWatch(watchID);
+```
+
## Position
Contains `Position` coordinates and timestamp, created by the geolocation API.
@@ -295,3 +315,438 @@
- Returned when the device is unable to retrieve a position. In general, this means the device is not connected to a network or can't get a satellite fix.
- `PositionError.TIMEOUT`
- Returned when the device is unable to retrieve a position within the time specified by the `timeout` included in `geolocationOptions`. When used with `navigator.geolocation.watchPosition`, this error could be repeatedly passed to the `geolocationError` callback every `timeout` milliseconds.
+
+
+## <a id="sample"></a>Sample: Get the weather, find stores, and see photos of things nearby with Geolocation ##
+
+Use this plugin to help users find things near them such as Groupon deals, houses for sale, movies playing, sports and entertainment events and more.
+
+Here's a "cookbook" of ideas to get you started. In the snippets below, we'll show you some basic ways to add these features to your app.
+
+* [Get your coordinates](#coords).
+* [Get the weather forecast](#weather).
+* [Receive updated weather forecasts as you drive around](#receive).
+* [See where you are on a map](#see).
+* [Find stores near you](#find).
+* [See pictures of things around you](#see).
+
+## <a id="coord"></a>Get your geolocation coordinates
+
+```javascript
+
+function getWeatherLocation() {
+
+ navigator.geolocation.getCurrentPosition
+ (onWeatherSuccess, onWeatherError, { enableHighAccuracy: true });
+}
+
+```
+## <a id="weather"></a>Get the weather forecast
+
+```javascript
+
+// Success callback for get geo coordinates
+
+var onWeatherSuccess = function (position) {
+
+ Latitude = position.coords.latitude;
+ Longitude = position.coords.longitude;
+
+ getWeather(Latitude, Longitude);
+}
+
+// Get weather by using coordinates
+
+function getWeather(latitude, longitude) {
+
+ // Get a free key at http://openweathermap.org/. Replace the "Your_Key_Here" string with that key.
+ var OpenWeatherAppKey = "Your_Key_Here";
+
+ var queryString =
+ 'http://api.openweathermap.org/data/2.5/weather?lat='
+ + latitude + '&lon=' + longitude + '&appid=' + OpenWeatherAppKey + '&units=imperial';
+
+ $.getJSON(queryString, function (results) {
+
+ if (results.weather.length) {
+
+ $.getJSON(queryString, function (results) {
+
+ if (results.weather.length) {
+
+ $('#description').text(results.name);
+ $('#temp').text(results.main.temp);
+ $('#wind').text(results.wind.speed);
+ $('#humidity').text(results.main.humidity);
+ $('#visibility').text(results.weather[0].main);
+
+ var sunriseDate = new Date(results.sys.sunrise);
+ $('#sunrise').text(sunriseDate.toLocaleTimeString());
+
+ var sunsetDate = new Date(results.sys.sunrise);
+ $('#sunset').text(sunsetDate.toLocaleTimeString());
+ }
+
+ });
+ }
+ }).fail(function () {
+ console.log("error getting location");
+ });
+}
+
+// Error callback
+
+function onWeatherError(error) {
+ console.log('code: ' + error.code + '\n' +
+ 'message: ' + error.message + '\n');
+}
+
+```
+
+## <a id="receive"></a>Receive updated weather forecasts as you drive around
+
+```javascript
+
+// Watch your changing position
+
+function watchWeatherPosition() {
+
+ return navigator.geolocation.watchPosition
+ (onWeatherWatchSuccess, onWeatherError, { enableHighAccuracy: true });
+}
+
+// Success callback for watching your changing position
+
+var onWeatherWatchSuccess = function (position) {
+
+ var updatedLatitude = position.coords.latitude;
+ var updatedLongitude = position.coords.longitude;
+
+ if (updatedLatitude != Latitude && updatedLongitude != Longitude) {
+
+ Latitude = updatedLatitude;
+ Longitude = updatedLongitude;
+
+ // Calls function we defined earlier.
+ getWeather(updatedLatitude, updatedLongitude);
+ }
+}
+
+```
+
+## <a id="see"></a>See where you are on a map
+
+Both Bing and Google have map services. We'll use Google's. You'll need a key but it's free if you're just trying things out.
+
+Add a reference to the **maps** service.
+
+```HTML
+
+ <script src="https://maps.googleapis.com/maps/api/js?key=Your_API_Key"></script>
+
+```
+Then, add code to use it.
+
+```javascript
+
+var Latitude = undefined;
+var Longitude = undefined;
+
+// Get geo coordinates
+
+function getMapLocation() {
+
+ navigator.geolocation.getCurrentPosition
+ (onMapSuccess, onMapError, { enableHighAccuracy: true });
+}
+
+// Success callback for get geo coordinates
+
+var onMapSuccess = function (position) {
+
+ Latitude = position.coords.latitude;
+ Longitude = position.coords.longitude;
+
+ getMap(Latitude, Longitude);
+
+}
+
+// Get map by using coordinates
+
+function getMap(latitude, longitude) {
+
+ var mapOptions = {
+ center: new google.maps.LatLng(0, 0),
+ zoom: 1,
+ mapTypeId: google.maps.MapTypeId.ROADMAP
+ };
+
+ map = new google.maps.Map
+ (document.getElementById("map"), mapOptions);
+
+
+ var latLong = new google.maps.LatLng(latitude, longitude);
+
+ var marker = new google.maps.Marker({
+ position: latLong
+ });
+
+ marker.setMap(map);
+ map.setZoom(15);
+ map.setCenter(marker.getPosition());
+}
+
+// Success callback for watching your changing position
+
+var onMapWatchSuccess = function (position) {
+
+ var updatedLatitude = position.coords.latitude;
+ var updatedLongitude = position.coords.longitude;
+
+ if (updatedLatitude != Latitude && updatedLongitude != Longitude) {
+
+ Latitude = updatedLatitude;
+ Longitude = updatedLongitude;
+
+ getMap(updatedLatitude, updatedLongitude);
+ }
+}
+
+// Error callback
+
+function onMapError(error) {
+ console.log('code: ' + error.code + '\n' +
+ 'message: ' + error.message + '\n');
+}
+
+// Watch your changing position
+
+function watchMapPosition() {
+
+ return navigator.geolocation.watchPosition
+ (onMapWatchSuccess, onMapError, { enableHighAccuracy: true });
+}
+
+```
+
+## <a id="find"></a>Find stores near you
+
+You can use the same Google key for this.
+
+Add a reference to the **places** service.
+
+```HTML
+
+<script src=
+"https://maps.googleapis.com/maps/api/js?key=Your_API_Key&libraries=places">
+</script>
+
+```
+
+Then, add code to use it.
+
+```javascript
+
+var Map;
+var Infowindow;
+var Latitude = undefined;
+var Longitude = undefined;
+
+// Get geo coordinates
+
+function getPlacesLocation() {
+ navigator.geolocation.getCurrentPosition
+ (onPlacesSuccess, onPlacesError, { enableHighAccuracy: true });
+}
+
+// Success callback for get geo coordinates
+
+var onPlacesSuccess = function (position) {
+
+ Latitude = position.coords.latitude;
+ Longitude = position.coords.longitude;
+
+ getPlaces(Latitude, Longitude);
+
+}
+
+// Get places by using coordinates
+
+function getPlaces(latitude, longitude) {
+
+ var latLong = new google.maps.LatLng(latitude, longitude);
+
+ var mapOptions = {
+
+ center: new google.maps.LatLng(latitude, longitude),
+ zoom: 15,
+ mapTypeId: google.maps.MapTypeId.ROADMAP
+
+ };
+
+ Map = new google.maps.Map(document.getElementById("places"), mapOptions);
+
+ Infowindow = new google.maps.InfoWindow();
+
+ var service = new google.maps.places.PlacesService(Map);
+ service.nearbySearch({
+
+ location: latLong,
+ radius: 500,
+ type: ['store']
+ }, foundStoresCallback);
+
+}
+
+// Success callback for watching your changing position
+
+var onPlacesWatchSuccess = function (position) {
+
+ var updatedLatitude = position.coords.latitude;
+ var updatedLongitude = position.coords.longitude;
+
+ if (updatedLatitude != Latitude && updatedLongitude != Longitude) {
+
+ Latitude = updatedLatitude;
+ Longitude = updatedLongitude;
+
+ getPlaces(updatedLatitude, updatedLongitude);
+ }
+}
+
+// Success callback for locating stores in the area
+
+function foundStoresCallback(results, status) {
+
+ if (status === google.maps.places.PlacesServiceStatus.OK) {
+
+ for (var i = 0; i < results.length; i++) {
+
+ createMarker(results[i]);
+
+ }
+ }
+}
+
+// Place a pin for each store on the map
+
+function createMarker(place) {
+
+ var placeLoc = place.geometry.location;
+
+ var marker = new google.maps.Marker({
+ map: Map,
+ position: place.geometry.location
+ });
+
+ google.maps.event.addListener(marker, 'click', function () {
+
+ Infowindow.setContent(place.name);
+ Infowindow.open(Map, this);
+
+ });
+}
+
+// Error callback
+
+function onPlacesError(error) {
+ console.log('code: ' + error.code + '\n' +
+ 'message: ' + error.message + '\n');
+}
+
+// Watch your changing position
+
+function watchPlacesPosition() {
+
+ return navigator.geolocation.watchPosition
+ (onPlacesWatchSuccess, onPlacesError, { enableHighAccuracy: true });
+}
+
+```
+
+## <a id="pictures"></a>See pictures of things around you
+
+Digital photos can contain geo coordinates that identify where the picture was taken.
+
+Use Flickr API's to find pictures that folks have taken near you. Like Google services, you'll need a key, but it's free if you just want to try things out.
+
+```javascript
+
+var Latitude = undefined;
+var Longitude = undefined;
+
+// Get geo coordinates
+
+function getPicturesLocation() {
+
+ navigator.geolocation.getCurrentPosition
+ (onPicturesSuccess, onPicturesError, { enableHighAccuracy: true });
+
+}
+
+// Success callback for get geo coordinates
+
+var onPicturesSuccess = function (position) {
+
+ Latitude = position.coords.latitude;
+ Longitude = position.coords.longitude;
+
+ getPictures(Latitude, Longitude);
+}
+
+// Get pictures by using coordinates
+
+function getPictures(latitude, longitude) {
+
+ $('#pictures').empty();
+
+ var queryString =
+ "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=Your_API_Key&lat="
+ + latitude + "&lon=" + longitude + "&format=json&jsoncallback=?";
+
+ $.getJSON(queryString, function (results) {
+ $.each(results.photos.photo, function (index, item) {
+
+ var photoURL = "http://farm" + item.farm + ".static.flickr.com/" +
+ item.server + "/" + item.id + "_" + item.secret + "_m.jpg";
+
+ $('#pictures').append($("<img />").attr("src", photoURL));
+
+ });
+ }
+ );
+}
+
+// Success callback for watching your changing position
+
+var onPicturesWatchSuccess = function (position) {
+
+ var updatedLatitude = position.coords.latitude;
+ var updatedLongitude = position.coords.longitude;
+
+ if (updatedLatitude != Latitude && updatedLongitude != Longitude) {
+
+ Latitude = updatedLatitude;
+ Longitude = updatedLongitude;
+
+ getPictures(updatedLatitude, updatedLongitude);
+ }
+}
+
+// Error callback
+
+function onPicturesError(error) {
+
+ console.log('code: ' + error.code + '\n' +
+ 'message: ' + error.message + '\n');
+}
+
+// Watch your changing position
+
+function watchPicturePosition() {
+
+ return navigator.geolocation.watchPosition
+ (onPicturesWatchSuccess, onPicturesError, { enableHighAccuracy: true });
+}
+
+```
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index d291197..8acb569 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -20,6 +20,13 @@
-->
# Release Notes
+### 2.2.0 (Apr 15, 2016)
+* Replace `PermissionHelper.java` with `cordova-plugin-compat`
+* CB-10691 Check the context to avoid null errors
+* CB-10636 Add `JSHint` for plugins
+* Using a fallback epsilon in case `Number.EPSILON` is not defined.
+* CB-10574 MobileSpec can't get results for **WP8.1** Builds
+
### 2.1.0 (Jan 15, 2016)
* CB-10319 **Android** Adding reflective helper methods for permission requests
* CB-8523 Fixed accuracy when `enableHighAccuracy: false` on **iOS**.
diff --git a/package.json b/package.json
index ba6e4f7..347d2dc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-geolocation",
- "version": "2.1.1-dev",
+ "version": "2.2.1-dev",
"description": "Cordova Geolocation Plugin",
"cordova": {
"id": "cordova-plugin-geolocation",
@@ -36,6 +36,13 @@
"cordova-windows",
"cordova-firefoxos"
],
+ "scripts": {
+ "test": "npm run jshint",
+ "jshint": "node node_modules/jshint/bin/jshint www && node node_modules/jshint/bin/jshint src && node node_modules/jshint/bin/jshint tests"
+ },
"author": "Apache Software Foundation",
- "license": "Apache 2.0"
+ "license": "Apache-2.0",
+ "devDependencies": {
+ "jshint": "^2.6.0"
+ }
}
diff --git a/plugin.xml b/plugin.xml
index b5e1ad7..c312813 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -22,7 +22,7 @@
xmlns:rim="http://www.blackberry.com/ns/widgets"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-geolocation"
- version="2.1.1-dev">
+ version="2.2.1-dev">
<name>Geolocation</name>
<description>Cordova Geolocation Plugin</description>
@@ -31,6 +31,8 @@
<repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-geolocation.git</repo>
<issue>https://issues.apache.org/jira/browse/CB/component/12320638</issue>
+ <dependency id="cordova-plugin-compat" version="^1.0.0" />
+
<!-- android -->
<platform name="android">
@@ -46,7 +48,6 @@
</config-file>
<source-file src="src/android/Geolocation.java" target-dir="src/org/apache/cordova/geolocation/" />
- <source-file src="src/android/PermissionHelper.java" target-dir="src/org/apache/cordova/geolocation/" />
<js-module src="www/android/geolocation.js" name="geolocation">
<clobbers target="navigator.geolocation" />
diff --git a/src/android/Geolocation.java b/src/android/Geolocation.java
index 79f0684..3e0bd8a 100644
--- a/src/android/Geolocation.java
+++ b/src/android/Geolocation.java
@@ -21,10 +21,12 @@
import android.content.pm.PackageManager;
import android.Manifest;
import android.os.Build;
+import android.util.Log;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;
import org.apache.cordova.LOG;
import org.json.JSONArray;
@@ -41,6 +43,7 @@
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+ Log.d(TAG, "We are entering execute");
context = callbackContext;
if(action.equals("getPermission"))
{
@@ -63,18 +66,20 @@
int[] grantResults) throws JSONException
{
PluginResult result;
- for(int r:grantResults)
- {
- if(r == PackageManager.PERMISSION_DENIED)
- {
- LOG.d(TAG, "Permission Denied!");
- result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
- context.sendPluginResult(result);
- return;
+ //This is important if we're using Cordova without using Cordova, but we have the geolocation plugin installed
+ if(context != null) {
+ for (int r : grantResults) {
+ if (r == PackageManager.PERMISSION_DENIED) {
+ LOG.d(TAG, "Permission Denied!");
+ result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
+ context.sendPluginResult(result);
+ return;
+ }
+
}
+ result = new PluginResult(PluginResult.Status.OK);
+ context.sendPluginResult(result);
}
- result = new PluginResult(PluginResult.Status.OK);
- context.sendPluginResult(result);
}
public boolean hasPermisssion() {
diff --git a/src/android/PermissionHelper.java b/src/android/PermissionHelper.java
deleted file mode 100644
index 4a3ca2d..0000000
--- a/src/android/PermissionHelper.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.geolocation;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.LOG;
-
-import android.content.pm.PackageManager;
-
-/**
- * This class provides reflective methods for permission requesting and checking so that plugins
- * written for cordova-android 5.0.0+ can still compile with earlier cordova-android versions.
- */
-public class PermissionHelper {
- private static final String LOG_TAG = "CordovaPermissionHelper";
-
- /**
- * Requests a "dangerous" permission for the application at runtime. This is a helper method
- * alternative to cordovaInterface.requestPermission() that does not require the project to be
- * built with cordova-android 5.0.0+
- *
- * @param plugin The plugin the permission is being requested for
- * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult()
- * along with the result of the permission request
- * @param permission The permission to be requested
- */
- public static void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
- PermissionHelper.requestPermissions(plugin, requestCode, new String[] {permission});
- }
-
- /**
- * Requests "dangerous" permissions for the application at runtime. This is a helper method
- * alternative to cordovaInterface.requestPermissions() that does not require the project to be
- * built with cordova-android 5.0.0+
- *
- * @param plugin The plugin the permissions are being requested for
- * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult()
- * along with the result of the permissions request
- * @param permissions The permissions to be requested
- */
- public static void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) {
- try {
- Method requestPermission = CordovaInterface.class.getDeclaredMethod(
- "requestPermissions", CordovaPlugin.class, int.class, String[].class);
-
- // If there is no exception, then this is cordova-android 5.0.0+
- requestPermission.invoke(plugin.cordova, plugin, requestCode, permissions);
- } catch (NoSuchMethodException noSuchMethodException) {
- // cordova-android version is less than 5.0.0, so permission is implicitly granted
- LOG.d(LOG_TAG, "No need to request permissions " + Arrays.toString(permissions));
-
- // Notify the plugin that all were granted by using more reflection
- deliverPermissionResult(plugin, requestCode, permissions);
- } catch (IllegalAccessException illegalAccessException) {
- // Should never be caught; this is a public method
- LOG.e(LOG_TAG, "IllegalAccessException when requesting permissions " + Arrays.toString(permissions), illegalAccessException);
- } catch(InvocationTargetException invocationTargetException) {
- // This method does not throw any exceptions, so this should never be caught
- LOG.e(LOG_TAG, "invocationTargetException when requesting permissions " + Arrays.toString(permissions), invocationTargetException);
- }
- }
-
- /**
- * Checks at runtime to see if the application has been granted a permission. This is a helper
- * method alternative to cordovaInterface.hasPermission() that does not require the project to
- * be built with cordova-android 5.0.0+
- *
- * @param plugin The plugin the permission is being checked against
- * @param permission The permission to be checked
- *
- * @return True if the permission has already been granted and false otherwise
- */
- public static boolean hasPermission(CordovaPlugin plugin, String permission) {
- try {
- Method hasPermission = CordovaInterface.class.getDeclaredMethod("hasPermission", String.class);
-
- // If there is no exception, then this is cordova-android 5.0.0+
- return (Boolean) hasPermission.invoke(plugin.cordova, permission);
- } catch (NoSuchMethodException noSuchMethodException) {
- // cordova-android version is less than 5.0.0, so permission is implicitly granted
- LOG.d(LOG_TAG, "No need to check for permission " + permission);
- return true;
- } catch (IllegalAccessException illegalAccessException) {
- // Should never be caught; this is a public method
- LOG.e(LOG_TAG, "IllegalAccessException when checking permission " + permission, illegalAccessException);
- } catch(InvocationTargetException invocationTargetException) {
- // This method does not throw any exceptions, so this should never be caught
- LOG.e(LOG_TAG, "invocationTargetException when checking permission " + permission, invocationTargetException);
- }
- return false;
- }
-
- private static void deliverPermissionResult(CordovaPlugin plugin, int requestCode, String[] permissions) {
- // Generate the request results
- int[] requestResults = new int[permissions.length];
- Arrays.fill(requestResults, PackageManager.PERMISSION_GRANTED);
-
- try {
- Method onRequestPermissionResult = CordovaPlugin.class.getDeclaredMethod(
- "onRequestPermissionResult", int.class, String[].class, int[].class);
-
- onRequestPermissionResult.invoke(plugin, requestCode, permissions, requestResults);
- } catch (NoSuchMethodException noSuchMethodException) {
- // Should never be caught since the plugin must be written for cordova-android 5.0.0+ if it
- // made it to this point
- LOG.e(LOG_TAG, "NoSuchMethodException when delivering permissions results", noSuchMethodException);
- } catch (IllegalAccessException illegalAccessException) {
- // Should never be caught; this is a public method
- LOG.e(LOG_TAG, "IllegalAccessException when delivering permissions results", illegalAccessException);
- } catch(InvocationTargetException invocationTargetException) {
- // This method may throw a JSONException. We are just duplicating cordova-android's
- // exception handling behavior here; all it does is log the exception in CordovaActivity,
- // print the stacktrace, and ignore it
- LOG.e(LOG_TAG, "InvocationTargetException when delivering permissions results", invocationTargetException);
- }
- }
-}
diff --git a/src/windows/GeolocationProxy.js b/src/windows/GeolocationProxy.js
index f6188bc..03ed495 100644
--- a/src/windows/GeolocationProxy.js
+++ b/src/windows/GeolocationProxy.js
@@ -14,47 +14,48 @@
* limitations under the License.
*/
-var PositionError = require('./PositionError'),
- ids = {},
- loc;
+/* global Windows, WinJS */
-function ensureLocator() {
+var PositionError = require('./PositionError');
+var callbacks = {};
+var locs = {};
+
+// constants
+var FALLBACK_EPSILON = 0.001;
+
+function ensureAndCreateLocator() {
var deferral;
- if (!loc) {
- loc = new Windows.Devices.Geolocation.Geolocator();
+ var loc = new Windows.Devices.Geolocation.Geolocator();
- if (typeof Windows.Devices.Geolocation.Geolocator.requestAccessAsync === 'function') {
- deferral = Windows.Devices.Geolocation.Geolocator.requestAccessAsync().then(function (result) {
- if (result === Windows.Devices.Geolocation.GeolocationAccessStatus.allowed) {
- return loc;
- }
+ if (typeof Windows.Devices.Geolocation.Geolocator.requestAccessAsync === 'function') {
+ deferral = Windows.Devices.Geolocation.Geolocator.requestAccessAsync().then(function (result) {
+ if (result === Windows.Devices.Geolocation.GeolocationAccessStatus.allowed) {
+ return loc;
+ }
- return WinJS.Promise.wrapError({
- code: PositionError.PERMISSION_DENIED,
- message: 'Geolocation access has not been allowed by user.'
- });
+ return WinJS.Promise.wrapError({
+ code: PositionError.PERMISSION_DENIED,
+ message: 'Geolocation access has not been allowed by user.'
});
- } else {
- deferral = WinJS.Promise.wrap(loc);
- }
+ });
} else {
deferral = WinJS.Promise.wrap(loc);
- }
+ }
return deferral;
}
-function createErrorCode() {
+function createErrorCode(loc) {
switch (loc.locationStatus) {
case Windows.Devices.Geolocation.PositionStatus.initializing:
// This status indicates that a location device is still initializing
case Windows.Devices.Geolocation.PositionStatus.noData:
- // No location data is currently available
+ // No location data is currently available
case Windows.Devices.Geolocation.PositionStatus.notInitialized:
// This status indicates that the app has not yet requested
- // location data by calling GetGeolocationAsync() or
- // registering an event handler for the positionChanged event.
+ // location data by calling GetGeolocationAsync() or
+ // registering an event handler for the positionChanged event.
case Windows.Devices.Geolocation.PositionStatus.notAvailable:
// Location is not available on this version of Windows
return PositionError.POSITION_UNAVAILABLE;
@@ -76,7 +77,7 @@
altitudeAccuracy: pos.coordinate.altitudeAccuracy,
timestamp: pos.coordinate.timestamp
};
-
+
if (pos.coordinate.point) {
res.latitude = pos.coordinate.point.position.latitude;
res.longitude = pos.coordinate.point.position.longitude;
@@ -86,13 +87,13 @@
res.longitude = pos.coordinate.longitude;
res.altitude = pos.coordinate.altitude;
}
-
+
return res;
}
module.exports = {
getLocation: function (success, fail, args, env) {
- ensureLocator().done(function () {
+ ensureAndCreateLocator().done(function (loc) {
if (loc) {
var highAccuracy = args[0],
maxAge = args[1];
@@ -109,7 +110,7 @@
},
function (err) {
fail({
- code: createErrorCode(),
+ code: createErrorCode(loc),
message: err.message
});
}
@@ -125,15 +126,15 @@
},
addWatch: function (success, fail, args, env) {
- ensureLocator().done(function () {
- var clientId = args[0],
- highAccuracy = args[1],
+ ensureAndCreateLocator().done(function (loc) {
+ var clientId = args[0];
+ var highAccuracy = args[1];
- onPositionChanged = function (e) {
+ var onPositionChanged = function (e) {
success(createResult(e.position), { keepCallback: true });
- },
+ };
- onStatusChanged = function (e) {
+ var onStatusChanged = function (e) {
switch (e.status) {
case Windows.Devices.Geolocation.PositionStatus.noData:
case Windows.Devices.Geolocation.PositionStatus.notAvailable:
@@ -166,29 +167,36 @@
// JavaScript runtime error: Operation aborted
// You must set the MovementThreshold property or the ReportInterval property before adding event handlers.
// WinRT information: You must set the MovementThreshold property or the ReportInterval property before adding event handlers
- loc.movementThreshold = Number.EPSILON;
+ if (Number.EPSILON) {
+ loc.movementThreshold = Number.EPSILON;
+ } else {
+ loc.movementThreshold = FALLBACK_EPSILON;
+ }
}
loc.addEventListener("positionchanged", onPositionChanged);
loc.addEventListener("statuschanged", onStatusChanged);
- ids[clientId] = { pos: onPositionChanged, status: onStatusChanged };
- }, fail);
+ callbacks[clientId] = { pos: onPositionChanged, status: onStatusChanged };
+ locs[clientId] = loc;
+ }, fail);
},
clearWatch: function (success, fail, args, env) {
- var clientId = args[0],
- callbacks = ids[clientId];
+ var clientId = args[0];
+ var callback = callbacks[clientId];
+ var loc = locs[clientId];
- if (callbacks) {
- loc.removeEventListener("positionchanged", callbacks.pos);
- loc.removeEventListener("statuschanged", callbacks.status);
+ if (callback && loc) {
+ loc.removeEventListener("positionchanged", callback.pos);
+ loc.removeEventListener("statuschanged", callback.status);
- delete ids[clientId];
+ delete callbacks[clientId];
+ delete locs[clientId];
}
success();
}
};
-require("cordova/exec/proxy").add("Geolocation", module.exports);
\ No newline at end of file
+require("cordova/exec/proxy").add("Geolocation", module.exports);
diff --git a/tests/plugin.xml b/tests/plugin.xml
index 255a939..0a5a009 100644
--- a/tests/plugin.xml
+++ b/tests/plugin.xml
@@ -22,7 +22,7 @@
xmlns:rim="http://www.blackberry.com/ns/widgets"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-geolocation-tests"
- version="2.1.1-dev">
+ version="2.2.1-dev">
<name>Cordova Geolocation Plugin Tests</name>
<license>Apache 2.0</license>
diff --git a/tests/tests.js b/tests/tests.js
index 65a9c69..50c5bfb 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -18,6 +18,10 @@
* under the License.
*
*/
+
+/* jshint jasmine: true */
+/* global WinJS, device */
+
exports.defineAutoTests = function () {
var fail = function (done, context, message) {
// prevents done() to be called several times
@@ -267,6 +271,40 @@
var watchLocationId = null;
/**
+ * Set location status
+ */
+ function setLocationStatus(status) {
+ document.getElementById('location_status').innerHTML = status;
+ }
+ function setLocationDetails(p) {
+ var date = (new Date(p.timestamp));
+ document.getElementById('latitude').innerHTML = p.coords.latitude;
+ document.getElementById('longitude').innerHTML = p.coords.longitude;
+ document.getElementById('altitude').innerHTML = p.coords.altitude;
+ document.getElementById('accuracy').innerHTML = p.coords.accuracy;
+ document.getElementById('heading').innerHTML = p.coords.heading;
+ document.getElementById('speed').innerHTML = p.coords.speed;
+ document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy;
+ document.getElementById('timestamp').innerHTML = date.toDateString() + " " + date.toTimeString();
+ }
+
+ /**
+ * Stop watching the location
+ */
+ function stopLocation() {
+ var geo = navigator.geolocation;
+ if (!geo) {
+ alert('navigator.geolocation object is missing.');
+ return;
+ }
+ setLocationStatus("Stopped");
+ if (watchLocationId) {
+ geo.clearWatch(watchLocationId);
+ watchLocationId = null;
+ }
+ }
+
+ /**
* Start watching location
*/
var watchLocation = function () {
@@ -293,22 +331,6 @@
};
/**
- * Stop watching the location
- */
- var stopLocation = function () {
- var geo = navigator.geolocation;
- if (!geo) {
- alert('navigator.geolocation object is missing.');
- return;
- }
- setLocationStatus("Stopped");
- if (watchLocationId) {
- geo.clearWatch(watchLocationId);
- watchLocationId = null;
- }
- };
-
- /**
* Get current location
*/
var getLocation = function (opts) {
@@ -340,24 +362,6 @@
};
- /**
- * Set location status
- */
- var setLocationStatus = function (status) {
- document.getElementById('location_status').innerHTML = status;
- };
- var setLocationDetails = function (p) {
- var date = (new Date(p.timestamp));
- document.getElementById('latitude').innerHTML = p.coords.latitude;
- document.getElementById('longitude').innerHTML = p.coords.longitude;
- document.getElementById('altitude').innerHTML = p.coords.altitude;
- document.getElementById('accuracy').innerHTML = p.coords.accuracy;
- document.getElementById('heading').innerHTML = p.coords.heading;
- document.getElementById('speed').innerHTML = p.coords.speed;
- document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy;
- document.getElementById('timestamp').innerHTML = date.toDateString() + " " + date.toTimeString();
- };
-
/******************************************************************************/
var location_div = '<div id="info">' +
@@ -423,8 +427,8 @@
note =
'<h3>Allow use of current location, if prompted</h3>';
- contentEl.innerHTML = values_info + location_div + latitude + longitude + altitude + accuracy + heading + speed
- + altitude_accuracy + time + note + actions;
+ contentEl.innerHTML = values_info + location_div + latitude + longitude + altitude + accuracy + heading + speed +
+ altitude_accuracy + time + note + actions;
createActionButton('Get Location', function () {
getLocation();
diff --git a/www/android/geolocation.js b/www/android/geolocation.js
index 57b8122..7265bec 100644
--- a/www/android/geolocation.js
+++ b/www/android/geolocation.js
@@ -19,13 +19,15 @@
*
*/
-
var exec = cordova.require('cordova/exec');
var utils = require('cordova/utils');
var PositionError = require('./PositionError');
-module.exports = {
+// Native watchPosition method is called async after permissions prompt.
+// So we use additional map and own ids to return watch id synchronously.
+var pluginToNativeWatchMap = {};
+module.exports = {
getCurrentPosition: function(success, error, args) {
var win = function() {
var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation');
@@ -67,7 +69,3 @@
exec(win, null, "Geolocation", "getPermission", []);
}
};
-
-// Native watchPosition method is called async after permissions prompt.
-// So we use additional map and own ids to return watch id synchronously.
-var pluginToNativeWatchMap = {};