Get precise Android GPS-Location in Python - android

I try to obtain the GPS-Location of my Android Phone in Python (using QPython3 app). This kind of works, but it seems there are several LocationProviders in Android:
gps: pure gps location, slow, energy consuming, but very accurate,
and exactly what I need.
network: mix of gps and wifi/cell locating, faster, but less accurate
passive: like above but completely without using gps
Problem:
When I run my script (below) I only get my location provided by "network"
wich is not accurate enough.
But I can't find a way to force a specific LocationProvider.
Code:
# import needed modules
import android
import time
import sys, select, os #for loop exit
#Initiate android-module
droid = android.Android()
#notify me
droid.makeToast("fetching GPS data")
print("start gps-sensor...")
droid.startLocating()
while True:
#exit loop hook
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
line = input()
print("exit endless loop...")
break
#wait for location-event
event = droid.eventWaitFor('location',10000).result
if event['name'] == "location":
try:
#try to get gps location data
timestamp = repr(event['data']['gps']['time'])
longitude = repr(event['data']['gps']['longitude'])
latitude = repr(event['data']['gps']['latitude'])
altitude = repr(event['data']['gps']['altitude'])
speed = repr(event['data']['gps']['speed'])
accuracy = repr(event['data']['gps']['accuracy'])
loctype = "gps"
except KeyError:
#if no gps data, get the network location instead (inaccurate)
timestamp = repr(event['data']['network']['time'])
longitude = repr(event['data']['network']['longitude'])
latitude = repr(event['data']['network']['latitude'])
altitude = repr(event['data']['network']['altitude'])
speed = repr(event['data']['network']['speed'])
accuracy = repr(event['data']['network']['accuracy'])
loctype = "net"
data = loctype + ";" + timestamp + ";" + longitude + ";" + latitude + ";" + altitude + ";" + speed + ";" + accuracy
print(data) #logging
time.sleep(5) #wait for 5 seconds
print("stop gps-sensor...")
droid.stopLocating()
Sample Output (fake coordinates):
net;1429704519675;37.235065;-115.811117;0;0;23
net;1429704519675;37.235065;-115.811117;0;0;23
net;1429704519675;37.235065;-115.811117;0;0;23
Summarization:
How do I get a precise GPS location in Android using Python?
Thanks in advance everyone!
EDIT: already tested:
inside / outside
enabled / disabled
WiFi GPS enabled (before running script)

I had the same problem. You Can do something Like this if you want to enforce GPS as LocationProvider
import android, time
droid = android.Android()
droid.startLocating()
print('reading GPS ...')
event=droid.eventWaitFor('location', 10000)
while 1:
try :
provider = event.result['data']['gps']['provider']
if provider == 'gps':
lat = str(event['data']['gps']['latitude'])
lng = str(event['data']['gps']['longitude'])
latlng = 'lat: ' + lat + ' lng: ' + lng
print(latlng)
break
else: continue
except KeyError:
continue

I was trying to do something like this today and I had a similar problem. I was getting the same output over and over again. Long story short, I discovered this. Putting this in at the bottom of the loop should solve the problem.
droid.eventClearBuffer()
If you look at the original post sample output, you will notice that the time stamps are all the same. Clearing the buffer resets the object returned by the 'location' event.

droid = android.Android()
droid.startLocating(0, 0)
event = droid.eventWait(1000).result
if event['name'] == "location":
print(event['data']['gps'])
droid.stopLocating()

Related

Is HTML5 browser geolocation feature on mobile available while screen off/ suspend?

