Get Current Location From Best Available Provider - Stack Overflow

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

Android: get current location from best available provider - Stack Overflow http://stackoverflow.com/questions/2504429/android-get-current-location...

sign up

log in

tour

help

careers 2.0

Stack Overflow is a question and answer site for professional and enthusiast programmers. Its 100% free, no registration required.

Android: get current location from best available provider


I have some Android code that needs to get the best available location QUICKLY, from GPS, network or whatever is available. Accuracy is less important than speed. Getting the best available location is surely a really standard task. Yet I cant find any code to demonstrate it. The Android location code expects you to specify criteria, register for updates, and wait - which is fine if you have detailed criteria and dont mind waiting around. But my app needs to work a bit more like the Maps app does when it first locates you - work from any available provider, and just check the location isnt wildly out of date or null. Ive attempted to roll my own code to do this, but am having problems. (Its inside an IntentService where an upload happens, if that makes any difference. Ive included all the code for info.) Whats wrong with this code? @Override protected void onHandleIntent(Intent arg0) { testProviders(); doUpload(); } private boolean doUpload() { int j = 0; // check if we have accurate location data yet - wait up to 30 seconds while (j < 30) { if ((latString == "") || (lonString == "")) { Log.d(LOG_TAG, "latlng null"); Thread.sleep(1000); j++; } else { Log.d(LOG_TAG, "found lat " + latString + " and lon " + lonString); break; } //do the upload here anyway, with or without location data //[code removed for brevity] } public boolean testProviders() { Log.e(LOG_TAG, "testProviders"); String location_context = Context.LOCATION_SERVICE; locationmanager = (LocationManager) getSystemService(location_context); List<String> providers = locationmanager.getProviders(true); for (String provider : providers) { Log.e(LOG_TAG, "registering provider " + provider); listener = new LocationListener() { public void onLocationChanged(Location location) { // keep checking the location - until we have // what we need //if (!checkLoc(location)) { Log.e(LOG_TAG, "onLocationChanged"); locationDetermined = checkLoc(location); //} } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { }

1 of 4

2/18/2014 1:47 PM

Android: get current location from best available provider - Stack Overflow http://stackoverflow.com/questions/2504429/android-get-current-location...
}; locationmanager.requestLocationUpdates(provider, 0, 0, listener);

} private boolean checkLoc(Location location) { float tempAccuracy = location.getAccuracy(); int locAccuracy = (int) tempAccuracy; Log.d(LOG_TAG, "locAccuracy = " + locAccuracy); if ((locAccuracy != 0) && (locAccuracy < LOCATION_ACCURACY)) { latitude = location.getLatitude(); longitude = location.getLongitude(); latString = latitude.toString(); lonString = longitude.toString(); return true; } return false; } public void removeListeners() { // Log.e(LOG_TAG, "removeListeners"); if ((locationmanager != null) && (listener != null)) { locationmanager.removeUpdates(listener); } locationmanager = null; // Log.d(LOG_TAG, "Removed " + listener.toString()); } @Override public void onDestroy() { super.onDestroy(); removeListeners(); } Unfortunately, this finds the network provider, but only ever outputs latlng null 30 times - it never seems to get a location at all. I never even get a log statement of locationChanged . Its funny, because from ddms I can see output like: NetworkLocationProvider: onCellLocationChanged [305,8580] NetworkLocationProvider: getNetworkLocation(): returning cache location with accuracy 75.0 seeming to suggest that the network provider does have some location info after all, Im just not getting at it. Can anyone help? I think working example code would be a useful resource for the Android/StackOverflow community.
android

} Log.e(LOG_TAG, "getting updates"); return true;

asked Mar 23 10 at 23:39 AP257 7,366 22 104 168 Maybe my code sample can help stackoverflow.com/questions/3145089/ Fedor Jun 30 10 at 0:21

