1

I am trying to retrieve location via fused location api.I have tried to build a helper class so that I can use it throughout my app.

Code:

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 android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class GPSTracker2  implements ConnectionCallbacks,
        OnConnectionFailedListener,LocationListener {
    // LogCat tag
    private static final String TAG = GPSTracker2.class.getSimpleName();

    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;

    private Location mLastLocation;

    // Google client to interact with Google API
    private GoogleApiClient mGoogleApiClient;

    // boolean flag to toggle periodic location updates
    private boolean mRequestingLocationUpdates = false;

    private LocationRequest mLocationRequest;

    // Location updates intervals in sec
    private static int UPDATE_INTERVAL = 1000; // 10 sec
    private static int FATEST_INTERVAL = 500; // 5 sec
    private static int DISPLACEMENT = 10; // 10 meters

   Context context;
// flag for GPS status
    boolean canGetLocation = true;

    double latitude,longitude;

        public GPSTracker2(Context context) {
            // TODO Auto-generated constructor stub
              // First we need to check availability of play services
            this.context=context;
             createLocationRequest();
            if (checkPlayServices()) {

                // Building the GoogleApi client
                buildGoogleApiClient();
            }

            if (mGoogleApiClient != null) {
                mGoogleApiClient.connect();
            }
            // Show location button click listener
        }





    /**
     * Method to display the location on UI
     * */
    /*private void displayLocation() {

        mLastLocation = LocationServices.FusedLocationApi
                .getLastLocation(mGoogleApiClient);

        if (mLastLocation != null) {
            double latitude = mLastLocation.getLatitude();
            double longitude = mLastLocation.getLongitude();

        } else {


        }
    }*/

        /**
         * Method to display the location on UI
         * */
        private void displayLocation() {

            mLastLocation = LocationServices.FusedLocationApi
                    .getLastLocation(mGoogleApiClient);

            if (mLastLocation != null) {
                double latitude = mLastLocation.getLatitude();
                double longitude = mLastLocation.getLongitude();

            Toast.makeText(context,latitude+" "+longitude,Toast.LENGTH_LONG).show();

            } else {


            }
        }
    /**
     * Function to get latitude
     * */
    public double getLatitude(){


         mLastLocation = LocationServices.FusedLocationApi
                    .getLastLocation(mGoogleApiClient);

            if (mLastLocation != null) {
                this.canGetLocation = true;
               double latitude = mLastLocation.getLatitude();
               System.out.println("In GetLat==>"+latitude);
               return latitude;
            }else{
                System.out.println("last known null");
                return 0.0;
            }

    }

    /**
     * Function to get longitude
     * */
    public double getLongitude(){

         mLastLocation = LocationServices.FusedLocationApi
                    .getLastLocation(mGoogleApiClient);

            if (mLastLocation != null) {
                this.canGetLocation = true;
               longitude = mLastLocation.getLongitude();
               System.out.println("In Getlong==>"+longitude);
            }
            return longitude;
    }

    /**
     * Creating google api client object
     * */
    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(context)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API).build();
    }

    /**
     * Method to verify google play services on the device
     * */
    private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil
                .isGooglePlayServicesAvailable(context);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, (Activity) context,
                        PLAY_SERVICES_RESOLUTION_REQUEST).show();
            } else {
                Toast.makeText(context,
                        "context device is not supported.", Toast.LENGTH_LONG)
                        .show();
                //finish();
            }
            return false;
        }
        return true;
    }

    /**
     * Creating location request object
     * */
    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FATEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
    }

    /**
     * Starting the location updates
     * */
    protected void startLocationUpdates() {

        LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);

    }

    /**
     * Stopping location updates
     */
    protected void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(
                mGoogleApiClient, this);
    }

    /**
     * Google api callback methods
     */
    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
                + result.getErrorCode());
    }

    @Override
    public void onConnected(Bundle arg0) {

        // Once connected with google api, get the location
      //  displayLocation();
        //getLatitude();
        //getLongitude();
        displayLocation();
 System.out.println("On Connected");
        if (mRequestingLocationUpdates) {
            startLocationUpdates();
        }
    }

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

    @Override
    public void onLocationChanged(Location location) {
        // Assign the new location
        mLastLocation = location;

        Toast.makeText(context, "Location changed!",
                Toast.LENGTH_SHORT).show();
        displayLocation();
        // Displaying the new location on UI
       // displayLocation();
       // getLatitude();
     //   getLongitude();
    }

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

