Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set LocationEngine properties in android #510

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import android.content.Context;
import android.graphics.Point;
import android.util.DisplayMetrics;
import android.util.Log;
import org.maplibre.android.location.engine.LocationEngineRequest;
import org.maplibre.geojson.Polygon;
import org.maplibre.android.camera.CameraPosition;
import org.maplibre.android.camera.CameraUpdate;
Expand Down Expand Up @@ -133,6 +135,17 @@ static LatLngBounds toLatLngBounds(Object o) {
return builder.build();
}

static LocationEngineRequest toLocationEngineRequest(Object o) {
if (o == null) {
return null;
}
List<?> data = toList(o);
return new LocationEngineRequest.Builder(toInt(data.get(0)))
.setPriority(toInt(data.get(1)))
.setDisplacement(toInt(data.get(2)))
.build();
}

static List<LatLng> toLatLngList(Object o, boolean flippedOrder) {
if (o == null) {
return null;
Expand Down Expand Up @@ -208,6 +221,12 @@ static String toString(Object o) {
static void interpretMapLibreMapOptions(Object o, MapLibreMapOptionsSink sink, Context context) {
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final Map<?, ?> data = toMap(o);

final Object locationEngineProperties = data.get("locationEngineProperties");
if (locationEngineProperties != null) {
final List<?> locationEnginePropertiesList = toList(locationEngineProperties);
sink.setLocationEngineProperties(toLocationEngineRequest(locationEnginePropertiesList));
}
final Object cameraTargetBounds = data.get("cameraTargetBounds");
if (cameraTargetBounds != null) {
final List<?> targetData = toList(cameraTargetBounds);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package org.maplibre.maplibregl;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import org.maplibre.android.location.engine.LocationEngineCallback;
import org.maplibre.android.location.engine.LocationEngineRequest;
import org.maplibre.android.location.engine.LocationEngineResult;
import org.maplibre.android.location.engine.LocationEngineImpl;


public class MapLibreGPSLocationEngine implements LocationEngineImpl<LocationListener> {
private static final String TAG = "GPSLocationEngine";
final LocationManager locationManager;

String currentProvider = LocationManager.PASSIVE_PROVIDER;

public MapLibreGPSLocationEngine(@NonNull Context context) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
}

@NonNull
@Override
public LocationListener createListener(LocationEngineCallback<LocationEngineResult> callback) {
return new AndroidLocationEngineCallbackTransport(callback);
}

@Override
public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback)
throws SecurityException {
Location lastLocation = getLastLocationFor(currentProvider);
if (lastLocation != null) {
callback.onSuccess(LocationEngineResult.create(lastLocation));
return;
}

for (String provider : locationManager.getAllProviders()) {
lastLocation = getLastLocationFor(provider);
if (lastLocation != null) {
callback.onSuccess(LocationEngineResult.create(lastLocation));
return;
}
}
callback.onFailure(new Exception("Last location unavailable"));
}

@SuppressLint("MissingPermission")
Location getLastLocationFor(String provider) throws SecurityException {
Location location = null;
try {
location = locationManager.getLastKnownLocation(provider);
} catch (IllegalArgumentException iae) {
Log.e(TAG, iae.toString());
}
return location;
}

@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull LocationListener listener,
@Nullable Looper looper) throws SecurityException {
currentProvider = getBestProvider(request.getPriority());
locationManager.requestLocationUpdates(currentProvider, request.getInterval(), request.getDisplacement(),
listener, looper);
}

@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull PendingIntent pendingIntent) throws SecurityException {
currentProvider = getBestProvider(request.getPriority());
locationManager.requestLocationUpdates(currentProvider, request.getInterval(),
request.getDisplacement(), pendingIntent);
}

@SuppressLint("MissingPermission")
@Override
public void removeLocationUpdates(@NonNull LocationListener listener) {
if (listener != null) {
locationManager.removeUpdates(listener);
}
}

@Override
public void removeLocationUpdates(PendingIntent pendingIntent) {
if (pendingIntent != null) {
locationManager.removeUpdates(pendingIntent);
}
}

private String getBestProvider(int priority) {
String provider = null;
if (priority != LocationEngineRequest.PRIORITY_NO_POWER) {
provider = LocationManager.GPS_PROVIDER;
}
return provider != null ? provider : LocationManager.PASSIVE_PROVIDER;
}


@VisibleForTesting
static final class AndroidLocationEngineCallbackTransport implements LocationListener {
private final LocationEngineCallback<LocationEngineResult> callback;

AndroidLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
this.callback = callback;
}

@Override
public void onLocationChanged(Location location) {
callback.onSuccess(LocationEngineResult.create(location));
}

@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
// noop
}

@Override
public void onProviderEnabled(String s) {
// noop
}

@Override
public void onProviderDisabled(String s) {
callback.onFailure(new Exception("Current provider disabled"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import androidx.annotation.NonNull;
import org.maplibre.android.camera.CameraPosition;
import org.maplibre.android.geometry.LatLngBounds;
import org.maplibre.android.location.engine.LocationEngineRequest;
import org.maplibre.android.maps.MapLibreMapOptions;
import io.flutter.plugin.common.BinaryMessenger;

Expand All @@ -23,6 +24,7 @@ class MapLibreMapBuilder implements MapLibreMapOptionsSink {
private int myLocationRenderMode = 0;
private String styleString = "";
private LatLngBounds bounds = null;
private LocationEngineRequest locationEngineRequest = null;

MapLibreMapController build(
int id,
Expand All @@ -43,6 +45,10 @@ MapLibreMapController build(
controller.setCameraTargetBounds(bounds);
}

if(null != locationEngineRequest ){
controller.setLocationEngineProperties(locationEngineRequest);
}

return controller;
}

Expand Down Expand Up @@ -206,4 +212,9 @@ public void setAttributionButtonMargins(int x, int y) {
public void setDragEnabled(boolean enabled) {
this.dragEnabled = enabled;
}

@Override
public void setLocationEngineProperties(@NonNull LocationEngineRequest locationEngineRequest) {
this.locationEngineRequest = locationEngineRequest;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
import com.google.gson.JsonParser;
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import org.maplibre.android.location.engine.LocationEngine;
import org.maplibre.android.location.engine.LocationEngineDefault;
import org.maplibre.android.location.engine.LocationEngineProxy;
import org.maplibre.android.location.engine.LocationEngineRequest;
import org.maplibre.geojson.Feature;
import org.maplibre.geojson.FeatureCollection;
import org.maplibre.android.camera.CameraPosition;
Expand Down Expand Up @@ -1861,6 +1865,20 @@ public void setCameraTargetBounds(LatLngBounds bounds) {
this.bounds = bounds;
}

@Override
public void setLocationEngineProperties(LocationEngineRequest locationEngineRequest){
if(locationComponent != null){
if(locationEngineRequest.getPriority() == LocationEngineRequest.PRIORITY_HIGH_ACCURACY){
locationComponent.setLocationEngine(new LocationEngineProxy(
new MapLibreGPSLocationEngine(context)));
} else {
locationComponent.setLocationEngine(
LocationEngineDefault.INSTANCE.getDefaultLocationEngine(context));
}
locationComponent.setLocationEngineRequest(locationEngineRequest);
}
}

@Override
public void setCompassEnabled(boolean compassEnabled) {
mapLibreMap.getUiSettings().setCompassEnabled(compassEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package org.maplibre.maplibregl

import org.maplibre.android.geometry.LatLngBounds
import org.maplibre.android.location.engine.LocationEngineRequest

/** Receiver of MapLibreMap configuration options. */
internal interface MapLibreMapOptionsSink {
Expand Down Expand Up @@ -42,4 +43,6 @@ internal interface MapLibreMapOptionsSink {
fun setAttributionButtonGravity(gravity: Int)

fun setAttributionButtonMargins(x: Int, y: Int)

fun setLocationEngineProperties(locationEngineRequest: LocationEngineRequest)
}
3 changes: 3 additions & 0 deletions maplibre_gl/lib/maplibre_gl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ export 'package:maplibre_gl_platform_interface/maplibre_gl_platform_interface.da
LatLngQuad,
Line,
LineOptions,
LocationEngineAndroidProperties,
LocationEnginePlatforms,
LocationPriority,
MapLibreMethodChannel,
MapLibrePlatform,
MinMaxZoomPreference,
Expand Down
49 changes: 29 additions & 20 deletions maplibre_gl/lib/src/maplibre_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class MapLibreMap extends StatefulWidget {
this.styleString = MapLibreStyles.demo,
this.onMapCreated,
this.onStyleLoadedCallback,
this.locationEnginePlatforms = LocationEnginePlatforms.defaultPlatform,
this.gestureRecognizers,
this.compassEnabled = true,
this.cameraTargetBounds = CameraTargetBounds.unbounded,
Expand Down Expand Up @@ -67,6 +68,10 @@ class MapLibreMap extends StatefulWidget {
assert(annotationOrder.length <= 4),
assert(annotationConsumeTapEvents.length > 0);

/// The properties for the platform-specific location engine.
/// Only has an impact if [myLocationEnabled] is set to true.
final LocationEnginePlatforms locationEnginePlatforms;

/// Defines the layer order of annotations displayed on map
///
/// Any annotation type can only be contained once, so 0 to 4 types
Expand Down Expand Up @@ -338,29 +343,30 @@ class _MapLibreMapState extends State<MapLibreMap> {
/// When used to change configuration, null values will be interpreted as
/// "do not change this configuration option".
class _MapLibreMapOptions {
_MapLibreMapOptions({
this.compassEnabled,
this.cameraTargetBounds,
this.styleString,
this.minMaxZoomPreference,
required this.rotateGesturesEnabled,
required this.scrollGesturesEnabled,
required this.tiltGesturesEnabled,
required this.zoomGesturesEnabled,
required this.doubleClickZoomEnabled,
this.trackCameraPosition,
this.myLocationEnabled,
this.myLocationTrackingMode,
this.myLocationRenderMode,
this.logoViewMargins,
this.compassViewPosition,
this.compassViewMargins,
this.attributionButtonPosition,
this.attributionButtonMargins,
});
_MapLibreMapOptions(
{this.compassEnabled,
this.cameraTargetBounds,
this.styleString,
this.minMaxZoomPreference,
required this.rotateGesturesEnabled,
required this.scrollGesturesEnabled,
required this.tiltGesturesEnabled,
required this.zoomGesturesEnabled,
required this.doubleClickZoomEnabled,
this.trackCameraPosition,
this.myLocationEnabled,
this.myLocationTrackingMode,
this.myLocationRenderMode,
this.logoViewMargins,
this.compassViewPosition,
this.compassViewMargins,
this.attributionButtonPosition,
this.attributionButtonMargins,
this.locationEnginePlatforms});

_MapLibreMapOptions.fromWidget(MapLibreMap map)
: this(
locationEnginePlatforms: map.locationEnginePlatforms,
compassEnabled: map.compassEnabled,
cameraTargetBounds: map.cameraTargetBounds,
styleString: map.styleString,
Expand Down Expand Up @@ -418,6 +424,8 @@ class _MapLibreMapOptions {

final Point? attributionButtonMargins;

final LocationEnginePlatforms? locationEnginePlatforms;

final _gestureGroup = {
'rotateGesturesEnabled',
'scrollGesturesEnabled',
Expand Down Expand Up @@ -464,6 +472,7 @@ class _MapLibreMapOptions {
addIfNonNull('attributionButtonPosition', attributionButtonPosition?.index);
addIfNonNull(
'attributionButtonMargins', pointToArray(attributionButtonMargins));
addIfNonNull('locationEngineProperties', locationEnginePlatforms?.toList());
return optionsMap;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
library maplibre_gl_platform_interface;

import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'dart:math';
import 'package:flutter/foundation.dart';
Expand All @@ -20,3 +21,4 @@ part 'src/fill.dart';
part 'src/ui.dart';
part 'src/maplibre_gl_platform_interface.dart';
part 'src/source_properties.dart';
part 'src/location_engine_properties.dart';
Loading