5

In my android app, I need to gt the user location when he clicks a button. I do not need to receive continuous updates on his location however.

I searched through a few questions on stackoverflow, but the answers are 2-3 years old, so I was wondering, as on the Android SDK now, what is the best way to do it.

Also, I would like not to get null in the location if possible.

Thanks in advance.

Ayush Gupta
  • 8,716
  • 8
  • 59
  • 92

3 Answers3

15

UPDATE September 23, 2020

Change log of version 17.1.0 mentions a new way to get current location:

FusedLocationProviderClient.getCurrentLocation()

A single fresh location will be returned if the device location can be determined within reasonable time (tens of seconds), otherwise null will be returned. This method may return locations that are a few seconds old, but never returns much older locations. This is suitable for foreground applications that need a single fresh current location.

Documentation: https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient#getCurrentLocation(int,%20com.google.android.gms.tasks.CancellationToken)

Example of usage:

val cancellationTokenSource = CancellationTokenSource()
fusedLocationProviderClient.getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, cancellationTokenSource.token)

// onStop or whenever you want to cancel the request
cancellationTokenSource.cancel()

Old Answer

You can use setNumUpdates method and pass the value 1. example:

mLocationRequest = new LocationRequest();
mLocationRequest.setNumUpdates(1);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

By default locations are continuously updated until the request is explicitly removed, however you can optionally request a set number of updates. For example, if your application only needs a single fresh location, then call this method with a value of 1 before passing the request to the location client.

https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html#setNumUpdates(int)

Ahmad Melegy
  • 1,530
  • 1
  • 16
  • 18
  • From documentation: "When using this option care must be taken to either explicitly remove the request when no longer needed or to set an expiration with (setExpirationDuration(long) or setExpirationTime(long). Otherwise in some cases if a location can't be computed, this request could stay active indefinitely consuming power." – Wojciech Kulik Nov 02 '20 at 09:56
  • 1
    Hello, I found that if you set "setNumUpdates(1)" it won't get the position, you must set it to at least 2. I'm using: " LocationServices.getFusedLocationProviderClient(mActivity).requestLocationUpdates(mLocationRequest, mLocationCallback, null); " .............Not "getCurrentLocation". – Z3R0 Feb 19 '21 at 08:49
  • @Z3R0 I believe that's not true.. it might be a bug in your code. I have been using `setNumUpdates(1)` for a long time and it's working fine. – Ahmad Melegy Feb 19 '21 at 19:53
  • 1
    @AhmadEl-Melegy I was using too, but now it isn't working anymore. Idk if because I have updated the target sdk or the library, but if I remove "setNumUpdates" or I set it to > 1 the code works. – Z3R0 Mar 18 '21 at 13:29
  • I confirm the "you must set it to at least 2" case. – porlicus Apr 04 '21 at 15:52
  • Looks like some behaviour change/bug introduced lately? Please try the update answer using `getCurrentLocation`. – Ahmad Melegy Apr 05 '21 at 06:14
2

Android introduce Fused Location in last I/O Summit, Fused location provide you more reliable and accurate location with the best available provider.

import android.location.Location;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {


    TextView txtOutputLat, txtOutputLon;
    Location mLastLocation;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    String lat, lon;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GoogleApiClient();
    }


    @Override
    public void onConnected(Bundle bundle) {


        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(100); // Update location every second

        //use if you want location update
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,              mLocationRequest, this);

        // here you get current location
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                                                                          mGoogleApiClient);
        if (mLastLocation != null) {
            lat = String.valueOf(mLastLocation.getLatitude());
            lon = String.valueOf(mLastLocation.getLongitude());

        }

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onLocationChanged(Location location) {
        lat = String.valueOf(location.getLatitude());
        lon = String.valueOf(location.getLongitude());

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        GoogleApiClient();
    }

    synchronized void GoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
        .addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this)
        .addApi(LocationServices.API)
        .build();


    }

    @Override
    protected void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mGoogleApiClient.disconnect();
    }


}
Rajat
  • 10,977
  • 3
  • 38
  • 55
Nishchal Sharma
  • 1,070
  • 9
  • 16
0
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  



if (mGoogleApiClient == null) {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
        .addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this)
        .addApi(LocationServices.API)
        .build();
}


       protected void onStart() {
    mGoogleApiClient.connect();
    super.onStart();
}

protected void onStop() {
    mGoogleApiClient.disconnect();
    super.onStop();
}



 public class MainActivity extends ActionBarActivity implements
    ConnectionCallbacks, OnConnectionFailedListener {

@Override
public void onConnected(Bundle connectionHint) {
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
            mGoogleApiClient);
    if (mLastLocation != null) {
        mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
        mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
    }
}
}

for further reference see here

Rushi Ayyappa
  • 2,708
  • 2
  • 16
  • 32