Skip to content Skip to sidebar Skip to footer

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

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"