To substitute my usage of native apps that allow to keep track of my position, I wanted to generate a PWA using the HTML5 Goelocation API.
The result I have been able to achieve so far seems to point a inferior functionality of the HTML5 Goelocation API compared to native Android API.
Below is the code I have used and the issue is, that the PWA/ website application only receives infrequent updates. Additionally the app only receives position while the screen is not off.
This puts a huge obstacle into having a PWA being to track for instance my bike tour, since I cannot keep the screen and browser in the foreground, while ideed I wished the PWA would simply continues running even when the screen is off.
Now I am aware that in most cases a device user and privacy aware person would benefit from the useragent/browser to cut the waste of resources and limit privacy loss by disabling the very feature I search.
In essence however I have looked over the MDN documentation and besides the PositionOptions I was yet unable to find any clue about the guarantees of the API.
Find below the way I have sought to make it work as a code.
Does + Should HTML5 Goelocation API work when screen of on a mobile?
Is there a concrete information about if and how much geolocation information is returedn? like frequency/delay of update and like geofencing imprecision ?
Could for instance google maps navigation work in the browser itself?
My platform is Gecko on Android. If better results could be achieved in Chromium on Android I would be happy to hear about that too.
On Android I use firefox. In it I wanted to have my website provide a page that keeps track of my movements via the geolocation API, in order to replace my strave.
window.addEventListener("load",function(){
var a= document.createElement("div");
var textarea = document.createElement("textarea");
//textarea.value="aaaa"
textarea.style.display="block"
textarea.style.minHeight="5cm"
textarea.style.width="100%"
document.body.appendChild(a);
document.body.appendChild(textarea);
if(confirm("reset data?")){
localStorage.clear() ;
}
localStorage.setItem("start"+Date.now(),startInfo);
var startInfo = Object.keys(localStorage).length+ " " +Date.now()+ " " + (Date.now() % 864000);
var lastTime=0,lastLat=0,lastLon=0,count=0,lastDistance=0;
var startTime = Date.now();
var distance = 0;
if('geolocation' in navigator) {
a.innerHTML="<h2>super wir haben geolocation!</h2>";
setInterval(()=>{
navigator.geolocation.getCurrentPosition((position) => {
// var a = document.createElement("div");
count++;
a.innerHTML="<h1>"+(((Date.now()-startTime)/1000)|0)+" "+((distance*100|0)/100)+"</h1><h3>"+startInfo+"</h3><h2>date="+(new Date()).toString()+"<br>lang="+position.coords.latitude+" long="+ position.coords.longitude+"</h2>";
var lat = ((position.coords.latitude * 10000000) | 0)
var lon = ((position.coords.longitude * 10000000) | 0)
var time = Date.now();
var deltaTime = time - lastTime;
var deltaLat = lat - lastLat;
var deltaLon = lon - lastLon;
if(Math.abs(deltaLat)>100000 || Math.abs(deltaLon) > 100000)
{
} else{
distance += Math.sqrt(deltaLat*deltaLat+deltaLon*deltaLon);
}
var deltaDistance = distance - lastDistance;
lastLat=lat;
lastLon=lon;
lastTime=time;
lastDistance=distance;
newline = (((Date.now()-startTime)/1000)|0) + " dist=" + distance + "("+deltaDistance+") lat=" + lat + "("+deltaLat+") lon=" + lon + "("+deltaLon+") ";
textarea.value = newline + "\n" + textarea.value;
localStorage.setItem("P"+(Date.now()%864000),deltaLat+" "+deltaLon+" "+deltaTime);
},function(){},{timeout:900});
},1000);
} else {
a.innerHTML="<h2> shit</h2>";
}
});

get offline GPS coordinates on android device

