I am working on a React Native app that works both on Android and iPhone. I have a feature where you can "share my current location". This works very well and accurately on iPhone but on Android, it only shows the correct city/locality however the actual location is far off from your street. For getting the location I use the https://github.com/Agontuk/react-native-geolocation-service library.
Here's the relevant code, I'm simply calling Geolocation.getCurrentPosition, not doing anything special. And I'm asking for high accuracy in options. Any ideas on how I can improve the accuracy on Android?
Edit: If I open Google Maps on the same Android phone, I get the accurate/correct location.
Geolocation.getCurrentPosition(
(position) => {
// Do stuff with the position
},
(error) => {
// See error code charts below.
logError(
new Error(
`Cannot get current location: ${error.code} ${error.message}`,
),
);
},
{
enableHighAccuracy: true,
accuracy: {
android: 'high',
ios: 'bestForNavigation',
},
timeout: 15000,
maximumAge: 10000,
distanceFilter: 10,
},
);
}
},```
I figured out that the issue was that I did not have the ACCES_FINE_LOCATION permission in my AndroidManifest.xml. It's a bit confusing because this did not result in any actual error, it just did not give accurate location instead.
So just add this to the manifest file
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
I am using react-native-geolocation-service to fetch the location of the user. On iOS it is easy to just ask for location access when the app is in the foreground, you just skip adding background location access as a capability. However, I don't understand how you remove this permission on Android. I don't have the ACCESS_BACKGROUND_LOCATION permission set and I'm still getting the option "Allow all the time" on e.g. my Pixel 2.
This is the code I am using to fetch the location of the user:
const getCurrentPosition = async (onSuccess, onError) => {
if (Platform.OS === 'android') {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'My title',
message: 'My message',
buttonPositive: 'Continue',
}
);
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
onError();
return;
}
}
Geolocation.getCurrentPosition(
(result) => {
const position = {
longitude: result.coords.longitude,
latitude: result.coords.latitude,
};
onSuccess(position);
},
(error) => {
onError();
},
{ enableHighAccuracy: true, maximumAge: 10000, timeout: 15000 }
);
};
Look into your main AndroidManifest.xml file (and by main I mean under android/app/src/main(COULD_BE_SOMETHING_ELSE_USUALLY_MAIN_BUT_YMMV)/AndroidManifest.xml)
You need to find a bunch of <uses-permission />. Check if one of these bad boys got ACCESS_BACKGROUND_LOCATION:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
No luck? Fear not, my dear friend. Here's a remedy for your battle-fatigued-from-dealings-with-react-native mind. Add this line under the last <uses-permission> tag.
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
tools:node="remove" />
May peace prevail.
Technical nitty gritty:
Actually, a library, like react-native-geolocation-service or react-native-background-geolocation, can alter final AndroidManifest.xml, which will go to a bundle edited heavily.
Simply deleting a line won't cut it, because you don't have an access to that final draft, cause it's auto-generated. You need to be one step ahead and use tools:node="remove" to make sure it will be deleted from the final version of the manifest file.
Sources:
[1] https://developer.android.com/studio/build/manifest-merge
[2] https://github.com/transistorsoft/react-native-background-geolocation/issues/1149
I have a problem using Geolocation on Android device.
I create an Ionic 3 application.
I use Geolocation ( [https://ionicframework.com/docs/native/geolocation/ 13]).
I use the sample code provided there.
The problem is that, the code works in Browser but whenever I upload it on an Android device, it does not work.
When I start the app on device the alert for location permission is prompted.
I press Allow.
Then in the android tray an icon appears that says “Searching for GPS”.
After timeout expires I got the error for timeout and no location.
The strange think is this:
If I close my app, then open google maps ( or other app using gps position ) and reopen my app works as it should.
I don’t know what to do.
The permissions are fine :
and everything was installed properly.
Can anyone help please?
i got it actually i have to pass apikey with that like
<script src="http://maps.googleapis.com/maps/api/js?key=YOUR_KEY"></script>
in the index page
without this key it sometime works but not sure everytime.
Note : this key is only generated when you have a valid gmail a/c (by providing DOB/CreditCard nos) although its free .
try this, it should work
ionic cordova run android --prod
--prod makes production build apk
import { LocationAccuracy } from '#ionic-native/location-accuracy';
declare var navigator
Above
#Component
watchPosition() {
this.locationAccuracy.request(this.locationAccuracy.REQUEST_PRIORITY_HIGH_ACCURACY).then(
() => {
var options = {
timeout: 500,
maximumAge: Infinity
};
this.watch = navigator.geolocation.watchPosition((data) => {
let latlng: LatLng = new LatLng(data.coords.latitude, data.coords.longitude);
}, (error) => {
console.log("error watch", error)
}, options);
}
}, error => {
alert('Error requesting location permissions' + JSON.stringify(error))
});
}
}
The GPS location output from the navigator.geolocation.getCurrentPosition won't update based on the location I have set in Genymotion GPS Simulate menu. This is the code that I used to request for new location:
navigator.geolocation.getCurrentPosition(
(position) => console.log("Location: " + JSON.stringify(position)),
(error) => console.log("Error: " + error),
{enableHighAccuracy: true, timeout: 10000, maximumAge: 2000}
);
The output that I got was (see below), and the timestamp doesn't get updated.
Location: {"timestamp":1471229266000,"coords":{"speed":0,"heading":0,"accuracy":1,"longitude":0,"altitude":0,"latitude":0}}
I have added GPS Permission in the Manifest file.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
NOTE: A imperfect workaround for this issue that I am facing is to disable the GPS function on android and enable it back in order for the location to be updated based on what I have entered in the Genymotion
React native getCurrentPosition uses cached position depending on your maximumAge value. Try setting maximumAge to 0
I'm using sencha-touch 2.0 and phonegap 2.0.0 in my app to retrieve user's location.
When runing on my locahost, everything works just fine. However, when loading the .apk to my android 15 api's device (using eclipse and the adt plugin), every call to getCurrentLocation or watchPosition never returns...
here is my code:
geoOn: function(){
var geoReady = navigator.geolocation || undefined;
var onSuccess = function(position){
Top5.app.alert('Geolocation success '+String(position.coords.latitude) + ' ' + String(position.coords.longitude),'Geolocation');
var scope = Ext.getCmp('nestedList');
scope.updateDistance(position.coords);
};
var onFailure = function(error){Top5.app.alert('Geolocation failed: '+String(error.code) + ' '+String(error.message),'Geolocation');};
if (geoReady) {
this.watchId = navigator.geolocation.watchPosition(onSuccess ,onFailure,{timeout:6000,maximumAge: 3000,enableHighAccuracy: true});
}
else{
Ext.device.Geolocation.watchPosition({
frequency: 3000, // Update every 3 seconds
callback: function(position) {
this.updateDistance(position.coords);
},
failure: function() {
console.log('Geolocation Failure!');
},
scope:this
});
}
},
geoGet: function(){
var geoReady = navigator.geolocation || undefined;
if (geoReady) {
var onSuccess = function(position){
Top5.app.alert('Geolocation successful!!!');
var scope = Ext.getCmp('nestedList');
scope.updateDistance(position.coords);
};
var onFailure = function(error){Top5.app.alert('Geolocation failed: '+String(error.code) + ' '+String(error.message),'Geolocation');};
navigator.geolocation.getCurrentPosition(onSuccess,onFailure);
}
else{}
},
geoOff:function(){
var geoReady = navigator.geolocation || undefined;
if (geoReady) {
navigator.geolocation.clearWatch(this.watchId);
this.watchId = null;
}
else{
Ext.device.Geolocation.clearWatch();
}
},
updateDistance:function(coords){
Top5.app.alert('updateDist','');
var scope = Ext.getCmp('nestedList');
var lat = coords.latitude,lon = coords.longitude;
var store = scope.getStore();
var i,record;
for(i = 0; i < store.data.all.length; i++)
{
record = store.data.all[i];
if(record.data.locationX){
record.set('distance',Top5.app.getDistance(record.data.locationX,record.data.locationY,lat,lon).toFixed(3));
}
}
}
UPDATE: So I walked out of my building and it worked... I need to go outside more often.
However, when I'm disabling the gps, I thought geoLocation will find my location using wifi connection - but it failes (I'm setting enableHighAccuracy: false). Why is that?
UPDATE: Let me rephrase my question:
Does navigator.geolocation.watchPosition suppose to work both with GPS signal and wifi/g3 signals? How can I detect user location using internet connection only? currently, my code is working only with GPS, and when that option disabled or signal is blocked, geolocation isn't working.
I know that maybe it is too late, but today i struggled with the same issue! The solution turned out to be very simple!
SOLUTION: Reboot the device.
That's all.
The problem is, that you never know when i user will get this kind of bug, so if your application relies heavily on geolocation i recommend you set a timeout in location options navigator.geolocation.getCurrentPosition(geoSuccess, geoError, {timeout: 15000}) and alert user about the problem and possible solution.
P.S.
Keep in mind, that Geolocation can timeout for example if mobile data is turned off too, so reboot won't always fix it. On iPhone it uses cellular data to get your position, but on Android, it looks like the phone does not have access to cellular data unless 3G is turned on
It could sound stupid, but, did you activate the "Use Networks" option?
Go to Settings -> Location and security -> Use networks; and active it. I have passed all the afternoon watching the problem and it was that.
I restarted and restarted. I reset my phone to factory settings.
But nothing worked.
Until I set enablHighAccuracy from true to false.
And... Tada.... it works.
So :
var options;
options = {
maximumAge: 30000,
timeout: 5000,
enableHighAccuracy: false
};
This used to work fine using PhoneGap 2.6.0. I needed to make this change since I'm now using Phonegap 3.3 - tested on a Wiko Cink+ phone.
Try removing the Phonegap plugin geolocation plugin from your project. You won't need to make any changes to your JavaScript code as your device will fall back on the standard HTML5 navigator.geolocation functionality which has the same method signature.
Assuming you're using PhoneGap 3.3, you just need to run:
cordova plugin rm org.apache.cordova.geolocation
If you are running on an emulator, it may be because the device does not have a geolocation set. Try setting the location by running the following, assuming your android emulator is on port 5554:
telnet localhost 5554
geo fix -0.001 51.5
Restart your phone or Go to google map and check if gps is working over there.
I got it working.
I had this happen to a working app after updating PhoneGap to version 3.6.3 from 3.5. After trying many other suggestions Arthur's answer worked. 15 seconds seemed too long to me so I used {timeout: 2000}. I'm guessing the new version is slower as my code worked fine before the update on the same devices. Thought I'd post as well as upvote him as everything I found in Google was about initial setup and mostly irrelevant to my situation.
You just need to add enableHighAccuracy: true, maximumAge: 60000 and then reboot your device.
From my trial and error analysis, its most likely:
1. The version of android you're using. On Lollipop and lower you may need to go to the phones location settings and enable high accuracy settings (using gps, wlan and mobile networks to get location). I had to do this on a kitkat phone.
2. As others have mentioned, you can try changing the settings of getCurrentPosition by either enabling/disabling highaccuracy and adding a timeout.
3.If you're using ngCordova, make sure you installed it right and the location functions are actually being called. Use console to verify
Try This Solution:
window.setInterval(checkPosition, 5000);
function checkPosition() {
function onSuccess(position) {
document.getElementById('result1').innerHTML = position.coords.latitude;
document.getElementById('result2').innerHTML = position.coords.longitude;
}
// onError Callback receives a PositionError object
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
I've managed to work it out.... However , I have no idea what actually solved it. All I've done is to change one of my model's structure. Can anyone see the connection to geolocation?