Location accuracy remains low using GPS - android

I have the following code in main activity:
LocationManager mlocMan = (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);
if (mlocMan.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
LocationListener mlocListener = new LocationManagerHelper(...);
mlocMan.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,mlocListener);
}
In the location listener I have this: (theAccuracy was initialized to -1)
if (theAccuracy == -1 || theAccuracy > loc.getAccuracy()) {
theAccuracy = Math.round(loc.getAccuracy());
latitude = loc.getLatitude();
longitude = loc.getLongitude();
}
updateTimes++;
if (updateTimes == 3) {
mLocMan.removeUpdates(this);
updateTimes = 0;
//get address for location
theAccuracy = -1;
}
Meaning, after 3 location updates from the GPS, take the best accurate location and get its address. On the emulator I get fixed accuracy of 20m (I send long/lat using DDMS) but that's not real life so I tried with my device and while the very first time (3 requests) gave me the exact address (on the spot) with 40m accuracy, the next ones were sometimes more accurate but the address was nearby. The best accuracy I got was 29m (happened once) most of the times it's above 30. Is this a problem of my GPS (LG G3) or is there any other idea that can make things more accurate after 3-4-5 requests?

A few reasons:
Your emulator doesn't have actual gps hardware, so it's probably using your ip address, so that's why it seems fixed.
GPS hardware on your phone has to warm up a bit. Set the frequency of polling up for a bit (1 update a second, or half-second), and let it run for a few seconds, before taking measurements that count.
The location manager supports both hardware and network lookups (wifi / celltowers). Not sure how to set provider to just your phone's hardware, but if you use the googlePlayServices gps client (LocationClient), it's quite simple:
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationClient.requestLocationUpdates(mLocationRequest, (LocationListener) this);
You're probably testing at your computer in doors. Buildings definitely effect gps accuracy.

Related

Fused Location API gives Inaccurate Lat, Long when plotting in map it is slightly away from the road path even for low accuracy value

Google provides the fused location provider API to obtain location co-ordinates. According to the documentation, the API internally polls location data from different providers (GPS, Wifi, Cellular networks) and provides the best location. But, in High Accuracy mode, I have collected the below information. In this test GPS is always ON.
Latitude: 12.8560136
Longitude: 80.1997696
User Activity: IN VEHICLE
Speed: 21.810165 mph
Altitude: -83.0
Accuracy: 12.0
When I see this point in map, the points are not in the road. They are slightly away from the road.
Other points with the same accuracy are plotted in the road.When I full zoom and see, some of the points are slightly away from the traveled road path.
I want the accurate information. It points must be in the road path.
I have used the Fused Location API to get the location information.
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
Share your suggestion. If I use the Location manager will it solve my problem.
And also I need to consume less battery only. Fused API guarantees that it consumes only less power and more efficient.
And also Fused Location API has below issues,
Not able to get the satellite count.
Is always returning the FUSED provider. Not exactly gives which provider(GPS or Network) returns the Location information.
Your never notified when both the provider is unavailable . It will not return any value when none of the provider is available. To check the provider availability we need to separately register with Location manager. which consumes more power.
Please help me on this. Thanks in advance.
You won't beat the fused provider accuracy or power use with a straight up location provider.
The fused location provider reports speed as meters per second and accuracy in meters. The example point you have is accurate to 12 meters. A US lane is defined as 3.7m. With 12m of accuracy you could be off by 12/3.7=3.25 lanes in any direction. I can't say this enough. If you want accuracy you have to check the accuracy of the location.
How to get more accuracy by GPS_PROVIDER
LatLng and distance between returning incorrect values on newer phones
can't find the exact current location in android
Android Maps GPS outlier
Fused Location Provider unexpected behavior
Adjust your program to handle the accuracy of the point. For example assume the point is correct shade a circle around the point with a radius = the accuracy in the location.
Location data from GPS and other providers cannot be guaranteed to lie on the road. These sensors do not have the requisite mapping context to snap raw location signals to roads. To achieve this with raw data, you can use a snap to roads API. Mapping providers like Google Maps and OSM have ways to do this:
Google Maps snap to roads API
OSRM match service
If you are looking for an end-to-end solution that gives you location data on the road, you can also try the HyperTrack SDK for Android, which collects and processes location data to improve its accuracy. (Disclaimer: I work at HyperTrack.)
Also, to answer your other question, FusedLocationProviderApi does not expose the satellite count and provider information. To get the provider info, you can set up a GpsStatus.Listener class. This can be used in parallel to the fused provider in your app to check if the device has a GPS fix. You can use the following code snippet to set this up:
public class GPSStatusListener implements GpsStatus.Listener {
private LocationManager locationManager;
private boolean gpsFix;
public GPSStatusListener(LocationManager locationManager) {
this.locationManager = locationManager;
}
#Override
public void onGpsStatusChanged(int changeType) {
if (locationManager != null) {
try {
GpsStatus status = locationManager.getGpsStatus(null);
switch (changeType) {
case GpsStatus.GPS_EVENT_FIRST_FIX: // Received first fix
gpsFix = true;
break;
case GpsStatus.GPS_EVENT_SATELLITE_STATUS: // Check if satellites are in fix
for (GpsSatellite sat : status.getSatellites()) {
if (sat.usedInFix()) {
gpsFix = true;
break;
} else {
gpsFix = false;
}
}
break;
case GpsStatus.GPS_EVENT_STARTED: // GPS turned on
gpsFix = false;
break;
case GpsStatus.GPS_EVENT_STOPPED: // GPS turned off
gpsFix = false;
break;
default:
gpsFix = false;
return;
}
} catch (Exception e){
// Handle exception
}
}
}
public String getProvider() {
if (gpsFix) {
return "gps";
} else {
return "non_gps";
}
}
}

