Skip to content

Commit 93dde0d

Browse files
committed
Apply Pull Request maplibre#510 (Set LocationEngine properties in android)
See https://github.com/maplibre/flutter-maplibre-gl/pull/510/files for more details.
1 parent 8246a84 commit 93dde0d

File tree

9 files changed

+303
-0
lines changed

9 files changed

+303
-0
lines changed

Diff for: maplibre_gl/android/src/main/java/org/maplibre/maplibregl/Convert.java

+13
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import android.content.Context;
88
import android.graphics.Point;
99
import android.util.DisplayMetrics;
10+
import android.util.Log;
11+
import org.maplibre.android.location.engine.LocationEngineRequest;
1012
import org.maplibre.geojson.Polygon;
1113
import org.maplibre.android.camera.CameraPosition;
1214
import org.maplibre.android.camera.CameraUpdate;
@@ -133,6 +135,17 @@ static LatLngBounds toLatLngBounds(Object o) {
133135
return builder.build();
134136
}
135137

138+
static LocationEngineRequest toLocationEngineRequest(Object o) {
139+
if (o == null) {
140+
return null;
141+
}
142+
List<?> data = toList(o);
143+
return new LocationEngineRequest.Builder(toInt(data.get(0)))
144+
.setPriority(toInt(data.get(1)))
145+
.setDisplacement(toInt(data.get(2)))
146+
.build();
147+
}
148+
136149
static List<LatLng> toLatLngList(Object o, boolean flippedOrder) {
137150
if (o == null) {
138151
return null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package org.maplibre.maplibregl;
2+
3+
import android.annotation.SuppressLint;
4+
import android.app.PendingIntent;
5+
import android.content.Context;
6+
import android.location.Location;
7+
import android.location.LocationListener;
8+
import android.location.LocationManager;
9+
import android.os.Bundle;
10+
import android.os.Looper;
11+
import android.util.Log;
12+
13+
import androidx.annotation.NonNull;
14+
import androidx.annotation.Nullable;
15+
import androidx.annotation.VisibleForTesting;
16+
17+
import org.maplibre.android.location.engine.LocationEngineCallback;
18+
import org.maplibre.android.location.engine.LocationEngineRequest;
19+
import org.maplibre.android.location.engine.LocationEngineResult;
20+
import org.maplibre.android.location.engine.LocationEngineImpl;
21+
22+
23+
public class MapLibreGPSLocationEngine implements LocationEngineImpl<LocationListener> {
24+
private static final String TAG = "GPSLocationEngine";
25+
final LocationManager locationManager;
26+
27+
String currentProvider = LocationManager.PASSIVE_PROVIDER;
28+
29+
public MapLibreGPSLocationEngine(@NonNull Context context) {
30+
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
31+
}
32+
33+
@NonNull
34+
@Override
35+
public LocationListener createListener(LocationEngineCallback<LocationEngineResult> callback) {
36+
return new AndroidLocationEngineCallbackTransport(callback);
37+
}
38+
39+
@Override
40+
public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback)
41+
throws SecurityException {
42+
Location lastLocation = getLastLocationFor(currentProvider);
43+
if (lastLocation != null) {
44+
callback.onSuccess(LocationEngineResult.create(lastLocation));
45+
return;
46+
}
47+
48+
for (String provider : locationManager.getAllProviders()) {
49+
lastLocation = getLastLocationFor(provider);
50+
if (lastLocation != null) {
51+
callback.onSuccess(LocationEngineResult.create(lastLocation));
52+
return;
53+
}
54+
}
55+
callback.onFailure(new Exception("Last location unavailable"));
56+
}
57+
58+
@SuppressLint("MissingPermission")
59+
Location getLastLocationFor(String provider) throws SecurityException {
60+
Location location = null;
61+
try {
62+
location = locationManager.getLastKnownLocation(provider);
63+
} catch (IllegalArgumentException iae) {
64+
Log.e(TAG, iae.toString());
65+
}
66+
return location;
67+
}
68+
69+
@SuppressLint("MissingPermission")
70+
@Override
71+
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
72+
@NonNull LocationListener listener,
73+
@Nullable Looper looper) throws SecurityException {
74+
currentProvider = getBestProvider(request.getPriority());
75+
locationManager.requestLocationUpdates(currentProvider, request.getInterval(), request.getDisplacement(),
76+
listener, looper);
77+
}
78+
79+
@SuppressLint("MissingPermission")
80+
@Override
81+
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
82+
@NonNull PendingIntent pendingIntent) throws SecurityException {
83+
currentProvider = getBestProvider(request.getPriority());
84+
locationManager.requestLocationUpdates(currentProvider, request.getInterval(),
85+
request.getDisplacement(), pendingIntent);
86+
}
87+
88+
@SuppressLint("MissingPermission")
89+
@Override
90+
public void removeLocationUpdates(@NonNull LocationListener listener) {
91+
if (listener != null) {
92+
locationManager.removeUpdates(listener);
93+
}
94+
}
95+
96+
@Override
97+
public void removeLocationUpdates(PendingIntent pendingIntent) {
98+
if (pendingIntent != null) {
99+
locationManager.removeUpdates(pendingIntent);
100+
}
101+
}
102+
103+
private String getBestProvider(int priority) {
104+
String provider = null;
105+
if (priority != LocationEngineRequest.PRIORITY_NO_POWER) {
106+
provider = LocationManager.GPS_PROVIDER;
107+
}
108+
return provider != null ? provider : LocationManager.PASSIVE_PROVIDER;
109+
}
110+
111+
112+
@VisibleForTesting
113+
static final class AndroidLocationEngineCallbackTransport implements LocationListener {
114+
private final LocationEngineCallback<LocationEngineResult> callback;
115+
116+
AndroidLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
117+
this.callback = callback;
118+
}
119+
120+
@Override
121+
public void onLocationChanged(Location location) {
122+
callback.onSuccess(LocationEngineResult.create(location));
123+
}
124+
125+
@Override
126+
public void onStatusChanged(String s, int i, Bundle bundle) {
127+
// noop
128+
}
129+
130+
@Override
131+
public void onProviderEnabled(String s) {
132+
// noop
133+
}
134+
135+
@Override
136+
public void onProviderDisabled(String s) {
137+
callback.onFailure(new Exception("Current provider disabled"));
138+
}
139+
}
140+
}