Firstly, I'm not a developer or programmer so any help here would be really appreciated! I have a form for use on android mobile devices which launches in Google Chrome. The users can use this form when offline and I was wondering how best to get offline GPS co-ordinates in lat and long. I've been doing some digging around and the code below seems to work. I pull the lat, long and accuracy result from this code into a separate field on my form.
What I am not sure about is how to pull in a timestamp so that I can be assured the reading is current and not something cached on the device. The currency and reliability of the coordinates is very important to me.
Any help at all on this would be marvellous!!
Thanks, Angela
<!DOCTYPE html>
<html>
<body>
<p>Get your latitude and longitude (test this to ensure it works when out of coverage)</p>
<button onclick="getLocation()">Get your coordinates</button>
<p id="demo"></p>
<script>
var x = document.getElementById("demo");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
x.innerHTML = "Geolocation is not supported by this browser.";
}
}
function showPosition(position) {
x.innerHTML = "Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude;
"<br>Accuracy: " + position.coords.accuracy + '<br />'
}
function showPosition(position) {
var latlon = position.coords.latitude + "," + position.coords.longitude +", Accuracy " + position.coords.accuracy;
$('input[name="coords"]').val(latlon).trigger('input');
}
</script>
</body>
</html>
getCurrentPosition accepts a second parameter, PositionOptions. There are a few options you can experiment with to achieve desired results, but specifically you'll want to use maximumAge and enableHighAccuracy. To ensure uncached results:
navigator.geolocation.getCurrentPosition(function(pos){
console.log('Got position', pos);
}, {
// can be `0` = uncached, any number in milliseconds,
// or `Infinity` which will only retrieve cached results
maximumAge: 0,
// may take longer, but browser will do everything possible
// to get the most accurate position
enableHighAccuracy: true
});
It's also worth noting the returned Position comes with an accuracy property, which returns a positive double indicating the accuracy of your lat and long in meters. Depending on the use case, you may want to require a certain accuracy threshold for users to interact with your app. You can see the full spec here.

How can I get exact GPS location with AIR Geolocation API?

