Search code examples
androidmultithreadinggeolocationandroid-looper

FusedLocationProviderClient when and how to stop Looper?


I used to use FusedLocationApi until I learned that it is deprecated (see references below). It was simple to implement. As the documentation says you need to use it in conjunction with GoogleApiClient

LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient,
                        locationRequest, this);

I recently changed to FusedLocationProviderClient (see reference below) Following a tutorial I was able to successfully get FusedLocationProviderClient working

Tutorial: https://github.com/codepath/android_guides/wiki/Retrieving-Location-with-LocationServices-API

// new Google API SDK v11 uses getFusedLocationProviderClient(this)
getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
      @Override
      public void onLocationResult(LocationResult locationResult) {
         // do work here
         onLocationChanged(locationResult.getLastLocation();
      }
    },
    Looper.myLooper());

The issue I am running into is the Looper thread. Even with the application in the background, the Looper thread continues to run. I would like to pause location updates when the application is in the background and then resume location updates when the application is in the foreground. How can I achieve this?

References:

  1. https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi
  2. https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient

Solution

  • You just need to call mFusedLocationClient.removeLocationUpdates(mLocationCallback) in onPause() of your Activity. However, there is a bit more to it than just that.

    Use member variables for the FusedLocationProviderClient and LocationRequest in your main activity:

    import com.google.android.gms.location.FusedLocationProviderClient;
    import com.google.android.gms.location.LocationCallback;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationResult;
    
    public class MainActivity extends AppCompatActivity
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener {
    
        FusedLocationProviderClient mFusedLocationClient;
        LocationRequest mLocationRequest;
    
        //..........
    

    Use a member variable for the LocationCallback as well:

    LocationCallback mLocationCallback = new LocationCallback(){
        @Override
        public void onLocationResult(LocationResult locationResult) {
            for (Location location : locationResult.getLocations()) {
                Log.i("MainActivity", "Location: " + location.getLatitude() + " " + location.getLongitude());
    
            }
        };
    
    };
    

    Then, assign mFusedLocationClient in onCreate() :

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        requestLocationUpdates();
    
        //...............
    }
    

    Then in onResume(), if theFusedLocationProviderClient is set up, then use it.

    @Override
    public void onResume() {
        if (mFusedLocationClient != null) {
            requestLocationUpdates();
        }
    }
    
    public void requestLocationUpdates() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(120000); // two minute interval
        mLocationRequest.setFastestInterval(120000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
        }
    }
    

    And finally, in onPause(), call removeLocationUpdates():

    @Override
    public void onPause() {
        super.onPause();
        if (mFusedLocationClient != null) {
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
        }
    }