Diff for: maplibre_gl/android/src/main/java/org/maplibre/maplibregl/MapLibreMapBuilder.java

+11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import androidx.annotation.NonNull;
1010
import org.maplibre.android.camera.CameraPosition;
1111
import org.maplibre.android.geometry.LatLngBounds;
12+
import org.maplibre.android.location.engine.LocationEngineRequest;
1213
import org.maplibre.android.maps.MapLibreMapOptions;
1314
import io.flutter.plugin.common.BinaryMessenger;
1415

@@ -23,6 +24,7 @@ class MapLibreMapBuilder implements MapLibreMapOptionsSink {
2324
private int myLocationRenderMode = 0;
2425
private String styleString = "";
2526
private LatLngBounds bounds = null;
27+
private LocationEngineRequest locationEngineRequest = null;
2628

2729
MapLibreMapController build(
2830
int id,
@@ -43,6 +45,10 @@ MapLibreMapController build(
4345
controller.setCameraTargetBounds(bounds);
4446
}
4547

48+
if (null != locationEngineRequest) {
49+
controller.setLocationEngineProperties(locationEngineRequest);
50+
}
51+
4652
return controller;
4753
}
4854

@@ -206,4 +212,9 @@ public void setAttributionButtonMargins(int x, int y) {
206212
public void setDragEnabled(boolean enabled) {
207213
this.dragEnabled = enabled;
208214
}
215+
216+
@Override
217+
public void setLocationEngineProperties(@NonNull LocationEngineRequest locationEngineRequest) {
218+
this.locationEngineRequest = locationEngineRequest;
219+
}
209220
}

Diff for: maplibre_gl/android/src/main/java/org/maplibre/maplibregl/MapLibreMapController.java

+18
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
import com.google.gson.JsonParser;
3535
import org.maplibre.android.gestures.AndroidGesturesManager;
3636
import org.maplibre.android.gestures.MoveGestureDetector;
37+
import org.maplibre.android.location.engine.LocationEngine;
38+
import org.maplibre.android.location.engine.LocationEngineDefault;
39+
import org.maplibre.android.location.engine.LocationEngineProxy;
40+
import org.maplibre.android.location.engine.LocationEngineRequest;
3741
import org.maplibre.geojson.Feature;
3842
import org.maplibre.geojson.FeatureCollection;
3943
import org.maplibre.android.camera.CameraPosition;
@@ -1868,6 +1872,20 @@ public void setCompassEnabled(boolean compassEnabled) {
18681872
mapLibreMap.getUiSettings().setCompassEnabled(compassEnabled);
18691873
}
18701874

1875+
@Override
1876+
public void setLocationEngineProperties(LocationEngineRequest locationEngineRequest){
1877+
if(locationComponent != null){
1878+
if(locationEngineRequest.getPriority() == LocationEngineRequest.PRIORITY_HIGH_ACCURACY){
1879+
locationComponent.setLocationEngine(new LocationEngineProxy(
1880+
new MapLibreGPSLocationEngine(context)));
1881+
} else {
1882+
locationComponent.setLocationEngine(
1883+
LocationEngineDefault.INSTANCE.getDefaultLocationEngine(context));
1884+
}
1885+
locationComponent.setLocationEngineRequest(locationEngineRequest);
1886+
}
1887+
}
1888+
18711889
@Override
18721890
public void setTrackCameraPosition(boolean trackCameraPosition) {
18731891
this.trackCameraPosition = trackCameraPosition;

Diff for: maplibre_gl/android/src/main/java/org/maplibre/maplibregl/MapLibreMapOptionsSink.kt

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package org.maplibre.maplibregl
55

66
import org.maplibre.android.geometry.LatLngBounds
7+
import org.maplibre.android.location.engine.LocationEngineRequest
78

89
/** Receiver of MapLibreMap configuration options. */
910
internal interface MapLibreMapOptionsSink {
@@ -42,4 +43,6 @@ internal interface MapLibreMapOptionsSink {
4243
fun setAttributionButtonGravity(gravity: Int)
4344

4445
fun setAttributionButtonMargins(x: Int, y: Int)
46+
47+
fun setLocationEngineProperties(locationEngineRequest: LocationEngineRequest)
4548
}

Diff for: maplibre_gl/lib/maplibre_gl.dart

+3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export 'package:maplibre_gl_platform_interface/maplibre_gl_platform_interface.da
6666
LatLngQuad,
6767
Line,
6868
LineOptions,
69+
LocationEngineAndroidProperties,
70+
LocationEnginePlatforms,
71+
LocationPriority,
6972
MapLibreMethodChannel,
7073
MapLibrePlatform,
7174
MinMaxZoomPreference,

Diff for: maplibre_gl/lib/src/maplibre_map.dart

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class MapLibreMap extends StatefulWidget {
2020
this.styleString = MapLibreStyles.demo,
2121
this.onMapCreated,
2222
this.onStyleLoadedCallback,
23+
this.locationEnginePlatforms = LocationEnginePlatforms.defaultPlatform,
2324
this.gestureRecognizers,
2425
this.compassEnabled = true,
2526
this.cameraTargetBounds = CameraTargetBounds.unbounded,
@@ -67,6 +68,10 @@ class MapLibreMap extends StatefulWidget {
6768
assert(annotationOrder.length <= 4),
6869
assert(annotationConsumeTapEvents.length > 0);
6970

71+
/// The properties for the platform-specific location engine.
72+
/// Only has an impact if [myLocationEnabled] is set to true.
73+
final LocationEnginePlatforms locationEnginePlatforms;
74+
7075
/// Defines the layer order of annotations displayed on map
7176
///
7277
/// Any annotation type can only be contained once, so 0 to 4 types
@@ -357,10 +362,12 @@ class _MapLibreMapOptions {
357362
this.compassViewMargins,
358363
this.attributionButtonPosition,
359364
this.attributionButtonMargins,
365+
this.locationEnginePlatforms
360366
});
361367

362368
_MapLibreMapOptions.fromWidget(MapLibreMap map)
363369
: this(
370+
locationEnginePlatforms: map.locationEnginePlatforms,
364371
compassEnabled: map.compassEnabled,
365372
cameraTargetBounds: map.cameraTargetBounds,
366373
styleString: map.styleString,
@@ -418,6 +425,8 @@ class _MapLibreMapOptions {
418425

419426
final Point? attributionButtonMargins;
420427

428+
final LocationEnginePlatforms? locationEnginePlatforms;
429+
421430
final _gestureGroup = {
422431
'rotateGesturesEnabled',
423432
'scrollGesturesEnabled',
@@ -464,6 +473,7 @@ class _MapLibreMapOptions {
464473
addIfNonNull('attributionButtonPosition', attributionButtonPosition?.index);
465474
addIfNonNull(
466475
'attributionButtonMargins', pointToArray(attributionButtonMargins));
476+
addIfNonNull('locationEngineProperties', locationEnginePlatforms?.toList());
467477
return optionsMap;
468478
}
469479

Diff for: maplibre_gl_platform_interface/lib/maplibre_gl_platform_interface.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
library maplibre_gl_platform_interface;
22

33
import 'dart:async';
4+
import 'dart:io';
45
import 'dart:convert';
56
import 'dart:math';
67
import 'package:flutter/foundation.dart';
@@ -20,3 +21,4 @@ part 'src/fill.dart';
2021
part 'src/ui.dart';
2122
part 'src/maplibre_gl_platform_interface.dart';
2223
part 'src/source_properties.dart';
24+
part 'src/location_engine_properties.dart';

0 commit comments

Comments
 (0)