Search code examples
androidgpslocationmanagerfusion

Gps and Network state to calculate location is not accurate inside buildings


Location manager is not giving accurate location data inside building and its hard to handle gps and Network state together. Are there any solutions for this problem to calculate exact datas better than this.i want to use this in the taxi meter App.

public Location getLocation() {
        try {
            mLocationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);

            // getting GPS status
            boolean isGPSEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

            // getting network status
            boolean isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // no network provider is enabled
            } else {
                // First get location from Network Provider
                if (isNetworkEnabled) {
                    mLocationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER,  MIN_TIME_BW_UPDATES,  MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (mLocationManager != null) {
                        location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            lat = location.getLatitude();
                            lng = location.getLongitude();
                        }
                    }
                }
                //get the location by gps
                if (isGPSEnabled) {
                    if (location == null) {
                        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (mLocationManager != null) {location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                lat = location.getLatitude();
                                lng = location.getLongitude();
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }

Solution

  • use the fusion API that google developer have developed with fusion of GPS Sensor,Magnetometer,Accelerometer also using Wifi or cell location to calculate or estimate the location. It is also able to give location updates also inside the building accurately.

    package com.example.ashis.gpslocation;
    
    import android.app.Activity;
    import android.location.Location;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.GooglePlayServicesUtil;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
    import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
    import com.google.android.gms.location.LocationListener;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Location sample.
     *
     * Demonstrates use of the Location API to retrieve the last known location for a device.
     * This sample uses Google Play services (GoogleApiClient) but does not need to authenticate a user.
     * See https://github.com/googlesamples/android-google-accounts/tree/master/QuickStart if you are
     * also using APIs that need authentication.
     */
    
    public class MainActivity extends Activity implements LocationListener,
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener {
    
        private static final long ONE_MIN = 500;
        private static final long TWO_MIN = 500;
        private static final long FIVE_MIN = 500;
        private static final long POLLING_FREQ = 1000 * 20;
        private static final long FASTEST_UPDATE_FREQ = 1000 * 5;
        private static final float MIN_ACCURACY = 1.0f;
        private static final float MIN_LAST_READ_ACCURACY = 1;
    
        private LocationRequest mLocationRequest;
        private Location mBestReading;
    TextView tv;
        private GoogleApiClient mGoogleApiClient;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            if (!servicesAvailable()) {
                finish();
            }
    
            setContentView(R.layout.activity_main);
    tv= (TextView) findViewById(R.id.tv1);
            mLocationRequest = LocationRequest.create();
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            mLocationRequest.setInterval(POLLING_FREQ);
            mLocationRequest.setFastestInterval(FASTEST_UPDATE_FREQ);
    
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
    
    
            if (mGoogleApiClient != null) {
                mGoogleApiClient.connect();
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            if (mGoogleApiClient != null) {
                mGoogleApiClient.connect();
            }
        }
    
        @Override
        protected void onPause() {d
            super.onPause();
    
            if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
                mGoogleApiClient.disconnect();
            }
        }
    
    
            tv.setText(location + "");
            // Determine whether new location is better than current best
            // estimate
            if (null == mBestReading || location.getAccuracy() < mBestReading.getAccuracy()) {
                mBestReading = location;
    
    
                if (mBestReading.getAccuracy() < MIN_ACCURACY) {
                    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
                }
            }
        }
    
        @Override
        public void onConnected(Bundle dataBundle) {
            // Get first reading. Get additional location updates if necessary
            if (servicesAvailable()) {
    
                // Get best last location measurement meeting criteria
                mBestReading = bestLastKnownLocation(MIN_LAST_READ_ACCURACY, FIVE_MIN);
    
                if (null == mBestReading
                        || mBestReading.getAccuracy() > MIN_LAST_READ_ACCURACY
                        || mBestReading.getTime() < System.currentTimeMillis() - TWO_MIN) {
    
                    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    
                   //Schedule a runnable to unregister location listeners
    
                        @Override
                        public void run() {
                            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, MainActivity.this);
    
                        }
    
                    }, ONE_MIN, TimeUnit.MILLISECONDS);
    
                }
    
            }
        }
    
        @Override
        public void onConnectionSuspended(int i) {
    
        }
    
    
        private Location bestLastKnownLocation(float minAccuracy, long minTime) {
            Location bestResult = null;
            float bestAccuracy = Float.MAX_VALUE;
            long bestTime = Long.MIN_VALUE;
    
            // Get the best most recent location currently available
            Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            //tv.setText(mCurrentLocation+"");
            if (mCurrentLocation != null) {
                float accuracy = mCurrentLocation.getAccuracy();
                long time = mCurrentLocation.getTime();
    
                if (accuracy < bestAccuracy) {
                    bestResult = mCurrentLocation;
                    bestAccuracy = accuracy;
                    bestTime = time;
                }
            }
    
            // Return best reading or null
            if (bestAccuracy > minAccuracy || bestTime < minTime) {
                return null;
            }
            else {
                return bestResult;
            }
        }
    
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
    
        }
    
        private boolean servicesAvailable() {
            int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    
            if (ConnectionResult.SUCCESS == resultCode) {
                return true;
            }
            else {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0).show();
                return false;
            }
        }
    }