Android LocationManager network provider returns null

14,945

Please do NOT use this code. It's bad. It has a lot of errors. Also, getLastKnownLocation will return null if it doesn't have a location yet. Which it always will if nobody on the phone is using requestUpdates.

Your code is taken from a class that was posted on a very old thread on here called GPSTracker. I've been trying to kill that code for months- it causes far more problems than it helps. If you want better example code, try http://gabesechansoftware.com/location-tracking/ which is a blog post I wrote about how bad that code is. It will show you the correct way to do it, and explains some of what's wrong with that code.

Share:
14,945
Kamil Kłys
Author by

Kamil Kłys

Java developer by choice, happy to develop and provide useful solutions for problems of all kinds.

Updated on June 05, 2022

Comments

  • Kamil Kłys
    Kamil Kłys almost 2 years

    I wanted to get my GPS coordinates using Android App. I started developing, and I can get GPS coordinates, but they are not accurate. I wanted to use NETWORK_PROVIDER, but the Location by this provider is always null. More interesting, isProvicerEnabled returns true.

    I used example from this thread (best answer) enter link description here

    private void _getLocation() {
        // Get the location manager
        try {
            boolean isGPSEnabled = false;
            boolean isNetworkEnabled = false;
            locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
            Location location = null;
            double latitude = -1;
            double longitude = -1;
    
            // 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 {
                if (isNetworkEnabled) {
                    showToast("network");
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            1000,
                            0, this);
                    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
                else if (isGPSEnabled) {
                    showToast("gps");
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                1000,
                                0, this);
                        Log.d("GPS", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }
            showToast("" + latitude + longitude);
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    

    I have all the permissions in manifest

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

    I know the code is dirty, but for now it's only for testing. Do I miss something? I found similar examples in many places, and it seems pretty straight, so I am a little confused. My phone works ok, GPS and network works fine. For example Google Maps application I have works well. Any suggestions?

  • cYrixmorten
    cYrixmorten almost 10 years
    I too have made some modifications to the GPSTracker: callbacks for new locations and for first-fix status of GPS. Just in case you find it interesting: stackoverflow.com/questions/19365035/…
  • Kamil Kłys
    Kamil Kłys almost 10 years
    It is strange, that this kind of implementation is used in so many examples. I will take a look at the examples that you provided. Thanks guys!
  • Kamil Kłys
    Kamil Kłys almost 10 years
    I used the example code from the first link (blog), and it doesn't work for me. I use start() method, then getLocation() when clicking on a button, but it always returns null (and hasLocation() returns false). On the other hand, getPossiblyStaleLocation() works fine. Looks like maybe requestLocationUpdates() isn't working for me. Any ideas?
  • Gabe Sechan
    Gabe Sechan almost 10 years
    If you're using GPS- are you inside? If so you probably aren't getting location lock. Do you see no GPS symbol, a flashing GPS symbol, or a solid GPS symbol in the notification bar? No symbol=problem, flashing= GPS is running but isn't locked, solid means locked and you should get a location.
  • Gabe Sechan
    Gabe Sechan almost 10 years
    A way to test it if you're having real issues is to download a mock location provider and add mock location permission to your app. This allows you to fake GPS data, so you can do controlled testing. It will actually look just like GPS data to the app.
  • Kamil Kłys
    Kamil Kłys almost 10 years
    You were right. I had to wait, until my GPS signal is stable. So it works with GPS :). But it still returns null for network
  • Gabe Sechan
    Gabe Sechan almost 10 years
    Interesting. Do you have wifi on? Do you have any bars? The code is actually identical for network, and I definitely tested it. So I'm wondering if you have enough network signal to use it.
  • Kamil Kłys
    Kamil Kłys almost 10 years
    Ok. Looks like I found the problem. The code was ok. I was experimenting with GPS whole day, and looks like it was a little bit too much for my phone. Restarted my device and now it works fine!
  • Gabe Sechan
    Gabe Sechan over 7 years
    You should probably look at the 2+ years old date on it. Maybe one of these days I'll go back and add 6.0 permissions checks on it. Otherwise its aged well.
  • user1871869
    user1871869 over 7 years
    @GabeSechan Something I don't get about your code is the fact that when you call the start() function in ProviderLocationTracker, lastLocation is set to null. As a result, if lets say the location settings are turned off while the user is in the app, they turn on the location settings. Then, when we check hasLocation(), the lastLocation is always null no matter what. Is there a way around this? Right when we call lm.requestLocationUpdates shouldn't we be updating the lastLocation instead of setting it to null?
  • Gabe Sechan
    Gabe Sechan over 7 years
    So lets say the user turns on location in settings. That doesn't immediately make the phone start tracking location- it just means that apps are allowed to request the location. It won't actually turn on the GPS radio (or even the network location tracking) until at least one app has called requestLocationUpdates. Calling getLastKnownLocation would still return null. So we set lastLocation to null because there is no location in the system.
  • Gabe Sechan
    Gabe Sechan over 7 years
    There is a small chance of it having a lastknowlocation if another app was also using GPS- but it almost never happens. Also, when using the FallbackLocationTracker you could have the choice between an older GPS datapoint from getLastKnownLocation and a newer network one. I prefer to fail to the newer network point until the gps updates, especially as we don't really know how old that GPS datapoint is.
  • user1871869
    user1871869 over 7 years
    @GabeSechan sorry, I am still a little confused. You say that when we turn on location services, apps are allowed to request the location. Then, if a user turns on location services and then immediately after the start() method is called, isn't requestLocationUpdates() function called? Wouldn't that request the location for me and thereby make the location "known"? Or is there some sort of delay that occurs when we turn on the location services and when our phone actually recieves it?
  • Gabe Sechan
    Gabe Sechan over 7 years
    You're allowed to request them. That doesn't mean one is available. Its like going up to the counter and asking for an order of fries, right after you let them turn on the fryer. They just turned it on, they haven't started cooking yet. Same thing here- the OS is now allowed to return locations, but to save battery it doesn't even turn on the GPS radio until someone requests updates. It then takes several seconds to several minutes to actually get satellite lock. Remember it has to actually read signals from space to provide GPS.
  • user1871869
    user1871869 over 7 years
    @GabeSechan Thanks. Lets say my location has been turned on my phone for a long time and suddenly I turn on the application. I notice that the fallbackLocationTracker.hasLocation() method always ends up being false even after I have called fallbackLocationTracker.start() before that method. Why is that so? If my phone has turned on location throughout the day and suddenly when I turn on the application, shouldn't I already "have" the location? Unless again it is the problem where it still takes time for location to read the signals?
  • Gabe Sechan
    Gabe Sechan over 7 years
    It still takes time. Network is fairly quick, but can take a few seconds (assuming you have a network connection and a cellular connection. Without those it won't be able to get any location ever). GPS is slower- 15s minimum, 1 minute not uncommon. If there's a problem such as being inside, it also may never get a location.
  • user1871869
    user1871869 over 7 years
    @GabeSechan ah I see. Thanks for explaining that. Is there some sort of callback or method we can use to figure out when we have the location after our request has finally gone through and can give actual location coordinates?
  • Gabe Sechan
    Gabe Sechan over 7 years
    In the raw GPS code, the onLocationChange is called. In my code, its the LocationUpdateListener.onUpdate function.
  • user1871869
    user1871869 over 7 years
    @GabeSechan Ah sorry if I am pestering you so much but wouldn't I need to constantly poll or have some sort of wait time until the location is actually recieved for listener.onUpdate to work properly so then I can load things related to location? I can't see how I can pass in a location Location newLoc if my phone does not fully receive the location.
  • user1871869
    user1871869 over 7 years
    @GabeSechan Ah I see. After some debugging, I have found that it is actually automatically called. Thanks for your help! Seriously appreciate it.