Android: Get Current Location From Best Available Provider
Solution 1:
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 it's 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 don't really show is that all of the enabled providers are started simultaneously. All of the providers will return separate updates on to the 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:
voidgetCurrentLocation() {
List<String> providers = locationManager.getProviders(criteria, true);
if (providers != null) {
LocationnewestLocation=null;
for (String provider : providers) {
Locationlocation= 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 {
LocationDialogFragmentdialog=newLocationDialogFragment();
dialog.show(getSupportFragmentManager(),
LocationDialogFragment.class.getName());
}
}
Receive Location Update:
@OverridepublicvoidonLocationChanged(Location location) {
floatbestAccuracy= -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:
publicclassLocationDialogFragmentextendsDialogFragment {
@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builderbuilder=newAlertDialog.Builder(getActivity());
builder.setMessage(R.string.location_dialog_message)
.setPositiveButton(R.string.location_dialog_positive_button,
newOnClickListener() {
@OverridepublicvoidonClick(DialogInterface dialog, int which) {
IntentsettingsIntent=newIntent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(settingsIntent);
}
})
.setNegativeButton(R.string.location_dialog_negative_button,
newOnClickListener() {
@OverridepublicvoidonClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(),
R.string.no_location_message, Toast.LENGTH_LONG)
.show();
}
});
return builder.create();
}
}
Solution 2:
Thread.sleep()
in production code is a serious code smell IMHO. If you find you're having to do that, you're probably doing something that's not supposed to work that way. In this case, I think it's the source of your problem -- you're not letting Android go back to process this thread's message queue to dispatch any location updates it finds. I suspect an IntentService
is just not going to work for your scenario.
Post a Comment for "Android: Get Current Location From Best Available Provider"