4

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?

Community
  • 1
  • 1
Kamil Kłys
  • 1,907
  • 3
  • 18
  • 30

1 Answers1

10

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.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • 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: http://stackoverflow.com/questions/19365035/location-servise-gps-force-closed/19366773#19366773 – cYrixmorten Jul 26 '14 at 17:24
  • 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 Jul 26 '14 at 20:59
  • 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? – Kamil Kłys Jul 26 '14 at 22:24
  • 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 Jul 26 '14 at 22:35
  • 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. – Gabe Sechan Jul 26 '14 at 22:37
  • 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 – Kamil Kłys Jul 26 '14 at 22:39
  • 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. – Gabe Sechan Jul 26 '14 at 22:49
  • 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! – Kamil Kłys Jul 26 '14 at 23:04
  • 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. – Gabe Sechan Aug 11 '16 at 18:55
  • @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`? – user1871869 Sep 16 '16 at 02:47
  • 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 Sep 16 '16 at 02:55
  • 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. – Gabe Sechan Sep 16 '16 at 02:58
  • @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? – user1871869 Sep 16 '16 at 03:03
  • 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. – Gabe Sechan Sep 16 '16 at 03:06
  • @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? – user1871869 Sep 16 '16 at 03:18
  • 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. – Gabe Sechan Sep 16 '16 at 03:20
  • @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? – user1871869 Sep 16 '16 at 03:23
  • In the raw GPS code, the onLocationChange is called. In my code, its the LocationUpdateListener.onUpdate function. – Gabe Sechan Sep 16 '16 at 03:24
  • @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 Sep 16 '16 at 03:31
  • @GabeSechan Ah I see. After some debugging, I have found that it is actually automatically called. Thanks for your help! Seriously appreciate it. – user1871869 Sep 16 '16 at 03:46