Why does having Wifi on but not connected help Network location, when using LocationManager?

This is possibly off-topic for SO, if so I apologise (and gladly accept the flag for closure), but I'm having issues figuring out why when WIFI is on, but not connected to any access point (on my android device), it vastly improves the accuracy of network provider when using LocationManager. Without it on, the general network location result is about 1 mile away from my current position. Also, most of the time the lat/lng values returned are different, so it's not even that it requested once and just cached the result in lastKnownLocation()
Obviously I'm using both GPS and Network providers to get a decent fix on end-user location (when either isn't available), and using the timestamp to figure out which is the latest.
I've searched google and have come up with various answers like: "It just does" and "Its magic" - Which are pretty useless to be honest. I don't want an in-depth description of the inner workings, just a slightly lower level than: "It just does", or "that's how it works".
requested code
// first get location from network provider //
if(isNetworkEnabled)
{
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_FOR_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES,
this);
Logging.Debug("GPSTracker", "Network");
if(locationManager != null)
{
netLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(netLocation != null)
{
latitude = netLocation.getLatitude();
longitude = netLocation.getLongitude();
speed = netLocation.getSpeed();
}
}
}
// if gps is enabled get lat/lng using that as well //
if(isGPSEnabled)
{
if(gpsLocation == null)
{
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_FOR_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES,
this);
Logging.Debug("GPSTracker", "GPS Enabled");
if(locationManager != null)
{
gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(gpsLocation != null)
{
latitude = gpsLocation.getLatitude();
longitude = gpsLocation.getLongitude();
speed = gpsLocation.getSpeed();
}
}
}
}
Any insight is greatly appreciated. Thanks.
Android, Apple and other companies have access to a huge data base where they can look up Wlan-Device-Id (the Mac-Adress of your WLAN Router) to lat/lon coordinates.
So when your phone detects a "known" WLAN, it can either:
- look up a local cache of Wlan-id to coordinate, or if you have internet connection active, - it can connect and query the coordinate for the Wlan id via that data base.
Remains the question where they have the coordinate of your WLAN-id?
Probably the first time when you have GPS active while connected to your WLAN.
SkyHook is such a company that provides that data.
From the LocationManager API:
public static final String NETWORK_PROVIDER
Added in API level 1 Name of the network location provider.
This provider determines location based on availability of cell tower
and WiFi access points. Results are retrieved by means of a network
lookup.
Constant Value: "network"
Even though you are not connected to any access points, your phone can still detect them and use this location info when calling:
netLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

onlocationChanged is called even if I am sitting at the same place

I have used the code below and everything is working fine except that onLocationChanged is called even if I am sitting at the same location .
I thought it should be called only when I am moving right ?
I only want to get the location after I have moved a certain distance.
Please help me out.
Thanks in advance.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
locationMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
this);
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(this, "Working!", Toast.LENGTH_SHORT).show();
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
String Text = "Latitud = " + lat + "\nLongitud = " +
lng;
Toast.makeText(getBaseContext(),Text,Toast.LENGTH_SHORT).show();
}
}
You're requesting location updates at the shortest possible intervals/distances
locationMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
this);
This is what the documentation says about those parameters
" The location update interval can be controlled using the minTime parameter. The elapsed time between location updates will never be less than minTime, although it can be more depending on the Location Provider implementation and the update interval requested by other applications. "
The minDistance parameter can also be used to control the frequency of location updates. If it is greater than 0 then the location provider will only send your application an update when the location has changed by at least minDistance meters, AND at least minTime milliseconds have passed. However it is more difficult for location providers to save power using the minDistance parameter, so minTime should be the primary tool to conserving battery life.
I personally use a minTime of 10 seconds and 10 meters for my app
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000,
10, locationListener);
Network location is not as precise as you would think it is. Therefore the result returned by the sensors can fluctuate. This is even more true when you consider that GPS signal weakens if you don't have direct line of sight with the satellites, and the number of visible satellites also has effect on the precision. This gets even worse when you start using the network provider, where the position is calculated by triangulation of the signal strength of cell towers, and the number and SSIDs of visible wireless network. Since these can fluctuate quite a lot, the precision suffers greatly. There are bunch of averaging algorithms, and heuristics employed to minimize such fluctuations, but ultimately nothing can stabilize it to be as good as you expect it to be.
A simple averaging and variation filtering can help you. Adding a correction based on the device accelerometer can also help a lot, but it will make your code more complex.