2 Answers
You are definitely trying to do this the hard way. Here are some snippets from a new app I am working on. It uses Criteria to get all providers capable of returning a fine level of accuracy without a cost. If no providers are enabled a dialog is displayed that prompts the user to turn on their location settings. If the user hits ok an Intent is actually fired that sends them to the settings on their phone. If there are providers enabled the app takes the most recent last known location from any of the enabled providers. For my app I just need to know what general area the user is in and its likely that the last known location is from their home area. If providers are enabled the loop also requests location updates as quickly as possible. This is ideal for my app but you can change this to conserve battery my modifying the arguments to the requestLocationUpdates method. The optimization that this code has that the examples on the Android app dont really show is that all of the enabled providers are started simultaneously. All of the providers will return separate updates on to the

2 of 4

2/18/2014 1:47 PM

Android: get current location from best available provider - Stack Overflow http://stackoverflow.com/questions/2504429/android-get-current-location...

onLocationChanged method. In my app I remove the location listener after one of the providers returns a location with a good enough accuracy. Start Location Updates: void getCurrentLocation() { List<String> providers = locationManager.getProviders(criteria, true); if (providers != null) { Location newestLocation = null; for (String provider : providers) { Location location = locationManager.getLastKnownLocation(provider); if (location != null) { if (newestLocation == null) { newestLocation = location; } else { if (location.getTime() > newestLocation.getTime()) { newestLocation = location; } } locationManager.requestLocationUpdates(provider, 0, 0, this); } } } else { LocationDialogFragment dialog = new LocationDialogFragment(); dialog.show(getSupportFragmentManager(), LocationDialogFragment .class.getName()); } } Receive Location Update: @Override public void onLocationChanged(Location location) { float bestAccuracy = -1f; if (location.getAccuracy() != 0.0f && (location.getAccuracy() < bestAccuracy) || bestAccuracy == -1f) { if (location.getAccuracy() < Const.MIN_ACCURACY) { locationManager.removeUpdates(this); } } bestAccuracy = location.getAccuracy(); } Location Settings Dialog: public class LocationDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.location_dialog_message) .setPositiveButton(R.string.location_dialog_positive_button, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent settingsIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(settingsIntent); }

}) .setNegativeButton(R.string.location_dialog_negative_button, new OnClickListener() {

}); return builder.create();

@Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(getActivity(), R.string.no_location_message, Toast.LENGTH_LONG) .show(); }

3 of 4

2/18/2014 1:47 PM

Android: get current location from best available provider - Stack Overflow http://stackoverflow.com/questions/2504429/android-get-current-location...
}
edited Jul 17 13 at 9:21 Mr_and_Mrs_D 3,564 4 18 59 answered Feb 15 13 at 20:27 jophde 105 1 7

Great solution! Just one thing to point out. It may be due to a change in the API, but the condition (providers != null) has to be (privders.size() > 0) because the getProviders(Criteria, boolean) method does never return null , instead it can return a list with size 0. luixal Sep 11 13 at 18:03

I think I remember that not being accurate when I was testing this but I guess we have to go by the documentation. Anyway, everyone should know that the FusedLocationProvider in the Google Play Services library is much superior to the old location classes. The implementation is much different though. This technique is a bit outdated. jophde Sep 13 13 at 14:10

Thread.sleep() in production code is a serious code smell IMHO. If you find youre having to do that, youre probably doing something thats not supposed to work that way. In this case, I think its the source of your problem -- youre not letting Android go back to process this threads message queue to dispatch any location updates it finds. I suspect an IntentService is just not going to work for your scenario.
answered Mar 23 10 at 23:53 CommonsWare 355k 23 672 748 Thanks. I guess Ill do it in a normal Activity and just pass the lat/lon to the IntentService. Id still really like an example of how to check all LocationProviders and pick the best location though - if anyone has any example code, please do post it... if not Ill attempt to hack something and post it here. AP257 Mar 24 10 at 11:05 @CommonsWare - how do you suggest I implement the following without using Thread.sleep()? "Keep checking for location updates for 30 seconds; if no up-to-date location found by then, give up and use dummy values." AP257 Mar 24 10 at 12:32 There is a million and one reasons why Thread.sleep can be used in production code (although I am not saying necessarily here). monkjack Apr 2 11 at 11:22

Not the answer you're looking for? Browse other questions tagged your own question.

android or ask

4 of 4

2/18/2014 1:47 PM

You might also like