Getting Latitude and longitude in 30 seconds

I am trying to get location of user as longitude and latitude from GPS/network which ever is available and i want to get it fast , or else previous location coordinates will return if cannot get new one right now.

Here is my attempt:

public class GPSTracker extends Service{


    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
    private final Context mContext;
    // Declaring a Location Manager
    protected LocationManager locationManager;
    // flag for GPS status
    boolean isGPSEnabled = false;
    // flag for network status
    boolean isNetworkEnabled = false;
    // flag for GPS status
    boolean canGetLocation = false;
    Location location = null; // location
    double latitude; // latitude
    double longitude; // longitude
    myLocationLitener locationLitener;

    public GPSTracker(Context context) {
        this.mContext = context;
        locationLitener = new myLocationLitener();
        getLocation();
    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);

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

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

            if (!isGPSEnabled && !isNetworkEnabled) {
                // no network provider is enabled
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES,locationLitener);
                    Log.d("Network", "Network Enabled");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                            // TODO: Consider calling
                            //    ActivityCompat#requestPermissions
                            // here to request the missing permissions, and then overriding
                            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                            //                                          int[] grantResults)
                            // to handle the case where the user grants the permission. See the documentation
                            // for ActivityCompat#requestPermissions for more details.
                            return null;
                        }
                        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, locationLitener);
                        Log.d("GPS", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }

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

        return location;
    }

    /**
     * Stop using GPS listener Calling this function will stop using GPS in your
     * app
     */
    public void stopUsingGPS() {
        if (locationManager != null) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            locationManager.removeUpdates(locationLitener);
        }
    }

    /**
     * Function to get latitude
     */
    public double getLatitude() {
        if (location != null) {
            latitude = location.getLatitude();
        }

        // return latitude
        return latitude;
    }

    /**
     * Function to get longitude
     */
    public double getLongitude() {
        if (location != null) {
            longitude = location.getLongitude();
        }

        // return longitude
        return longitude;
    }

    /**
     * Function to check GPS/wifi enabled
     *
     * @return boolean
     */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }

    /**
     * Function to show settings alert dialog On pressing Settings button will
     * lauch Settings Options
     */
    public void showSettingsAlert() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // Setting Dialog Title
        alertDialog.setTitle("GPS is settings");

        // Setting Dialog Message
        alertDialog
                .setMessage("GPS is not enabled. Do you want to go to settings menu?");

        // On pressing Settings button
        alertDialog.setPositiveButton("Settings",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(
                                Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        mContext.startActivity(intent);
                    }
                });

        // on pressing cancel button
        alertDialog.setNegativeButton("Cancel",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });

        // Showing Alert Message
        alertDialog.show();
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    private class myLocationLitener implements LocationListener{

        @Override
        public void onLocationChanged(Location location) {

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    }
}

How i use this class?

Suppose i am running below function in async task (who don't have knowledge of android annotation @Background is doing this)

 @Background
    void getmyLocationAndSend(){
        GPSTracker gps = new GPSTracker(context);

        // check if GPS location can get Location
        if (gps.canGetLocation()) {

            LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

            if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                Log.d("Your Location", "latitude:" + gps.getLatitude()
                        + ", longitude: " + gps.getLongitude());

                latitude = gps.getLatitude(); // set the globals
                longitude = gps.getLongitude(); // set the globals
            }else{
                showToast("Network is connected..");
                if (progress != null && progress.isShowing()) {
                    progress.dismiss();
                }
            }
        }else{
            showToast("Cannot get location from gps..");
            if (progress != null && progress.isShowing()) {
                progress.dismiss();
            }
        }
    }

my goal is to get coordinates in less than 30 seconds , and never get 0.0 value , how can i achieve that any help appreciated ?


Solution 1:

Please check how i'm using in my app and its working perfect.I'm using fused api for update location please follow few steps.Currently you using very old approach.So, there is no need now and pass here your time in milliseconds what you want UPDATE_INTERVAL_IN_MILLISECONDS

Step 1. Make this class GoogleLocationService.java

public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;

public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;


public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
    this.locationUpdateListener = locationUpdateListener;
    this.activity = activity;
    buildGoogleApiClient();
}

protected synchronized void buildGoogleApiClient() {
    //Log.i(TAG, "Building GoogleApiClient");
    mGoogleApiClient = new GoogleApiClient.Builder(activity)
            .addConnectionCallbacks(callbacks)
            .addOnConnectionFailedListener(callbacks)
            .addApi(LocationServices.API)
            .build();
    createLocationRequest();
    mGoogleApiClient.connect();
}

