From e7846f4754218fb36c9844e8a07efd37e5815add Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Sat, 25 Feb 2017 13:31:48 +0100 Subject: [PATCH] Pebble: override the native navigator.geolocation GetCurrentPosition The native method requires FINE location permission, and we don't have it. Further we should handle the runtime permission request. --- .../app_config/js/gadgetbridge_boilerplate.js | 6 ++ .../activities/ExternalPebbleJSActivity.java | 56 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js b/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js index caf39669f..58afa1095 100644 --- a/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js +++ b/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js @@ -1,3 +1,9 @@ +navigator.geolocation.getCurrentPosition = function(success, failure) { //override because default implementation requires GPS permission + success(JSON.parse(GBjs.getCurrentPosition())); + failure({ code: 2, message: "POSITION_UNAVAILABLE"}); + +} + if (window.Storage){ var prefix = GBjs.getAppLocalstoragePrefix(); GBjs.gbLog("redefining local storage with prefix: " + prefix); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java index 856fe0ad1..77c5982c9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java @@ -1,9 +1,15 @@ package nodomain.freeyourgadget.gadgetbridge.activities; +import android.Manifest; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; +import android.support.v4.app.ActivityCompat; import android.support.v4.app.NavUtils; import android.util.Log; import android.view.MenuItem; @@ -39,6 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class ExternalPebbleJSActivity extends GBActivity { @@ -122,6 +129,10 @@ public class ExternalPebbleJSActivity extends GBActivity { return null; } + private boolean isLocationEnabledForWatchApp() { + return true; //as long as we don't give watchapp internet access it's not a problem + } + private class GBChromeClient extends WebChromeClient { @Override public boolean onConsoleMessage(ConsoleMessage consoleMessage) { @@ -306,6 +317,51 @@ public class ExternalPebbleJSActivity extends GBActivity { public void closeActivity() { NavUtils.navigateUpFromSameTask((ExternalPebbleJSActivity) mContext); } + + + @JavascriptInterface + public String getCurrentPosition() { + if (!isLocationEnabledForWatchApp()) { + return ""; + } + //we need to override this because the coarse location is not enough for the android webview, we should add the permission for fine location. + JSONObject geoPosition = new JSONObject(); + JSONObject coords = new JSONObject(); + try { + + Prefs prefs = GBApplication.getPrefs(); + + geoPosition.put("timestamp", (System.currentTimeMillis() / 1000) - 86400); //let JS know this value is really old + + coords.put("latitude", prefs.getFloat("location_latitude", 0)); + coords.put("longitude", prefs.getFloat("location_longitude", 0)); + + if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && + prefs.getBoolean("use_updated_location_if_available", false)) { + LocationManager locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); + Criteria criteria = new Criteria(); + String provider = locationManager.getBestProvider(criteria, false); + if (provider != null) { + Location lastKnownLocation = locationManager.getLastKnownLocation(provider); + if (lastKnownLocation != null) { + geoPosition.put("timestamp", lastKnownLocation.getTime()); + + coords.put("latitude", (float) lastKnownLocation.getLatitude()); + coords.put("longitude", (float) lastKnownLocation.getLongitude()); + coords.put("accuracy", lastKnownLocation.getAccuracy()); + coords.put("altitude", lastKnownLocation.getAltitude()); + coords.put("speed", lastKnownLocation.getSpeed()); + } + } + } + + geoPosition.put("coords", coords); + + } catch (JSONException e) { + e.printStackTrace(); + } + return geoPosition.toString(); + } } @Override