2

I'm using location services in an Android application I'm developing. After some research, I found out that getLastKnownLocation() is the fastest way of getting a user's recent location. I have no problem it being a little outdated as the module of my application doesn't require a user's current location. This solution is fine for me as I don't really need the exact location of a user at that given moment.

But, the evident problem with getLastKnownLocation is that it is bound to return null if the device doesn't have recent location stored or if you've recently rebooted the device.

My question is, what to do when getLastKnownLocation is null?

This is what I have come up yet:

LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
String bestProvider = lm.getBestProvider(criteria, false);
Location l = lm.getLastKnownLocation(bestProvider);
if(l != null) {
    Log.d("Lat", String.valueOf(l.getLatitude()));
    Log.d("Lng", String.valueOf(l.getLongitude()));
}
else {
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(), 
    PendingIntent.FLAG_UPDATE_CURRENT);
    lm.requestSingleUpdate(bestProvider, pi);
    Location ln = lm.getLastKnownLocation(lm.getBestProvider(criteria, false));
    // Still returns null
    Log.d("NewLat", String.valueOf(ln.getLatitude()));
    Log.d("NewLng", String.valueOf(ln.getLongitude()));
}

So, shouldn't the call to reqyestSingleUpdate store the latest location data? It doesn't seem to be working, though. Where am I going wrong? How'd you solve this problem?

Basit
  • 1,830
  • 2
  • 31
  • 50

2 Answers2

0

So insert his class int your app, and then in your activity use it like this

        mMyLocHelper = new MyLocationHelper();

        // An object with callback that will be called after location was found
        LocationResult locationResult = new LocationResult() {
            @Override
            public void gotLocation(Location location) {
                if (location != null) {
                    mUserLocation = location;

                    // Here my action after location is known (on UI thread!)
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {                 
                            myAction();
                        }
                    });
                }
                else {
                    // No location was found
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {                 
                            informUser();
                        }
                    });
                }
            }
        };

        // We state, that we can wait for 20 seconds for the location, and start the process
        if (mMyLocHelper.getLocation(this, locationResult, 20)) {
            mLocationEnabled = true;
        }
        else {
            mLocationEnabled = false;

            // Localization is turned off. Inform user
            informUser();
        }
  • anyway you can inform the user.

There is no guarantee, that you will get location.

Community
  • 1
  • 1
Yar
  • 4,543
  • 2
  • 35
  • 42
  • That answer is a little above my understanding level of Android. Would you mind simplifying it for me? I prefer using the code that I can understand. – Basit Oct 21 '14 at 10:12
  • Fedor provided a complete, working solution which you can insert into your app. I edited my answer. Actually, I slightly modified Fedor solution too. Anyway this is all I can try to help right now... – Yar Oct 21 '14 at 10:29
  • That's sounds doable. How about I just sleep the activity for a few seconds and retry? – Basit Oct 21 '14 at 10:49
  • Basically, the whole idea is to wait for location updates - requestLocationUpdates() function, and see if you get any. As I said, there is no guarantee, that you will obtain it. No need to sleep activity, or you can display a ProgressDialog. User can do whatever they need to, just after a time (you can set a Timer or sth) inform them that they have no location. If your app MUST have a location, then I suggest Fedor solution + my handler and then you can inform user and quit or something. – Yar Oct 21 '14 at 10:58
0

1) you cannot avoid having the "location yet unknown" state in your program. At some moment the location will be indeed unknown.

2) You getBestProvider(), but you can use the other provider for some time. There's no guarantee that the 2nd provider will work (there may be no SIM card in the phone).

3) You can store the last known location in the preferences, see Context.getSharedPreferences().

4) You can start "on the North Pole" (with North Pole's coordinates:-).

It is nevertheless possible that your application will never receive location data: it may be started in a building with too much metal for the GPS to work, and with no SIM card in the phone slot (if it is a phone rather than a tablet).

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • Storing the location as a shared preference sounds like a good idea. But wouldn't I have to create a location change listener and update the shared preferences whenever user's location is changed? Sounds like computationally expensive thing to do. – Basit Oct 21 '14 at 10:51
  • That's not computationally expensive, but remember that the activity gets abandoned and re-created each time you turn the screen and in some other cases. The listeners cannot be owned by the Activity, unless you unregister them _onPause()_. That is, you will need a _Model_ singleton (in _MVC_ = _Model-View-Controller_ sense) – 18446744073709551615 Oct 21 '14 at 12:07