protected void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

}

private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    @Override
    public void onConnected(Bundle bundle) {
        startLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

        if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
            Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();

        }
        locationUpdateListener.cannotReceiveLocationUpdates();
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location.hasAccuracy()) {
            if (location.getAccuracy() < 30) {
                locationUpdateListener.updateLocation(location);
            }
        }
    }
}

private static boolean locationEnabled(Context context) {
    boolean gps_enabled = false;
    LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    try {
        gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return gps_enabled;
}

private boolean servicesConnected(Context context) {
    return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}

private boolean isPackageInstalled(String packagename, Context context) {
    PackageManager pm = context.getPackageManager();
    try {
        pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}


public void startUpdates() {
    /*
     * Connect the client. Don't re-start any requests here; instead, wait
     * for onResume()
     */
    if (servicesConnected(activity)) {
        if (locationEnabled(activity)) {
            locationUpdateListener.canReceiveLocationUpdates();
            startLocationUpdates();
        } else {
            locationUpdateListener.cannotReceiveLocationUpdates();
            Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
        }
    } else {
        locationUpdateListener.cannotReceiveLocationUpdates();
        Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
    }
}

//stop location updates
public void stopUpdates() {
    stopLocationUpdates();
}

//start location updates
private void startLocationUpdates() {

    if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    if (mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
    }
}

public void stopLocationUpdates() {
    if (mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
    }
}

public void startGoogleApi() {
    mGoogleApiClient.connect();
}

public void closeGoogleApi() {
    mGoogleApiClient.disconnect();
}

 }

Step2. Make this interface LocationUpdateListener.java

 public interface LocationUpdateListener {

/**
 * Called immediately the service starts if the service can obtain location
 */
void canReceiveLocationUpdates();

/**
 * Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
 */
void cannotReceiveLocationUpdates();

/**
 * Called whenever the location has changed (at least non-trivially)
 * @param location
 */
void updateLocation(Location location);

/**
 * Called when GoogleLocationServices detects that the device has moved to a new location.
 * @param localityName The name of the locality (somewhere below street but above area).
 */
void updateLocationName(String localityName, Location location);
}

Step 3. Make this Location service class LocationService.java

public class LocationService extends Service {

private GoogleLocationService googleLocationService;

@Override
public void onCreate() {
    super.onCreate();
    //start the handler for getting locations
    //create component

    updateLocation(getApplicationContext());
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return Service.START_STICKY;
}

//get current location os user
private void updateLocation(Context context) {
    googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
        @Override
        public void canReceiveLocationUpdates() {
        }

        @Override
        public void cannotReceiveLocationUpdates() {
        }

        //update location to our servers for tracking purpose
        @Override
        public void updateLocation(Location location) {
            if (location != null ) {
                Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());

            }
        }

        @Override
        public void updateLocationName(String localityName, Location location) {

            googleLocationService.stopLocationUpdates();
        }
    });
    googleLocationService.startUpdates();
}


IBinder mBinder = new LocalBinder();


public class LocalBinder extends Binder {
    public LocationService getServerInstance() {
        return LocationService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

//stop location updates on stopping the service
@Override
public void onDestroy() {
    super.onDestroy();
    if (googleLocationService != null) {
        googleLocationService.stopLocationUpdates();
    }
}
}

Edited Answer:

How to use service,

Start service in your main activity,like this

startService(new Intent(context, LocationService.class));

for stop,

stopService(new Intent(context, LocationService.class));

and declare in manifest like this,

<service
 android:name=".service.location.LocationService"
 android:enabled="true"></service>

Note: I have done this because i need location after killed the app.If you dont want service.Then,you can call directly below code in class where location need to be update and remove locationservice.

 private GoogleLocationService googleLocationService;

 googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
    @Override
    public void canReceiveLocationUpdates() {
    }

    @Override
    public void cannotReceiveLocationUpdates() {
    }

    //update location to our servers for tracking purpose
    @Override
    public void updateLocation(Location location) {
        if (location != null ) {
            Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());

        }
    }

    @Override
    public void updateLocationName(String localityName, Location location) {

        googleLocationService.stopLocationUpdates();
    }
});
googleLocationService.startUpdates();


and call this onDestroy 
if (googleLocationService != null) {
    googleLocationService.stopLocationUpdates();
}

Remember Locationservice should be declare in manifest as well. According to me this is the best solution.I have done alot of work on location. Thanks hope this will help you