Search code examples
androidandroid-gps

How to fix 'GPS unable to get Location'?


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" />

Solution

  • 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.