问题
I am investigating GPS location on Samsung Galaxy2 (Android 2.3.5). SG2 supports A-GPS, so I turned GPS, Wifi network and Sensor aiding on. It looks working well but sometimes the GPS gives completely different location more than 50km far from my current place. Also the location changes often even though I just put on the phone one spot and never touched.
I am still new to Android, so I not sure what causes this problem. Below is the source code handling GPS location.:
public class LocationMonitor extends Service implements LocationListener,Runnable {
.... other local variables here
Object locationUpdateNotifier= null;
public static GeoPoint ourLocation;
public void synchronize()
{
if(ourLocation == null)
{
ourLocation = getLastKnownLocation();
if(ourLocation == null) return;
}
//Load last time we synced
long lastSyncTime = some_value;
if(lastSyncTime < System.currentTimeMillis() - UPDATE_FREQ) //UPDATE_FREQ - default 30 minutes
{
handler.post(new Runnable() {
public void run() {
GpsPingTask pingTask = new GpsPingTask(context,String.valueOf(ourLocation.getLatitudeE6()/1E6),String.valueOf(ourLocation.getLongitudeE6()/1E6));
pingTask.execute((Void)null); //Send location to server
}
});
lastSyncTime = System.currentTimeMillis();
//Save new lastSync time
}
}
public void kill()
{
if(locationManager !=null)
locationManager.removeUpdates(this);
}
public void onLocationChanged(Location location) {
try
{
//Read latitude and longitude from location
//Create Geo point so we can get a english street name address
ourLocation = new GeoPoint((int)(location.getLatitude()*1E6),(int)(location.getLongitude()*1E6));
if(locationUpdateNotifier != null)
{
synchronized (locationUpdateNotifier) {
locationUpdateNotifier.notify();
}
}
if(!doneFirstUpdate)
{
doneFirstUpdate =true;
Log.i("LocationMointor", "LocationMonitor.onLocationChanged() done first update at 0 frequency, resetting to normal speed");
//Set it to update at the requested frequency
resetLocationUpdatesFreq();
}
startSynchronizeThread();
}
catch (Throwable e) {
Log.i("LocationMointor", "LocationMonitor.onLocationChanged(): " + e);
}
}
public void onProviderDisabled(
String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void setTemporaryLocationUpdateFreq(int pingFreqSecs) {
setTemporaryLocationUpdateFreq(pingFreqSecs, 10);
}
public void setTemporaryLocationUpdateFreq(int pingFreqSecs, int minimumDistanceMeters) {
if(!doneFirstUpdate)
doneFirstUpdate =true;
tempLocationUpdateFreq = pingFreqSecs;
tempLocationUpdateMeters = minimumDistanceMeters;
handler.post(new Runnable()
{
public void run() {
//Turn of location updates
if(locationManager !=null)
locationManager.removeUpdates(locationMonitor);
//Restart location updates with new frequency
locationManager.requestLocationUpdates(getGpsMode(), UPDATE_FREQ, tempLocationUpdateMeters,locationMonitor);
//locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, tempLocationUpdateFreq*1000, tempLocationUpdateMeters,locationMonitor);
}
});
}
private void startSynchronizeThread() {
if(!running)
new Thread(this).start();
}
public void resetLocationUpdatesFreq() {
locationUpdateNotifier = null;
handler.post(new Runnable()
{
public void run() {
//Turn of location updates
if(locationManager !=null) {
locationManager.removeUpdates(locationMonitor);
//Restart location updates with default location update frequency
//locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MINIMUM_TIME_BETWEEN_UPDATE, MINIMUM_DISTANCECHANGE_FOR_UPDATE,locationMonitor);
}
}
});
}
public void setLocationUpdateFreq(int pingFreqMins) {
Log.i("LocationMointor", "LocationMonitor.setLocationUpdateFreq().mode: " + getGpsMode() + "pingFreq:" + pingFreqMins);
//Save new frequency value
SharedPreferences pref = context.getSharedPreferences(PREF_PING_FREQ, Context.MODE_PRIVATE);
Editor prefEditor= pref.edit();
prefEditor.putInt(PREF_PING_FREQ, 10);
prefEditor.commit();
handler.post(new Runnable()
{
public void run() {
//Turn of location updates
if(locationManager !=null)
locationManager.removeUpdates(locationMonitor);
//Restart location updates with new piong frequency
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MINIMUM_TIME_BETWEEN_UPDATE, MINIMUM_DISTANCECHANGE_FOR_UPDATE,locationMonitor);
}
});
}
public void addUpdateNotify(Object notifyable)
{
this.locationUpdateNotifier = notifyable;
}
public GeoPoint getLastKnownLocation()
{
Criteria crit = new Criteria();
//Try get last known fine location
crit.setAccuracy(Criteria.ACCURACY_FINE);
String provider = locationManager.getBestProvider(crit, false);
Location loc = locationManager.getLastKnownLocation(provider);
//If we got no location, try coarse location
if(loc == null)
{
crit.setAccuracy(Criteria.ACCURACY_COARSE);
provider = locationManager.getBestProvider(crit, false);
loc = locationManager.getLastKnownLocation(provider);
//If nothing, return nothing
if(loc == null)
{
Log.i("LocationMointor", "LocationMonitor.getLastKnownLocation() got no location");
return null;
}
}
//Create geopoint and return it.
GeoPoint geoPoint = new GeoPoint((int)(loc.getLatitude()*1E6),(int)(loc.getLongitude()*1E6));
Log.i("LocationMointor", "LocationMonitor.getLastKnownLocation() got " +geoPoint);
return geoPoint;
}
@Override
public void run() {
running = true;
Object pauser = new Object();
do{
try
{
synchronize();
synchronized(pauser)
{
pauser.wait(UPDATE_FREQ);
}
}
catch(Throwable ex)
{
Log.e("LocationMointor", "LocationMonitor.run() " +ex);
}
}
while(running);
}
public void onCreate() {
super.onCreate();
this.context = this;
this.locationMonitor= this;
handler = new Handler();
//Get the location manager service
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
//Start gps to get our location
this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, UPDATE_FREQ, this);
}
@Override
public void onDestroy() {
super.onDestroy();
kill();
}
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
private final IBinder mBinder = new MyBinder();
public class MyBinder extends Binder {
public LocationMonitor getService() {
return LocationMonitor.this;
}
}
}
Would you please help me to get over this issue? Thanks in advance.
回答1:
Unlike the original Galaxy S phone, the GS2's GPS works okay.
Judging from your code you're using getLastKnownLocation and falling back to Coarse when GPS is not available. So I think that's just what's happening: - you're getting either a very outdated GPS location - or a coarse location and Google doesn't map your area very well so it's off.
You can check these assumptions by adding logs or by checking the provider and the timestamp of the non-null location object you are getting from getLastKnownLocation().
回答2:
If you check the location on a real device and you are staying on the same spot I noticed myself that it can vary a little bit from location (you see this also in GPS software that does not know in what direction you are looking before you are driving/moving). So a slight change in the location is possible but normally not 50km. Do you have another device to test if it is device dependant that problem of the 50 km?
来源:https://stackoverflow.com/questions/9988925/incorrect-gps-location-on-samsung-galaxy2