How can I get the exact Latitude and Longitude? I only get whole numbers. From my understanding, in order to get down to the meter I need to get down to 5 decimal places. I have tried the horizontal and vertical accuracy but they don't match my phones GPS reading.
How can I get an exact GPS reading with Geolocation API, Down to the meter?
here is my code
var my_geo:Geolocation = new Geolocation();
my_geo.setRequestedUpdateInterval(2000);
my_geo.addEventListener(GeolocationEvent.UPDATE, onGeoUpdate);
function onGeoUpdate(e:GeolocationEvent):void
{
gpsLat1 = (e.latitude);
gpsLon1 = (e.longitude);
gpsHeading = (e.heading);
gpsHorAcc = (e.horizontalAccuracy);
gpsVerAcc = (e.verticalAccuracy);
gpsCheck = 2;
my_txt.text = "My Latitude is "+ gpsLat1 + " and my Longitude is "+ gpsLon1 + " Bearing is " + gpsHeading+ " HorAcc "+ gpsHorAcc+ " VertAcc "+gpsVerAcc;
}
Make sure your variables (gpsLat1, gpsLon1, gpsHeading, etc.) are of type Number and not a uint or int. Unsigned Integers and Integers only allow for whole numbers, whereas Number is the equivalent of float in most other languages (and allows for incredibly larger values, as well). If you save a decimal to an integer, it is rounded off/floored (I can't remember which), which sounds exactly like the problem you are having.
Alternatively, the API is restricted by the hardware you are testing on. If the hardware only returns a certain value for GPS coordinates, AIR cannot be any more precise. Odds are this is not the issue since a whole lat long point can be miles and miles in distance, meaning any device with that inaccurate of a GPS chip is absolutely useless.
Try this:
function onGeoUpdate(e:GeolocationEvent):void
{
gpsLat1 = (e.latitude.toString());
gpsLon1 = (e.longitude.toString());
gpsHeading = (e.heading.toString());
gpsHorAcc = (e.horizontalAccuracy.toString());
gpsVerAcc = (e.verticalAccuracy.toString());
gpsCheck = 2;
my_txt.text = "My Latitude is "+ gpsLat1 + " and my Longitude is "+ gpsLon1 + " Bearing is " + gpsHeading+ " HorAcc "+ gpsHorAcc+ " VertAcc "+gpsVerAcc;
}

Vertical Accuracy in android GPS

I am working with GPS related app. I need to get vertical accuracy but it always gets fix 11.0000. I need it to be dynamic as lat and lng. I have used getAccuracy but it results in horizontal accuracy.
#Override
public void onLocationChanged(Location location) {
if (location != null) {
lat = location.getLatitude();
lon = location.getLongitude();
Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault());
address = mailOb.getAddress(geoCoder, lat, lon);
if (!meterFootFlag) {
diameter = Math.round(location.getAccuracy()) + " m.";
altitude = Math.round(location.getAltitude()) + " m.";
} else {
diameter = Math.round(location.getAccuracy() * 3.28084) + " ft.";
altitude = Math.round(location.getAltitude() * 3.28084) + " ft.";
}
if (diameter.contains("+"))
diameter.replace("+", "");
else if (altitude.contains("+"))
altitude.replace("+", "");
} else {
lat = 0.0;
lon = 0.0;
if (!meterFootFlag) {
altitude = 0.0 + " m.";
diameter = 0.0 + " m.";
} else {
altitude = 0.0 + " ft.";
diameter = 0.0 + " ft.";
}
}
mlocManager.removeUpdates(MySettings.this);
pDialog.dismiss();
}
How can I get vertical accuracy?
Thanks in advance
Android does not provide the vertical accuracy.
Vertical accuracy usually is 2-3 times worse then horizontal accuracy.
A simple solution: use the androids accuracy for both horizontal and vertical.
advanced solution 1: find out what android uses as total accuracy (it could be a radial error of an error-sphere, including lat,long and altitude)
try to find out a conversion factor, e.g take accuracy and multiply *2,5
Another solution, look at iphone horizontal and vert accuracy, and compare to that of android. find out an average conversion factor from acc to vert acc.
Solution 3: think why you need vertical accuracy at all. why do you need that?
hints:examples from my iphone4: when iphone shows 30m hor, i have 57vert, 10hor: 15-20vert, 5 hor: 10vert
Starting with API 26 you can use getVerticalAccuracyMeters() method
#Override
#RequiresApi(Build.VERSION_CODES.O)
public void onLocationChanged(Location location) {
float accuracy = location.getVerticalAccuracyMeters();
}
Altitude accuracy heavily depends on core GPS accuracy, use of additional sensors as barometer and use of wifi/cell networks plus the fusion algorithms. It is NOT have a constant ratio. If u really want to get accuracy you can try the following: check variance of the signal while motionless, this will not always work as some devices will detect motionless and just repeat last output to save power. Another approach which is bit costly is to check with reference as https://developers.google.com/maps/documentation/elevation/intro
so u basically take lat lon measurement with the lat lon error and check the vertical error u get assuming you are in open area.

Reverse Geocoding issue

I implemented the reverse geocoding in my app and it is working, but sometimes it happens a very strange issue.
The code is that
List<Address> addresses = geo.getFromLocation(
obj.getLatitude(), obj.getLongitude(), 1);
List<Address> address = geo.getFromLocationName( addresses.get(0).getLocality().getBytes() , 1 );
Address location = address.get(0);
In the first part I get the address object of the place in which I'm. Than I want recover the generic coordinates of the city in where I'm because I don't want store the coordinates of my exact position.
This is working but I encounter a very strange issue! Trying the app with the fakegps app I set my position in "Ñuñoa", and the first address was found correctly, but when I try to get the generic coordinates, I get "Nunoa" that isn't in Chile, but in Peru!!
That makes no sense! why this?
Thanks for helping me
Sure Swathi.
List<Address> addresses = geo.getFromLocation(msg_r.getLatitude(),
msg_r.getLongitude(), 1);
String geoL = addresses.get(0).getLocality() + ", " + addresses.get(0).getAdminArea() + ", " + addresses.get(0).getCountryCode();
// reverse-reverseGeocoding
List<Address> address = geo.getFromLocationName(geoL, 1);
System.out.println("Where I am? " + geoL);
Address location = address.get(0);
// generic coordinate for the locality/city/town
location.getLatitude();
location.getLongitude();

Categories

Resources