[android] initialize LocationLayerPlugin with Map

This commit is contained in:
Łukasz Paczos
2018-09-03 15:48:32 +02:00
committed by Łukasz Paczos
parent 5d000d090f
commit cb771f6aca
3 changed files with 173 additions and 145 deletions

View File

@@ -44,6 +44,7 @@ import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
import com.mapbox.mapboxsdk.offline.OfflineGeometryRegionDefinition;
import com.mapbox.mapboxsdk.offline.OfflineRegionDefinition;
import com.mapbox.mapboxsdk.offline.OfflineTilePyramidRegionDefinition;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
@@ -178,9 +179,9 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(),
cameraChangeDispatcher);
// MapboxMap
mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, proj, registerTouchListener,
annotationManager, cameraChangeDispatcher);
mapCallback.attachMapboxMap(mapboxMap);
// user input
@@ -194,8 +195,13 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
mapGestureDetector, cameraChangeDispatcher, getWidth(), getHeight());
mapZoomButtonController.bind(uiSettings, zoomListener);
// compass
compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher));
compassView.setOnClickListener(createCompassClickListener(cameraChangeDispatcher));
// LocationLayerPlugin
mapboxMap.injectLocationLayerPlugin(new LocationLayerPlugin(context, mapboxMap));
// inject widgets with MapboxMap
attrView.setOnClickListener(new AttributionClickListener(context, mapboxMap));
@@ -1214,11 +1220,16 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
@Override
public void onMapChanged(@MapChange int change) {
if (change == DID_FINISH_LOADING_STYLE && initialLoad) {
initialLoad = false;
mapboxMap.onPreMapReady();
onMapReady();
mapboxMap.onPostMapReady();
if (change == WILL_START_LOADING_MAP) {
mapboxMap.onStartLoadingMap();
} else if (change == DID_FINISH_LOADING_STYLE) {
if (initialLoad) {
initialLoad = false;
mapboxMap.onPreMapReady();
onMapReady();
mapboxMap.onPostMapReady();
}
mapboxMap.onFinishLoadingStyle();
} else if (change == DID_FINISH_RENDERING_FRAME || change == DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) {
mapboxMap.onUpdateFullyRendered();
} else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {

View File

@@ -43,6 +43,7 @@ import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.light.Light;
@@ -75,6 +76,7 @@ public final class MapboxMap {
private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener;
private LocationLayerPlugin locationLayerPlugin;
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
MapboxMap(NativeMapView map, Transform transform, UiSettings ui, Projection projection,
@@ -110,12 +112,14 @@ public final class MapboxMap {
// if user hasn't loaded a Style yet
nativeMapView.setStyleUrl(Style.MAPBOX_STREETS);
}
locationLayerPlugin.onStart();
}
/**
* Called when the hosting Activity/Fragment onStop() method is called.
*/
void onStop() {
locationLayerPlugin.onStop();
}
/**
@@ -174,6 +178,20 @@ public final class MapboxMap {
invalidateCameraPosition();
}
/**
* Called when the map will start loading style.
*/
void onStartLoadingMap() {
locationLayerPlugin.onStartLoadingMap();
}
/**
* Called the map finished loading style.
*/
void onFinishLoadingStyle() {
locationLayerPlugin.onFinishLoadingStyle();
}
/**
* Called when the region is changing or has changed.
*/
@@ -2283,6 +2301,23 @@ public final class MapboxMap {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter);
}
//
// LocationLayerPlugin
//
void injectLocationLayerPlugin(LocationLayerPlugin locationLayerPlugin) {
this.locationLayerPlugin = locationLayerPlugin;
}
/**
* Returns an object that can be used to display user's location on the Map.
* @return the location layer
*/
@NonNull
public LocationLayerPlugin getLocationLayerPlugin() {
return locationLayerPlugin;
}
//
// Interfaces
//

View File

@@ -1,9 +1,6 @@
package com.mapbox.mapboxsdk.plugins.locationlayer;
import android.annotation.SuppressLint;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.content.Context;
import android.hardware.SensorManager;
import android.location.Location;
@@ -22,8 +19,7 @@ import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdate;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapView.OnMapChangedListener;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraIdleListener;
import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveListener;
@@ -33,8 +29,6 @@ import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import java.util.concurrent.CopyOnWriteArrayList;
import timber.log.Timber;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.DEFAULT_TRACKING_TILT_ANIMATION_DURATION;
@@ -66,10 +60,10 @@ import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.
* {@link LocationLayerOptions#MAX_ZOOM_DEFAULT} and {@link LocationLayerOptions#MIN_ZOOM_DEFAULT} respectively.
* You can adjust the zoom range with {@link LocationLayerOptions#maxZoom()} and {@link LocationLayerOptions#minZoom()}.
*/
public final class LocationLayerPlugin implements LifecycleObserver {
public final class LocationLayerPlugin {
private static final String TAG = "Mbgl-LocationLayerPlugin";
private final MapboxMap mapboxMap;
private final MapView mapView;
private LocationLayerOptions options;
private LocationEngine locationEngine;
private CompassEngine compassEngine;
@@ -101,7 +95,7 @@ public final class LocationLayerPlugin implements LifecycleObserver {
* Initialized in a started state because the plugin can be instantiated after lifecycle's onStart() and
* the developer might not register the lifecycle observer but call lifecycle methods manually instead.
*/
private boolean isPluginStarted = true;
private boolean isPluginStarted;
/**
* Indicates if Mapbox components are ready to be interacted with. This can differ from {@link #isPluginStarted}
@@ -121,102 +115,13 @@ public final class LocationLayerPlugin implements LifecycleObserver {
/**
* Construct a LocationLayerPlugin
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
* </p>
*
* @param mapView the MapView to apply the LocationLayerPlugin to
* @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with
*/
public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap) {
public LocationLayerPlugin(@NonNull Context context, @NonNull MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
this.mapView = mapView;
options = LocationLayerOptions.createFromAttributes(mapView.getContext(), R.style.mapbox_LocationLayer);
initializeLocationEngine();
initialize();
}
/**
* Construct a LocationLayerPlugin
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
* </p>
*
* @param mapView the MapView to apply the LocationLayerPlugin to
* @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with
* @param options to customize the user location icons inside your apps
*/
public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap,
@NonNull LocationLayerOptions options) {
this.mapboxMap = mapboxMap;
this.mapView = mapView;
this.options = options;
initializeLocationEngine();
initialize();
}
/**
* Construct a LocationLayerPlugin
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
* </p>
*
* @param mapView the MapView to apply the LocationLayerPlugin to
* @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with
*/
public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap,
@StyleRes int styleRes) {
this.mapboxMap = mapboxMap;
this.mapView = mapView;
this.options = LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes);
initializeLocationEngine();
initialize();
}
/**
* Construct a LocationLayerPlugin
*
* @param mapView the MapView to apply the LocationLayerPlugin to
* @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with
* @param locationEngine the {@link LocationEngine} this plugin should use to update
*/
public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap,
@Nullable LocationEngine locationEngine) {
this(mapView, mapboxMap, locationEngine,
LocationLayerOptions.createFromAttributes(mapView.getContext(),
R.style.mapbox_LocationLayer));
}
/**
* Construct a LocationLayerPlugin
*
* @param mapView the MapView to apply the LocationLayerPlugin to
* @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with
* @param locationEngine the {@link LocationEngine} this plugin should use to update
* @param styleRes customize the user location icons inside your apps {@code style.xml}
*/
public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap,
@Nullable LocationEngine locationEngine, @StyleRes int styleRes) {
this(mapView, mapboxMap, locationEngine,
LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes));
}
/**
* Construct a LocationLayerPlugin
*
* @param mapView the MapView to apply the LocationLayerPlugin to
* @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with
* @param locationEngine the {@link LocationEngine} this plugin should use to update
* @param options to customize the user location icons inside your apps
*/
public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap,
@Nullable LocationEngine locationEngine,
@NonNull LocationLayerOptions options) {
this.locationEngine = locationEngine;
this.mapboxMap = mapboxMap;
this.mapView = mapView;
this.options = options;
initialize();
options = LocationLayerOptions.createFromAttributes(context, R.style.mapbox_LocationLayer);
initialize(context);
}
/**
@@ -225,7 +130,7 @@ public final class LocationLayerPlugin implements LifecycleObserver {
*
* @param isEnabled true to show layers and enable camera, false otherwise
*/
public void setLocationLayerEnabled(boolean isEnabled) {
private void setLocationLayerEnabled(boolean isEnabled) {
if (isEnabled) {
enableLocationLayerPlugin();
} else {
@@ -233,6 +138,86 @@ public final class LocationLayerPlugin implements LifecycleObserver {
}
}
/**
* This method will show the location icon and enable the camera tracking the location.
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
*
* @param context the context
*/
@RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
public void activateLocationLayerPlugin(@NonNull Context context) {
activateLocationLayerPlugin(context, LocationLayerOptions.createFromAttributes(context, R.style
.mapbox_LocationLayer));
}
/**
* This method will show the location icon and enable the camera tracking the location.
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
*
* @param context the context
* @param styleRes the LocationLayerPlugin style res
*/
@RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
public void activateLocationLayerPlugin(@NonNull Context context, @StyleRes int styleRes) {
activateLocationLayerPlugin(context, LocationLayerOptions.createFromAttributes(context, styleRes));
}
/**
* This method will show the location icon and enable the camera tracking the location.
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
* </p>
*
* @param context the context
* @param options the options
*/
@RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
public void activateLocationLayerPlugin(@NonNull Context context, @NonNull LocationLayerOptions options) {
applyStyle(options);
initializeLocationEngine(context);
setLocationLayerEnabled(true);
}
/**
* This method will show the location icon and enable the camera tracking the location.
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
* </p>
*
* @param context the context
* @param locationEngine the engine, or null if you'd like to only force location updates
* @param styleRes the LocationLayerPlugin style res
*/
public void activateLocationLayerPlugin(@NonNull Context context, @Nullable LocationEngine locationEngine,
@StyleRes int styleRes) {
activateLocationLayerPlugin(locationEngine, LocationLayerOptions.createFromAttributes(context, styleRes));
}
/**
* This method will show the location icon and enable the camera tracking the location.
* <p>
* <strong>Note</strong>: This constructor will initialize and use an internal {@link LocationEngine}.
* </p>
*
* @param locationEngine the engine, or null if you'd like to only force location updates
* @param options the options
*/
public void activateLocationLayerPlugin(@Nullable LocationEngine locationEngine,
@NonNull LocationLayerOptions options) {
setLocationEngine(locationEngine);
applyStyle(options);
setLocationLayerEnabled(true);
}
/**
* This method will hide the location icon and disable the camera tracking the location.
*/
public void deactivateLocationLayerPlugin() {
setLocationLayerEnabled(false);
}
/**
* Returns whether the plugin is enabled, meaning that location can be displayed and camera modes can be used.
*
@@ -315,8 +300,8 @@ public final class LocationLayerPlugin implements LifecycleObserver {
*
* @param styleRes a XML style overriding some or all the options
*/
public void applyStyle(@StyleRes int styleRes) {
applyStyle(LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes));
public void applyStyle(@NonNull Context context, @StyleRes int styleRes) {
applyStyle(LocationLayerOptions.createFromAttributes(context, styleRes));
}
/**
@@ -350,9 +335,9 @@ public final class LocationLayerPlugin implements LifecycleObserver {
if (!isLocationLayerStarted) {
return;
} else if (getCameraMode() == CameraMode.NONE) {
Timber.e("%s%s",
Logger.e(TAG, String.format("%s%s",
"LocationLayerPlugin#zoomWhileTracking method can only be used",
" when a camera mode other than CameraMode#NONE is engaged.");
" when a camera mode other than CameraMode#NONE is engaged."));
return;
}
pluginAnimatorCoordinator.feedNewZoomLevel(zoomLevel, mapboxMap.getCameraPosition(), animationDuration, callback);
@@ -408,9 +393,9 @@ public final class LocationLayerPlugin implements LifecycleObserver {
if (!isLocationLayerStarted) {
return;
} else if (getCameraMode() == CameraMode.NONE) {
Timber.e("%s%s",
Logger.e(TAG, String.format("%s%s",
"LocationLayerPlugin#tiltWhileTracking method can only be used",
" when a camera mode other than CameraMode#NONE is engaged.");
" when a camera mode other than CameraMode#NONE is engaged."));
return;
}
pluginAnimatorCoordinator.feedNewTilt(tilt, mapboxMap.getCameraPosition(), animationDuration, callback);
@@ -645,28 +630,43 @@ public final class LocationLayerPlugin implements LifecycleObserver {
}
/**
* You must call this method from the parent's Activity#onStart() or Fragment#onStart()
* Internal use.
*/
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
if (mapView.isDestroyed()) {
Timber.e("You are calling plugins #onStart after the map was destroyed. Re-create the plugin before using it.");
// TODO: 03.09.18 LLP when map destroyed
/*if (context.isDestroyed()) {
Logger.e("You are calling plugins #onStart after the map was destroyed. Re-create the plugin before using it.");
return;
}
}*/
isPluginStarted = true;
onLocationLayerStart();
}
/**
* You must call this method from the parent's Activity#onStop() or Fragment#onStop().
* Internal use.
*/
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
onLocationLayerStop();
isPluginStarted = false;
}
/**
* Internal use.
*/
public void onStartLoadingMap() {
onLocationLayerStop();
}
/**
* Internal use.
*/
public void onFinishLoadingStyle() {
locationLayer.initializeComponents(options);
locationLayerCamera.initializeOptions(options);
onLocationLayerStart();
}
@SuppressLint("MissingPermission")
private void onLocationLayerStart() {
if (!isPluginStarted) {
@@ -720,25 +720,22 @@ public final class LocationLayerPlugin implements LifecycleObserver {
}
}
private void initialize() {
private void initialize(@NonNull Context context) {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
mapView.addOnMapChangedListener(onMapChangedListener);
mapboxMap.addOnMapClickListener(onMapClickListener);
mapboxMap.addOnMapLongClickListener(onMapLongClickListener);
LayerSourceProvider sourceProvider = new LayerSourceProvider();
LayerFeatureProvider featureProvider = new LayerFeatureProvider();
LayerBitmapProvider bitmapProvider = new LayerBitmapProvider(mapView.getContext());
LayerBitmapProvider bitmapProvider = new LayerBitmapProvider(context);
locationLayer = new LocationLayer(mapboxMap, sourceProvider, featureProvider, bitmapProvider, options);
locationLayerCamera = new LocationLayerCamera(
mapView.getContext(), mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener);
context, mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener);
pluginAnimatorCoordinator = new PluginAnimatorCoordinator();
pluginAnimatorCoordinator.addLayerListener(locationLayer);
pluginAnimatorCoordinator.addCameraListener(locationLayerCamera);
Context context = mapView.getContext();
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
compassEngine = new LocationLayerCompassEngine(windowManager, sensorManager);
@@ -747,14 +744,13 @@ public final class LocationLayerPlugin implements LifecycleObserver {
updateMapWithOptions(options);
enableLocationLayerPlugin();
setRenderMode(RenderMode.NORMAL);
setCameraMode(CameraMode.NONE);
}
private void initializeLocationEngine() {
private void initializeLocationEngine(@NonNull Context context) {
usingInternalLocationEngine = true;
locationEngine = new LocationEngineProvider(mapView.getContext()).obtainBestLocationEngineAvailable();
locationEngine = new LocationEngineProvider(context).obtainBestLocationEngineAvailable();
locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
locationEngine.setFastestInterval(1000);
locationEngine.addLocationEngineListener(locationEngineListener);
@@ -898,20 +894,6 @@ public final class LocationLayerPlugin implements LifecycleObserver {
}
};
private OnMapChangedListener onMapChangedListener = new OnMapChangedListener() {
@SuppressLint("MissingPermission")
@Override
public void onMapChanged(int change) {
if (change == MapView.WILL_START_LOADING_MAP) {
onLocationLayerStop();
} else if (change == MapView.DID_FINISH_LOADING_STYLE) {
locationLayer.initializeComponents(options);
locationLayerCamera.initializeOptions(options);
onLocationLayerStart();
}
}
};
private OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = new OnCameraMoveInvalidateListener() {
@Override
public void onInvalidateCameraMove() {