15

So I have implemented the new Fused Location Provider API to get a location of the user but for some reason, I cannot get any location unless the GPS is on. Not always, will users have their GPS on and I would like to not have to ask them to turn their GPS on every time the load the app. How can I tell the API to give me a location with whatever provider it has available?

Here is my code:

public class FusedLocationService implements
        LocationListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    public interface OnLocationChangedListener {
        public void OnLocationChanged(Location location);
    }

    private final String TAG = "SE8611";
    private boolean mRequestingLocationUpdates = true;

    private OnLocationChangedListener mCallBack;

    Service locationService;
    private LocationRequest locationRequest;
    private GoogleApiClient googleApiClient;
    private Location mCurrentLocation;
    private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;

    public FusedLocationService(Service locationService, final long INTERVAL, final long FASTEST_INTERVAL) {
        Logger.log(TAG, "FusedLocationService called");

        this.mCallBack = (OnLocationChangedListener)locationService;

        locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(INTERVAL);
        locationRequest.setFastestInterval(FASTEST_INTERVAL);
        this.locationService = locationService;

        googleApiClient = new GoogleApiClient.Builder(locationService)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        if (googleApiClient != null) {
            googleApiClient.connect();
        }
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        if(mRequestingLocationUpdates) {
            startLocationUpdates();
        }else{
            Logger.log(TAG, "Location updates are already running.");
        }
    }

    protected void startLocationUpdates() {
        this.fusedLocationProviderApi.requestLocationUpdates(
                googleApiClient, locationRequest, this);
        this.mRequestingLocationUpdates = false;
    }

    @Override
    public void onLocationChanged(Location mCurrentLocation) {
        Logger.log(TAG, "onLocationChanged called");
        this.mCurrentLocation = mCurrentLocation;
        this.mCallBack.OnLocationChanged(this.mCurrentLocation);
    }

    public void startLocationUpdatesAfterResume(){
        if (googleApiClient.isConnected() && !mRequestingLocationUpdates) {
            Logger.log(TAG, "startLocationUpdatesAfterResume called");
            this.startLocationUpdates();
        }
    }

    public void stopLocationUpdates() {
        Logger.log(TAG, "stopping Location Updates");
        LocationServices.FusedLocationApi.removeLocationUpdates(
                googleApiClient, this);
    }

    public Location getLocation() {
        return this.mCurrentLocation;
    }

    @Override
    public void onConnectionSuspended(int i) {
        this.mRequestingLocationUpdates = true;
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        this.mRequestingLocationUpdates = true;
    }
}
Georgi Angelov
  • 4,338
  • 12
  • 67
  • 96

3 Answers3

11

I had the same issue like you, which is not an issue at all. Android used to have a GPS button that let you control it directly, but they replaced it with a Location button which works different. In order to get any type of location, you must turn it on. Like you, I thought the Location button turns on and off the GPS only, but that's not the case. You can control the GPS by changing the location mode: 1. High accuracy (GPS, Wi-Fi and mobile networks) 2. Power Saving (Wi-Fi and mobile networks) 3. GPS only

Liav
  • 111
  • 1
  • 3
3

I think I have found the solution of the problem.

If you go to Settings -> Privacy and Safety -> Location, you would notice that Location is not only GPS, but it actually lets user decide which providers can be used. For example, you can set that only WiFi and Cellular should be used to obtain any locations

Disabling Location option will disable all providers at once, not only GPS.

To test that app for users with only WiFi can get a location – change setting to "Wifi+Cellular".

AAverin
  • 3,014
  • 3
  • 27
  • 32
0

you seem to be using LocationRequest.PRIORITY_HIGH_ACCURACY, which prefers using GPS above and over other methods. You might want to use PRIORITY_BALANCED_POWER_ACCURACY, which will use WiFi and cell towers before using GPS.

Also, since PRIORITY_BALANCED_POWER_ACCURACY is a "coarse" level of accuracy, you might want to change the location permission in your manifest appropriately.

The training documentation details more information about the priority flags, you might also want to go through it.

Abhishek
  • 473
  • 3
  • 12
  • 1
    Well I definitely tried that. However, I am not getting any location when I use PRIORITY_BALANCED_POWER_ACCURACY. – Georgi Angelov Feb 19 '15 at 04:55
  • Are you testing on an emulator or a device? – Abhishek Feb 19 '15 at 05:29
  • I am testing on a device. To clarify, I do not get any location if I do not have GPS on. – Georgi Angelov Feb 19 '15 at 05:35
  • Weird, I ran some quick sample code on a Lenovo K900 and managed to get location fixes with GPS off using `PRIORITY_BALANCED_POWER_ACCURACY`. A stab in the dark, but did you opt in for Google apps to access device location? It's under Google settings > Location > Access Location. Also check if the device is allowed to use Wi-Fi/Mobile network to access location. You may get a dialog asking if Google may collect anonymous location data, depending on your device model. – Abhishek Feb 19 '15 at 06:15