Skip to content
This repository has been archived by the owner on Oct 7, 2024. It is now read-only.

locationEngine needed? #248

Closed
langsmith opened this issue Mar 21, 2017 · 4 comments
Closed

locationEngine needed? #248

langsmith opened this issue Mar 21, 2017 · 4 comments
Milestone

Comments

@langsmith
Copy link
Contributor

langsmith commented Mar 21, 2017

@cammace advised that I open this ticket.

The question is what to do with the following two lines.

Previously, Cameron said: "If we are simply displaying the user location icon on the map through the SDK, I don't think there's a reason to create a locationEngine object and activate it. This should be take care of by the Maps sdk"

  // Get the location engine object for later use.
    locationEngine = LocationSource.getLocationEngine(this);
    locationEngine.activate();

Because those two lines were included in the demo app, they were also used in the user location example page as well.

If the lines are removed, then it affects camera movement and LocationEngineListener stuff in enableLocation()

Here's the code for the user location activity in the demo app:

package com.mapbox.mapboxandroiddemo.examples.location;

import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.LocationSource;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEngineListener;
import com.mapbox.services.android.telemetry.permissions.PermissionsListener;
import com.mapbox.services.android.telemetry.permissions.PermissionsManager;

import java.util.List;

public class BasicUserLocation extends AppCompatActivity implements PermissionsListener {

  private MapView mapView;
  private MapboxMap map;
  private FloatingActionButton floatingActionButton;
  private LocationEngine locationEngine;
  private LocationEngineListener locationEngineListener;
  private PermissionsManager permissionsManager;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Mapbox access token is configured here. This needs to be called either in your application
    // object or in the same activity which contains the mapview.
    Mapbox.getInstance(this, getString(R.string.access_token));

    // This contains the MapView in XML and needs to be called after the account manager
    setContentView(R.layout.activity_location_basic);

    // Get the location engine object for later use.
    locationEngine = LocationSource.getLocationEngine(this);
    locationEngine.activate();

    mapView = (MapView) findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);
    mapView.getMapAsync(new OnMapReadyCallback() {
      @Override
      public void onMapReady(MapboxMap mapboxMap) {
        map = mapboxMap;
      }
    });

    floatingActionButton = (FloatingActionButton) findViewById(R.id.location_toggle_fab);
    floatingActionButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        if (map != null) {
          toggleGps(!map.isMyLocationEnabled());
        }
      }
    });
  }

  @Override
  public void onResume() {
    super.onResume();
    mapView.onResume();
  }

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

  @Override
  protected void onStop() {
    super.onStop();
    mapView.onStop();
  }

  @Override
  public void onPause() {
    super.onPause();
    mapView.onPause();
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapView.onSaveInstanceState(outState);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
    // Ensure no memory leak occurs if we register the location listener but the call hasn't
    // been made yet.
    if (locationEngineListener != null) {
      locationEngine.removeLocationEngineListener(locationEngineListener);
    }
  }

  @Override
  public void onLowMemory() {
    super.onLowMemory();
    mapView.onLowMemory();
  }

  private void toggleGps(boolean enableGps) {
    if (enableGps) {
      // Check if user has granted location permission
      permissionsManager = new PermissionsManager(this);
      if (!PermissionsManager.areLocationPermissionsGranted(this)) {
        permissionsManager.requestLocationPermissions(this);
      } else {
        enableLocation(true);
      }
    } else {
      enableLocation(false);
    }
  }

  private void enableLocation(boolean enabled) {
    if (enabled) {
      // If we have the last location of the user, we can move the camera to that position.
      Location lastLocation = locationEngine.getLastLocation();
      if (lastLocation != null) {
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lastLocation), 16));
      }

      locationEngineListener = new LocationEngineListener() {
        @Override
        public void onConnected() {
          // No action needed here.
        }

        @Override
        public void onLocationChanged(Location location) {
          if (location != null) {
            // Move the map camera to where the user location is and then remove the
            // listener so the camera isn't constantly updating when the user location
            // changes. When the user disables and then enables the location again, this
            // listener is registered again and will adjust the camera once again.
            map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 16));
            locationEngine.removeLocationEngineListener(this);
          }
        }
      };
      locationEngine.addLocationEngineListener(locationEngineListener);
      floatingActionButton.setImageResource(R.drawable.ic_location_disabled_24dp);
    } else {
      floatingActionButton.setImageResource(R.drawable.ic_my_location_24dp);
    }
    // Enable or disable the location layer on the map
    map.setMyLocationEnabled(enabled);
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }

  @Override
  public void onExplanationNeeded(List<String> permissionsToExplain) {
    Toast.makeText(this, "This app needs location permissions in order to show its functionality.",
      Toast.LENGTH_LONG).show();
  }

  @Override
  public void onPermissionResult(boolean granted) {
    if (granted) {
      enableLocation(true);
    } else {
      Toast.makeText(this, "You didn't grant location permissions.",
        Toast.LENGTH_LONG).show();
      finish();
    }
  }
}
@langsmith langsmith changed the title what do do with locationEngine needed? locationEngine needed? Mar 21, 2017
@cammace
Copy link
Contributor

cammace commented Mar 22, 2017

cc: @tobrun

@zugaldia
Copy link
Member

Previously, Cameron said: "If we are simply displaying the user location icon on the map through the SDK, I don't think there's a reason to create a locationEngine object and activate it. This should be take care of by the Maps sdk"

That's correct, the Maps SDK takes care of setting up a default LocationEngine for you (called LocationSource for compatibility with the Google API). Once @Guardiola31337's mapbox/mapbox-gl-native#8710 lands you'll be able to set up your own though, if this is a requirement of this example.

@cammace
Copy link
Contributor

cammace commented Apr 13, 2017

I'd argue setting up a custom locationEngine instead of using LocationSource could make for a good example. I have found that some users get confused with the ordering in which the APIs need to be called. requestLocationUpdates adding listeners, activate etc.

@zugaldia
Copy link
Member

I'd argue setting up a custom locationEngine instead of using LocationSource could make for a good example.

👍 Let's ticket that separately and use the API introduced by mapbox/mapbox-gl-native#8710 (now merged).

Meanwhile, let's remove the redundant initialization from this example.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants