In my app, I've tried two ways of accessing location:
a) Using LocationManager and GPS_PROVIDER. I accept location to be processed if it has accuracy 50 or less. App receives location however most of the time receives no location at all - while Google Maps when I start it to try it out gets my location constantly and more precise than my app.
Here are parts of the source related to this:
Start to listen to locations:
// in service class, function to start listening for locations.
// class implements android.location.LocationListener interface
this.locman = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
if( !this.locman.isProviderEnabled(LocationManager.GPS_PROVIDER) ){
Log.d("","GPS is not enabled");
}else{
this.locman.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
this.onLocationChanged( this.locman.getLastKnownLocation(LocationManager.GPS_PROVIDER) );
}
android.location.LocationListener implementation of onLocationChanged function:
@Override
public void onLocationChanged(Location location)
{
... showing provided Location on the map
}
in manifest file:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
This can give me relatively frequent updates, but sometimes has huge gaps. I believe maybe it's problem with connecting with enough satellites, however if I open Google Maps in the same time - it works flawlessly. No time gaps between location updates, and more precise than what I am getting here.
I thought it may be needed to use LocationClient and LocationRequest instead, counting that maybe Google Play API may have some internal interpolation / prediction / whatever that improves precision.
b) Using GooglePlay API with LocationClient and LocationRequest. I've installed Google Play SDK, and also tried Google's sample apps. Here is my code related to this:
// in service class, function to start listening for locations.
// class implements com.google.android.gms.location.LocationListener,
// com.google.android.gms.common.ConnectionResult.OnConnectionFailedListener and
// com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks interface
this.locclient = new LocationClient(this.getApplicationContext(),this,this);
this.locclient.connect();
implementation of onConnected:
@Override
public void onConnected(Bundle dataBundle)
{
LocationRequest req = LocationRequest.create();
req.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
req.setInterval(2000); // 2 sec
req.setFastestInterval(16); // 60 fps
this.locclient.requestLocationUpdates(req, this);
}
And of course onConnectionFailed and onDisconnected is implemented and breakpointed - never gets in, while onConnected is called.
Implementation of com.google.android.gms.location.LocationListener:
@Override
public void onLocationChanged(Location location)
{
... showing provided Location on the map
}
In this case, I get updates immediately, however off for like 200m or more.
In desperation, I tried MyLocation app that is on Google Play and it shows SAME OFFSET!
When I try Google Maps, in the same time, it shows absolute accuracy like 5-6m the most.
Important notice: I am located in Shanghai, China. Not sure if this is related in any way.
How is it possible to have such huge offset between Google Maps and Google's own example of location service (MyLocationDemoActivity.java, provided in google_play_services/samples/maps/)?? To clarify: Google's map demo provided with Google Play Services sample codes, also shows SAME OFFSET (~200m) away from my real location, while in the same time Google Maps app shows precise location.
I'm using Nexus 4 as development platform.
Compiler is ADT (Eclipse). All up-to-date.
Really hope for some quick breakthrough from anyone here!!! Thanks in advance!
P.S.
I have now tried to use LocationRequest.PRIORITY_NO_POWER as setting for location request, to have my app get location update only when another app requested it. I've then started Google Maps, and switched back to my app. It immediately received location. I've copied long/lat into http://maps.googleapis.com/maps/api/staticmap?center=31.229179,121.422615&zoom=16&format=png&sensor=false&size=640x640&maptype=roadmap to test it out, and it is showing SAME OFFSET. While Google Maps on my phone shows exact location.
Is it possible that maps from Google have offset? Or that there is an offset to long/lat received?
I don't have enough reputation to comment yet so I'm writing an answer.
This is most likely related to the China GPS offset problem. The Chinese government insists on not allowing users to record accurate GPS data in some scenarios ("national security something blah blah") and force companies like Apple/Google to abide by the local laws.
Here is a link with some good information on the topic: http://www.sinosplice.com/life/archives/2013/07/16/a-more-complete-ios-solution-to-the-china-gps-offset-problem
As in above answer, offset is because of China government regulation. However people managed to get transform used at least by GoogleMaps and HEREMaps. It is here written in C#. Using that you can convert real coordinates to transformed ones with maximum 20 meters error. There are also more accurate implementations.
If you don't want to modify your software, you can use something based on this. It is my simple Xposed module to convert coordinates for all applications using LocationManager.