0

I am creating an Android application to get my current GPS location. First it was working, but now it always returns null. It just shows the GPS icon in my phone's notification bar but the icon is not getting activated or highlighted. I tried many tricks but nothing have worked so far. Here is my code:

final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
    @SuppressLint("RestrictedApi")
    @Override
    public void onClick(View view) {

        fab.setVisibility(View.VISIBLE);

        GpsTracker gt = new GpsTracker(getApplicationContext());
        Location l = gt.getLocation();
        if(l != null) {

            double lat = l.getLatitude();
            double lon = l.getLongitude();
            Toast.makeText(getApplicationContext(),"GPS Lat = "+lat+"\n lon = "+lon,Toast.LENGTH_SHORT).show();
            Snackbar.make(view, "GPS Lat = "+lat+"\n lon = "+lon, Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
            } else {
                Snackbar.make(view, "GPS unable to Connect", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
                Toast.makeText(getApplicationContext(),"GPS unable to Connect",Toast.LENGTH_SHORT).show();
            }
        }
    });

GpsTracker.java

import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import static android.content.Context.LOCATION_SERVICE;

public class GpsTracker implements LocationListener {

    public Context context;

    public GpsTracker(Context context) {
        super();
        this.context = context;
    }

    public Location getLocation(){
        if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) {
            Log.e("fist","error");
            return null;
        }
        try {
            LocationManager lm = (LocationManager) context.getSystemService(LOCATION_SERVICE);
            boolean isGPSEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
            if (isGPSEnabled) {
                lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000,10,this);
                Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                return loc;
            } else {
                Log.e("sec","Please enable your GPS");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @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) {
    }
}   

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
TofferJ
  • 4,678
  • 1
  • 37
  • 49

2 Answers2

0

You are only accessing the last known location. This is often null or wildly inaccurate to your current location. You should wait until you get some successful readings from onLocationChanged before returning a value to the caller.

Maybe you should split out the code where you initialize the location manager into a method, startLocationTracking(). Then, in your code, call that when the Action/Fragment is first created. Once the location manager is getting onLocationChanged events, it would update a Public variable with the current location. Then, your getLocation() method would simply return that currentLocation variable to the caller. Then, you should probably have a stopLocationTracking() method that you call when the Action/Fragment closes.

Michael Dougan
  • 1,698
  • 1
  • 9
  • 13
0

Hassan,

Have you considered using the Google Services in retrieving one's location. I prefer using that. Below find an example, however you will need to

  • Step One

Set up the Google API key on the Google API console : https://console.developers.google.com/?pli=1

Choose the Maps SDK for Android and Enable it, then generate the API Key therein.

Google Developer Console

  • Step Two

Copy and paste the API key on your strings.xml file in your Project

strings.xml file in your project

  • Step Three

Add the following dependency in your app.gradle file

implementation 'com.google.android.gms:play-services-maps:16.1.0'
  • Step Four

Add the following in your AndroidManifest.xml , after the application tag

<meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
<meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_maps_key" />

<meta-data
        android:name="com.google.android.maps.v2.API_KEY"
        android:value="@string/google_maps_key" />
  • Step Five

Implement the following Classes

public class MainActivity extends AppCompatActivity
        implements  OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener, LocationListener {

/*Declare the following Variables */
    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
    private boolean mRequestingLocationUpdates = false;
    private static int UPDATE_INTERVAL = 10000; // 10 sec
    private static int FATEST_INTERVAL = 5000; // 5 sec
    private static int DISPLACEMENT = 10; // 10 meters
    public GoogleApiClient mGoogleApiClient;
    LocationRequest mLocationRequest;
    Location mLastLocation;
    public static double lat = 0, lng = 0;
    LocationManager locationManager;
    Location location = null;
  • Step Six

Create the following functions outside the OnCreate Function

protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
        createLocationRequest();
    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FATEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(DISPLACEMENT);

    }

    @SuppressLint("MissingPermission")
    protected void startLocationUpdates() {
        try {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (LocationListener) this);
        } catch (Exception e) {
            Log.d("LOCATION_MSG", e.getMessage());
        }
    }

    protected void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, (LocationListener) this);
    }
  • Step Seven

Call the buildGoogleApiClient() in your onCreate

  • Step Eight

Override the methods

 @Override
    public void onConnected(@Nullable Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FATEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
    }

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

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

    }

    @SuppressLint("MissingPermission")
    @Override
    public void onLocationChanged(Location location) {
        mLastLocation = location;
        mLastLocation = LocationServices.FusedLocationApi
                .getLastLocation(mGoogleApiClient);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

    }
  • Step Nine

In your OnClick Listener :

fab.setOnClickListener

Add this

    mLastLocation = LocationServices.FusedLocationApi
            .getLastLocation(mGoogleApiClient);
    startLocationUpdates();

                    if (mLastLocation != null)

    {

        try {
            lat = mLastLocation.getLatitude();
            lng = mLastLocation.getLongitude();
        } catch (Exception e) {
            lat = 0;
            lng = 0;
        }
      /* Check your log cat for the following */
 Log.d("LOC_Latitude" , Double.toString(lat));
       Log.d("LOC_Longitude" , Double.toString(lng));


    }else{

    //Something is a miss, maybe the location service on your phone is not on, it could even be the internet connection.               
    }
  • Things to Note Ensure you have all the prerequisite permissions on your manifest , some devices would require permissions to be requested on run time. You can use the following to do that

    /*Declare this method outside our onCreate Function */

        public static boolean hasPermissions(Context context, String... permissions) {
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
                for (String permission : permissions) {
                    if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                        return false;
                    }
                }
            }
            return true;
        }
    
    /*Add this in your onCreate Function */  
    
    
    
    String[] PERMISSIONS = {Manifest.permission.INTERNET, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
    
        if (!hasPermissions(this, PERMISSIONS)) {
            ActivityCompat.requestPermissions(this, PERMISSIONS, 1);
        }
    

Also make sure you have the following permissions on your AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

Try that and revert in any case you are still stuck.

Osoro
  • 312
  • 2
  • 8