Google Maps can't get GPS location on Android 4.0.1

My Device gps found satellite but doesn't lock. It keeps constantly trying to acquire the GPS signal, but most times it fails. I tested it on other android version 4.1.1 and the problem persists.
I just tried many combinations of resetting both Google location services and the location access and nothing fixes it. I go into maps and I can't get a gps lock at all. I've noticed, it takes longer to get a GPS signal, and the signal gays lost more often
Disabling the 'Google location services' also doesn't work
In every app that uses GPS only the empty circle shows up. Sometimes (after many seconds) the dot appears and starts blinking. But even after three minutes my phone is searching for a GPS signal.
On official google map app, It say searching for GPS signal and stays like that
I don't have any bug report.It just looking for satellites all the time, in some point there is only circle without the dot inside.
sample code used to get GPS coordinates
#Override
public void onCreate(Bundle savedInstanceState) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria c = new Criteria();
c.setAccuracy(Criteria.ACCURACY_FINE);
c.setBearingRequired(true);
pro = locationManager.getBestProvider(c, true);
locationManager.requestLocationUpdates(pro, 0, 0, this);
Location loc = locationManager.getLastKnownLocation(pro);
gpsManager = new GPSManager();
if (loc != null) {
showLocation(loc);
}
#Override
protected void onPause() {
locationManager.removeUpdates(this);
}
Is there any solution?
My favorite tool for debugging GPS issues is the GPS Test app. It shows you how many satellites your phone is detecting, how strong their signal is, how accurate the fix is, etc. This at least lets you rule out if you're in an area with bad satellite coverage.
I've only got one app on the market, but it is a GPS based app. Here's some of my code that got things working. Mind you, this only uses the GPS, it doesn't do rough location based on network.
public void initLocationManager()
{
myGpsManager = (LocationManager)getSystemService(LOCATION_SERVICE);
long time = 0;
float dist =0;
myGpsListener = new locationListener();
myGpsManager.requestLocationUpdates("gps", time, dist, myGpsListener);
}
#Override
public void onPause()
{
myGpsManager.removeUpdates(myGpsListener);
super.onPause();
}

Android requestLocationUpdates when phone idle

I'd like to track my Location every minute. For that I use a locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000, 0, pll);
Here is the log when my phone is idle.
Date Latitude Longitude Accuracy
07:45:35 51.362402459999996 - 6.2174867399999995 (75.0)
07:46:35 51.362402459999996 - 6.2174867399999995 (75.0)
07:47:35 51.362402459999996 - 6.2174867399999995 (75.0)
...
07:50:35 51.362402459999996 - 6.2174867399999995 (75.0) # I'm further than 75m away from my home at that time
I've indeed a new location every minute but it is exactly the same. Just the time is updated. The position is not updated (maybe normal when I don't move enough) but I find it strange that the coordinates are exactly the same. Also as I don't have wireless activated, it should locate me accordingly to the CellId (with an accuracy of ~1000m), here I still have an accuracy of 75.0. It seems, it is the last location recorded using wireless networks.
Any idea how can I record the real last location (even with low accuracy) ?
public void onLocationChanged(Location location) {
System.out.println(new Date(location.getTime())+" "
+location.getLatitude()+" - "+location.getLongitude()+" ("+location.getAccuracy()+")");
callback.addEntry(location);
}
Hey use GPS_PROVIDER instead of NETWORK_PROVIDER as per below code
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, pll);
NETWORK_PROVIDER will give you only fix tower location and gps will give you exact changing location
You have got nearest GSM tower coordinates.
It seems there is no way to force to compute the position using the LocationManager with the celltower only when there is no wireless connexion.
Maybe another way would be to use the method mentioned in the thread Poor Man GPS : manually compute the position knowing the CellId.
Pseudo code :
onLocationChanged(new_location)
if isConnected()
record(new_location)
else
cell_location = poorManGPS()
record(cell_location)
end
The problem is of course that I cannot query the cell-id database with no internet connection. I see several solutions :
Store the current (and previous) cell id when I have internet and hope I'll stay in this one when I won't have internet
Use the cell id database on the phone (but I think root privileges needed)
Store the cell id for further localization

Categories

Resources