Showpath
Showpath

Reputation: 678

LocationClient by Google Services not using GPS data

I am currently trying the LocationClient provided by Google Services. When I am next to a building I receive frequent location updates but in the middle of a road they are less frequent and less accurate. In the country side, no updates at all. I wondered if the Google Location Services uses the GPS so I disabled all location providers but the GPS in the phone's settings and I instantly stopped receiving any update. Obviously my LocationClient does not receive any update using GPS data.

Am I missing something? Is there anything I have to set for the LocationClient or do I have to use the standard LocationManager.GPS_PROVIDER?

I am trying to build an app for running and I need accurate location data. Any advice would be much appreciated ;-)!

Here is the implementation that I use:

public class CustomLocationProvider implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener, android.location.LocationListener {

    private static final float DATA_UPDATE_DISTANCE = 100.0f;
    private static final long ONE_MIN = 1000 * 60;
    private static final long FIVE_MIN = ONE_MIN * 5;
    private static final int UPDATE_TIME = 5000;
    private static final int FASTEST_INTERVAL = 16;
    private static final int ACCURACY_THRESHOLD = 30;

    private Context mContext;
    private LocationClient mLocationClient;
    private Location mPreviousLocation;
    private float mTotalDistance;
    private float mDistanceSinceLastUpdate = 0.0f;

    private WeakReference<Activity> mDelegate;

    public interface LocationProviderDelegate {
        void locationUpdated(Location location);
    }

    // These settings are the same as the settings for the map. They will in fact give you updates
    // at the maximal rates currently possible.
    private static final LocationRequest REQUEST = LocationRequest.create()
            .setInterval(UPDATE_TIME)         // 5 seconds
            .setFastestInterval(FASTEST_INTERVAL)    // 16ms = 60fps
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    public CustomLocationProvider (Context context, Activity delegate) {
        if(context != null) {
            mContext = context;
            mDelegate = new WeakReference<Activity>(delegate);
        }
    }

    public void enableTracking(boolean enable) {
        if(enable) {

            setUpLocationClientIfNeeded();
            mLocationClient.connect();
        } else {
            if(mLocationClient != null) {
                mLocationClient.disconnect();
            }
        }
    }

    private void setUpLocationClientIfNeeded() {
        if (mLocationClient == null) {
            mLocationClient = new LocationClient(
                    mContext,
                    this,  // ConnectionCallbacks
                    this); // OnConnectionFailedListener
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        if(mPreviousLocation != null
                && location.getTime() > mPreviousLocation.getTime()
                && location.getAccuracy() < ACCURACY_THRESHOLD)
        {
            float distanceIncrement =  mPreviousLocation.distanceTo(location);
            mDistanceSinceLastUpdate += distanceIncrement;
            mTotalDistance += distanceIncrement;

            if(mDistanceSinceLastUpdate >= DATA_UPDATE_DISTANCE)
            {
                mDistanceSinceLastUpdate = 0.0f;
                requestDataUpdate(location);
            }

            updateLocation(location);
        } else if( mPreviousLocation == null){
            requestDataUpdate(location);
            updateLocation(location);
        }
    }

    private void updateLocation(Location location) {
        try {
            ((LocationProviderDelegate) mDelegate.get()).locationUpdated(location);
        } catch (Exception e) {
            Logger.logError("Cannot cast as a LocationProviderDelegate");
        }
        mPreviousLocation = location;
    }

    /**
     * Callback called when connected to GCore. Implementation of {@link ConnectionCallbacks}.
     */
    @Override
    public void onConnected(Bundle connectionHint) {
        mLocationClient.requestLocationUpdates(
                REQUEST,
                this);  // LocationListener
        Location location = mLocationClient.getLastLocation();
        if (location != null) {
            if (age(location) < FIVE_MIN) {
                mPreviousLocation = location;
                requestDataUpdate(location);
            }
        }
    }

    /**
     * Callback called when disconnected from GCore. Implementation of {@link ConnectionCallbacks}.
     */
    @Override
    public void onDisconnected() {
        // Do nothing
    }

    /**
     * Implementation of {@link OnConnectionFailedListener}.
     */
    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Logger.postMessageToTheUser("Connection failed", mDelegate.get());
    }

    public void Reset(){
        mTotalDistance = 0;
    }

    public float TotalDistance() {
        return mTotalDistance;
    }

    public void requestDataUpdate(Location location)
    {
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        double offset = 0.002;

        LatLngBounds bounds = LatLngBounds.builder()
                .include(new LatLng(latitude - offset, longitude - offset))
                .include(new LatLng(latitude + offset, longitude + offset))
                .build();

        updateData();
    }


    private long age(Location location) {
        return System.currentTimeMillis() - location.getTime();
    }

    @Override
    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        String newStatus = "";
        switch (status) {
        case LocationProvider.OUT_OF_SERVICE:
            newStatus = "OUT_OF_SERVICE";
            break;
        case LocationProvider.TEMPORARILY_UNAVAILABLE:
            newStatus = "TEMPORARILY_UNAVAILABLE";
            break;
        case LocationProvider.AVAILABLE:
            newStatus = "AVAILABLE";
            break;
        }
        String msg = provider + ": " + newStatus;
        Logger.postMessageToTheUser(msg, mDelegate.get());
    }
}

Upvotes: 0

Views: 512

Answers (1)

Emmanuel
Emmanuel

Reputation: 13223

The LocationClient provided by Google Play Services, uses a fused location provider. This means that it will use the best provider available along with the phone's sensors to give you the most accurate location it can.

It seems from your code that you are disregarding updates if the location accuracy is less than 30m. Remember that even though GPS is the most accurate way to get a location you cannot control how accurate that location is.

Also, calling LocationRequest.create() will create the request with default parameters. I would think you want to call create() last (after setInterval(),etc ) instead of first.

Upvotes: 1

Related Questions