Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
125 views
in Technique[技术] by (71.8m points)

Can anyone explain me how GPS tracking is working in Android

I'm looking for GPS coordinates. My criteria are:

  1. is not equal to the last location

  2. Accuracy < 500

In general terms, System should accept GPS coords that are <200m aprox.

I've made 4 tries in my app:

First try:

19.3820126,-99.1647096:Acc:50.528 Last location ( That's why we keep searching - error 3 km)
01-29 10:37:42.698  onLocationChanged﹕ 19.364292,-99.1776019:Acc:660.0 (error: Aprox 60 m - should accept it)
01-29 10:37:47.733  onLocationChanged﹕ 19.3639126,-99.1771124:Acc:660.0 (error: Aprox 80 m - should accept it)
01-29 10:37:52.788  onLocationChanged﹕ 19.3639126,-99.1771124:Acc:660.0 (error: Aprox 80 m - should accept it)
01-29 10:37:57.853  onLocationChanged﹕ 19.3820112,-99.1646983:Acc:50.531 (Last location - error 3km)... System get the wrong coord.

Second try:

01-29 10:42:05.885  onLocationChanged﹕ 19.3652615,-99.1782989:Acc:784.0 (error: Aprox 100 m - should accept it)
01-29 10:42:10.980  onLocationChanged﹕ 19.3652615,-99.1782989:Acc:784.0 (error: Aprox 100 m - should accept it)
01-29 10:42:15.985  onLocationChanged﹕ 19.3652615,-99.1782989:Acc:784.0 (error: Aprox 100 m - should accept it)
01-29 10:42:21.020  onLocationChanged﹕ 19.3652615,-99.1782989:Acc:784.0 (error: Aprox 100 m - should accept it)
01-29 10:42:26.085  onLocationChanged﹕ 19.3652615,-99.1782989:Acc:784.0 (error: Aprox 100 m - How can onLocationChanged can be called if location is not changing)

Third try:

01-29 10:47:20.002  onLocationChanged﹕ 19.3652615,-99.1782989:Acc:784.0 (Last location - error: Aprox 100 m)
01-29 10:47:25.037  onLocationChanged﹕ 19.3820153,-99.1646946:Acc:50.532 (Last location - error 3km)... System get the wrong coord.

Fourth try:

01-29 11:00:25.518  onLocationChanged﹕ 19.3651962,-99.1780395:Acc:639.0 (error: Aprox 100 m - should accept it)
01-29 11:00:34.016  onLocationChanged﹕ 19.3651962,-99.1780395:Acc:639.0 (error: Aprox 100 m - should accept it)
01-29 11:00:38.451  onLocationChanged﹕ 19.3651962,-99.1780395:Acc:639.0 (error: Aprox 100 m - should accept it)
01-29 11:00:43.455  onLocationChanged﹕ 19.3651962,-99.1780395:Acc:639.0 (error: Aprox 100 m - should accept it)
01-29 11:00:48.530  onLocationChanged﹕ 19.3651962,-99.1780395:Acc:639.0 (error: Aprox 100 m - should accept it)
01-29 11:00:53.585  onLocationChanged﹕ 19.3651962,-99.1780395:Acc:639.0 Time's up, app doesn't accept the coord ( criteria is Acc < 500), but I could accept it.

Those 4 tries make me ask a lot:

  1. is Accuracy a trustable factor. I understand that the smaller the accuracy, the better result. Nevertheless, I find out here that trusting the accuracy get me the wrong result.

  2. In the first and third try, why the accecpted coord is another coord (my home, and I am at work)

  3. In the second try, why is onLocationChanged called if the coord is the same

My code is very standard:

public class LocationUtils implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final long ONE_MIN = 1000 * 60;
private Context ctx;
// Debugging tag for the application
public static final String APPTAG = "LocationSample";

public static final int MILLISECONDS_PER_SECOND = 1000;

// The update interval
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;

// A fast interval ceiling
public static final int FAST_CEILING_IN_SECONDS = 1;

// Update interval in milliseconds
public static final long UPDATE_INTERVAL_IN_MILLISECONDS =
        MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;

// A fast ceiling of update intervals, used when the app is visible
public static final long FAST_INTERVAL_CEILING_IN_MILLISECONDS =
        MILLISECONDS_PER_SECOND * FAST_CEILING_IN_SECONDS;
public static final long FASTEST_INTERVAL_CEILING_IN_MILLISECONDS = 100; // 16ms = 60fps

// Create an empty string for initializing strings
public static final String EMPTY_STRING = new String();
public static GoogleApiClient mGoogleApiClient;
public static LocationRequest mLocationRequest;
private int mAction;



public LocationUtils(Context context) {
    ctx = context;
}


public static void disconnectGPS(LocationListener list) {
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        stopPeriodicUpdates(mGoogleApiClient, list);
        mGoogleApiClient.disconnect();
    }
}

public static void startPeriodicUpdates(GoogleApiClient mGoogleApiClient, LocationRequest mLocationRequest, LocationListener listener) {
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, listener);

}

public static void stopPeriodicUpdates(GoogleApiClient mGoogleApiClient, LocationListener listener) {
    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, listener);
}

public void init_location(Context ctx) {
    mGoogleApiClient = new GoogleApiClient.Builder(ctx)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    mLocationRequest = LocationRequest.create();

    /*
     * Set the update interval
     */
    mLocationRequest
            .setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);

    // Use high accuracy
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    // Set the interval ceiling to one minute
    mLocationRequest
            .setFastestInterval(FAST_INTERVAL_CEILING_IN_MILLISECONDS);
    mLocationRequest
            .setFastestInterval(FASTEST_INTERVAL_CEILING_IN_MILLISECONDS);
}


public static boolean servicesAvailable(Context ctx) {
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(ctx);

    if (ConnectionResult.SUCCESS == resultCode) {
        return true;
    } else {
        GooglePlayServicesUtil.getErrorDialog(resultCode, (Activity) ctx, 0).show();
        return false;
    }
}

@Override
public void onConnected(Bundle bundle) {
        startPeriodicUpdates(mGoogleApiClient,mLocationRequest, this);
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onLocationChanged(Location location) {
    Log.e("onLocationChanged",location.getLatitude()+","+location.getLongitude()+":Acc:"+location.getAccuracy() );
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

public void connect(int action) {
    mAction = action;
    if (!mGoogleApiClient.isConnected()) {
        mGoogleApiClient.connect();
        }


    }
}

I'm testing with several devices, Samsung s4, s3 mini, core 2. I always have GPS on, no wifi, but 3G activated.

EDIT: I'm testing indoor, so GPS results should not be great, but I expect Fused Location adapting to my situation as I can no longer choose the provider.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Accuracy is only 68% probability that your location is within the radius, so there is still a pretty good chance that it's incorrect.

By no WiFi you mean you are not connected to any network or that WiFi is disabled?

For example, if you had WiFi router in one place and then move to a new place and take WiFi router with you, Google will still return old location for quite a while.

As for your last question, you requested to update location every 5 seconds, so you will get callback with specified period even if location is the same.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...