I am using Phonegap Build version 3.4.0 with the geolocation plugin version 0.3.7.
My app should display the users location on a map.
This works very well under iOS.
But depending on the location settings in Android I am getting very different results.
If I am trying to get a quick location fix with enableHighAccuracy: false and the user has disabled Wireless Location Access, my error callback gets called with the error code 2. This is what I expected.
But if I am trying to get the best result with enableHighAccuracy: true and the user has disabled GPS Access the error callback does not get called. Instead it just times out.
Is this known behaviour and I have to live with it or is there something I could do?
I am using boilerplate code:
var positionOptions = {
enableHighAccuracy: true,
timeout: 1000*30,
maximumAge: 0
};
function positionSuccess(location) {
console.log(location);
};
function positionError(error) {
console.log(error);
};
navigator.geolocation.getCurrentPosition(
positionSuccess,
positionError,
positionOptions
);
Edit: this is tested on Huawei/Android 4.0.3, Moto G/Android 4.4.2, Samsung GT-I9100/Android 4.1.2, LG ???/Android 4.1.2
The geolocation on Cordova can be very tricky to get working correctly. I'm still occasionally battling with it myself. If you get a timeout make sure the geolocation code is even compatible with your test device by extending the timeout to ~300,000 ms (5 minutes). Yeah, if you're in a region with a bad signal it can take that long. Also try getting your location via wifi. And test on a live device (check out TestDevice). Android simulators are iffy.
If geolocation is crucial to your application, you should alert your users of the problem when you get each of these error codes. Tell your user that they need to enable one form of access or another and how to go about doing that.
Also, you can consider running getCurrentPosition where enableHighAccuracy: false, and if that fails run getCurrentPosition again but this time set enableHighAccuracy: true. Only after both methods have timed out, prompt the user with an error.
By the way, in my experience while on an Android, Cordova is usually able to lock onto a location within 2-3 seconds when using 3/4G in an urban environment. If not by then it pretty much never locks on. Good luck!
Related
I am using
window.addEventListener('devicemotion', event => this.watchDeviceMotion(event))
watchDeviceMotion(event: any) {
let motionData = {
x: event.acceleration.x,
y: event.acceleration.y,
z: event.acceleration.z,
}
let rotationData = {
alpha: event.rotationRate.alpha,
beta: event.rotationRate.beta,
gamma: event.rotationRate.gamma
}
if (this.getSensorData) {
// console.log(JSON.stringify(motionData))
// console.log(JSON.stringify(rotationData))
this.userData.motionData.push(motionData)
this.userData.rotationData.push(rotationData)
}
}
to access accelerometer data on an Android device using Ionic with Angular. When inside the app, the event works at a frequency of 60 Hz but when the app is switched to background, the frequency drops around 9-10 Hz for the first 5 mins and at some point while still in background it goes back at 60 Hz and remains like that indefinitely.
I am also using the background plugin with
this.backgroundMode.enable();
this.backgroundMode.on('activate').subscribe(() => {
this.backgroundMode.disableWebViewOptimizations();
});
I tried to add disableBatteryOptimizations() to the background plugin with the corresponding condition in config.xml but still no luck.
I also tried the plugins for Device Motion and Gyroscope but they behave the same.
How should I prevent the frequency from slowing down?
Has anyone else encountered this problem before?
It is unclear which version of Android you are using, but working against the system usually leads nowhere. Guess you might have tested that with an elder version, because since Android 9, the sampling rate should have a frequency of 0Hz, when the application is in the background.
This is due to a new power management with "App Standby Buckets", where only the "active" one isn't restricted.
See the Android 9 behavior changes:
Limited access to sensors in background
Android 9 limits the ability for background apps to access user input and sensor data. If your app is running in the background on a device running Android 9, the system applies the following restrictions to your app:
Your app cannot access the microphone or camera.
Sensors that use the continuous reporting mode,
such as accelerometers and gyroscopes, don't receive events.
Sensors that use the on-change or one-shot reporting modes don't receive events.
The only way to prevent this is manually setting the bucket to "active":
adb shell am set-standby-bucket packagename active|working_set|frequent|rare
Source: Test power-related issues and there's also an UsageStatsManager.
I'm working on updating an existing product using here-sdk from version 3.7 to 3.8 / 3.9
It has hardware gps on board available via android LocationManager.GPS_PROVIDER, but also receives location information from an external device which is injected via location mock as the network provider:
this.locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER,
false, false, false, false, true, true, true,
Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
this.locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true);
this.locationManager.setTestProviderStatus(LocationManager.NETWORK_PROVIDER,
LocationProvider.AVAILABLE, null, System.currentTimeMillis());
This external data is used primarily whenever gps is not available, eg. during startup.
PositioningManager is started with: PositioningManager.getInstance().start(PositioningManager.LocationMethod.GPS_NETWORK);
Other places in the codebase have locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, ...) -> onLocationChanged(Location location) handlers that fire on each new mocked location, plus other handlers listening to LocationManager.GPS_PROVIDER which work for updates from hardware gps.
There are also PositioningManager onPositionFixChanged() listeners which fire for these same coordinates from both providers.
On HERE SDK 3.7 this all works perfectly.
Once I upgrade HERE SDK to 3.8 however the network provider updates stop working.
The map display no longer updates and the onPositionFixChanged() listeners no longer fires for mock network updates. GPS updates work fine however.
The LocationManager onLocationChanged listeners still work for network, but not the PositioningManager callbacks.
If I change the mock provider to override LocationManager.GPS_PROVIDER instead of network, onPositionFixChanged() and the map updates correctly, but then the real gps coordinates are lost.
SDK 3.9 behaves the same.
Even changing Positioning Manager startup to not use gps, only network does not work, I get no updates from either provider then.
Switching back to 3.7 aar file makes it all work again (with no other code changes)
In case it helps, the device is running Android 5.1.1
Thanks!
I had a closer look into this topic and the root cause is here a change with the following background:
Within the 3.7 SDK we experienced an issue with the Tunnel extrapolation broken by "bad" network positions - In a simple test app a tunnel extrapolation was interrupted by a network position claim to be 24M accurate but likely was not. This is just one example but something which definitely should not happen. Within changes introduced ion 3.8 one we considered that the Android HERE We Go did not have this problem because it only uses LocationMethod.GPS during navigation and LocationMethod.GPS_NETWORK at all other times. The implementation of the same behavior means generally better navigation in tunnels is underway.
So the usage of an external device to get the location will not working starting from 3.8 and for now it is considered as expected behavior.
On the other hand it is not needed any longer as the SDK supports a much better tracking.
I have created a mobile app with cordova. This app uses the GPS location of the device. Now the issue is the cordova geolocation plugin seems not to be working on other devices especially on the nexus 7. See sample function below.
navigator.geolocation.getCurrentPosition(function (pos) {
//something here
}, location_error, {timeout: 60000, enableHighAccuracy: true, maximumAge: 3600000});
I tried a lot of solutions like setting timeout and enabling high accuracy. And the weirdest part is, when i restart the device geolocation works!
Does anyone have any solution for this, or any alternative?
I have a mobile application done in Meteor + ionic and I'm trying to get the user GPS location using this simple code:
navigator.geolocation.getCurrentPosition( function ( result ) {
console.log( result );
Session.set( 'pos', result );
}, function ( err ) {
console.log( err );
});
All I get is a warning saying that getCurrentPosition deprecated on insecure locations.
Why is my app seen as an insecure location since I'm running it with meteor run android-device which basically installs it on my phone then runs it like any other app?
If I open up the chrome inspector and control the app's browser I can switch the url from http://meteor.local to https://meteor.local making it a "secure location" but all I get is a timeout error when getCurrentPosition is fired.
So...how does one get the user's position inside a meteor mobile application?
According to the documentation you need to use the cordova geolocation plugin. I believe this is because the webview used by cordova may not have all the features of chrome on your mobile -- which is a natural but wrong assumption.
According to the geolocation plugin readme you need to add the plugin:
meteor add mdg:geolocation.
and then you can use:
Geolocation.currentLocation()
There might be a way to do this all with navigator.geolocation, but if you use the native functionality provided via the plugin then you won't need to worry much about security consideration in browsers. It will also ensure that things will work on older devices that may use a version of the webview that doesn't yet implement the geo API.
I had the same problem when using the navigator.geolocation. It seems like the error function will never be fired because the timeout default value is actually infinity. To solve it is to actually set a minimum timeout value.
navigator.geolocation.getCurrentPosition(success,error,{timeout:5000});
I am building a location aware app for Android using sencha 2.3.1 + phonegap 3.3.0, and use geolocation to show a list of destinations ordered by proximity to the user location.
Everything works fine if the setting for network-based location is on. But if I turn it off and leave gps only based location then it never gets detected.
The code is very basic, I tried both the sencha path:
Ext.device.Geolocation.watchPosition({
frequency: 10000,
callback: function(position) {
AppHelper.setCurrentLocation(position);//yeah!!
},
failure: function() {
AppHelper.setLocationModeOff();//oouch!
}
});
and the phonegap path:
var success = function(position) {
AppHelper.setCurrentLocation(position);
};
var fail = function() {
AppHelper.setLocationModeOff();
};
navigator.geolocation.watchPosition(success, fail,{ timeout: 30000 });
Result is the same, I tried waiting for a couple minutes for the geolock to happen but no sign of location service.
The phonegap location plugin is installed, the permissions are correct, and everything works if network location is enabled.
I am testing on a Sony Tablet S.
I am aware of this bug:
How to get user position by GPS in Sencha
But I checked the code and its is definetely fixed in sencha 2.3.1
I wil try on other devices but I was wondering if anybody experienced the same.
TIA.
EDIT:
I made an experiment using standard html5 code on my android device using systems default browser (webkit based).
I would access my settings page and change settings at each run.
Accessing http://html5demos.com/geo I get the following:
I started the device with network geolocation on and gps based location off:
I get a message that asks if I want to share my location I say yes, only this time everything works fine.
Turn off network based geolocation, gps still off:
Location detection fails. (as expected)
Turn on GPS, leave network geolocation off:
Geolocation fails silently, I don't get a request to use my location and subsequent activation of GPS based gelocation.
So my conclusion is: this is similar to what I noticed in phonegap. If network based geolocation is on everything works as expected. But if I have no network connection and gps is on that is pretty useless in my html5 app.
At least this is what happens on my device (sony tablet)
From my understanding of HTML5 geolocation API, that is expected behaviour, you just can't control if under the hood it is using gps or network location.
What's probably happening is that watchPosition(), when it is called, tries first a raw, quick positioning using network, then goes with the gps positioning to give you a better result (assuming you called it with the enableHighAccuracy parameter).
If you are disabling network positioning it probably gets stuck at the first point: as stated in cordova/phonegap's docs the permission to access coarse location is a requirement for geolocation to work.
(in app/AndroidManifest.xml)
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
I am guessing that revoking access to coarse location from the device settings somehow "overrides" the user permission given when installing the app.