I am trying to use this as:

The CallingClass.java

GPSTracker2 gps=new GPSTracker2(SettingsActivity.this);
        if(gps.canGetLocation())
        {
            System.out.println("lat-->"+gps.getLatitude()+" long===>"+gps.getLongitude());
        }else{
            showSettingsAlert(true);
        }

The Problem: Methods gps.getLatitude() and gps.getLongitude() is returning 0.0.But in the toast message (within the displayLocation(); method) the latitude and longitude is coming perfectly.

Hence I debugged my application and found that after calling the constructor of GpsTracker2 class,control is going back to the calling class and after finishing the onCreate of the calling class,the GoogleApiclient is getting connected.Hence it cannot fetch the latitude and longitude within the onCreate() of the calling class and hence the result.

How can I overcome this problem??

kgandroid
  • 5,507
  • 5
  • 39
  • 69
  • try definig your latitude and longitude variables at class level and in `get latitude` simply return them. though creating a model class for location would a good choic – karan Sep 08 '15 at 10:35
  • i have implemented a class like this but i can not get location because i do not know when the location is connected, so i decide to make a service, and i get get location anytime i need – Norutan Sep 08 '15 at 10:36
  • Can you please share your code??and how is the performance of your code? – kgandroid Sep 08 '15 at 10:41
  • check out this https://github.com/riteshreddyr/fused-location-provider – Zar E Ahmer Oct 26 '16 at 04:38
  • @Nepster did you used the `fused-location-provider`? I'm trying to make it work, but it seens to never connect to googleAPI so `onConnected` never gets called and I can't get the current location. Do you have a example how to used it in a fragment or activity? – lpfx Feb 28 '17 at 20:08
  • @Nepster I was mistaken. It is connecting but it takes a while. I'm using `fusedLocation.getCurrentLocation(0);` in `onStart` method to connect. The problem is that I'm using `fusedLocation.getLocation(0);` in `onResume` method and in the method `onConnected` was not called yet. So where is the best place to put the `fusedLocation.getLocation(0);` code to get the location as soon as the user open the screen? – lpfx Feb 28 '17 at 20:18
  • See my answer here. http://stackoverflow.com/a/41981246/3496570 – Zar E Ahmer Mar 01 '17 at 10:55
  • If any app has called getLocation before it will immediately return you locatiion . If you are the first one to getLocation . it would take time . May be 20 - 30 seconds. depending on your LocationRequest – Zar E Ahmer Mar 01 '17 at 10:58

2 Answers2

1

You are querying your gps helper before it has a location. For example in your getLatitude method.

public double getLatitude(){
    mLastLocation = LocationServices.FusedLocationApi
                .getLastLocation(mGoogleApiClient);

    // At first mLastKnownLocation will be null
    if (mLastLocation != null) {
        this.canGetLocation = true;
        double latitude = mLastLocation.getLatitude();
        System.out.println("In GetLat==>"+latitude);
        return latitude;
    } else {
        System.out.println("last known null");
        return 0.0; // This here is what is being returned.
    }
}

It isn't until your apiclient has called public void onLocationChanged(Location location) that a location will become available.

Method 1

Return a Location object instead of primitives. This way you can return null if it is being queried too early and the caller can handle it.

Method 2

The users of your GPS helper register a callback with it. Now they will be notified when a location is available.

In the GPSTracker class

List<LocationListener> listeners = new ArrayList<>();

public void registerListener(LocationListener listener) {
    listeners.add(listener);
}

public void removeListener(LocationListener listener) {
   listeners.remove(listener);
}

@Override
public void onLocationChanged(Location location) {
    mLastLocation = location;
    for (LocationListener listener : listeners) {
        listener.onLocationChanged(location);
    }
}

User of GPSTracker

GPSTracker gps = new GPSTracker();

LocationListener myCallback = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        // This code runs every time your gps gets a new location
        System.out.println("lat-->"+location.getLatitude()+" long===>"+location.getLongitude());
        doStuffWithLocation(location);
    }
};
gps.registerListener(myCallback);

// Then when you are finished
gps.removeListener(myCallback);
Breavyn
  • 2,232
  • 16
  • 29
0

I find class GooglePlayServicesHelper

after use code below in Activity

    geoGPS = new GooglePlayServicesHelper(mContext, true);
    mLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            Logger.debug("lat: " + latitude);
            Logger.debug("long: " + longitude);
        }
    };
Do Xuan Nguyen
  • 189
  • 4
  • 8