Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Adding My Location parameter to the Google Maps plugin #898

Merged
merged 9 commits into from
Nov 20, 2018
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ static void interpretGoogleMapOptions(Object o, GoogleMapOptionsSink sink) {
if (zoomGesturesEnabled != null) {
sink.setZoomGesturesEnabled(toBoolean(zoomGesturesEnabled));
}
final Object myLocationEnabled = data.get("myLocationEnabled");
if (myLocationEnabled != null) {
sink.setMyLocationEnabled(toBoolean(myLocationEnabled));
}
}

static void interpretMarkerOptions(Object o, MarkerOptionsSink sink) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
class GoogleMapBuilder implements GoogleMapOptionsSink {
private final GoogleMapOptions options = new GoogleMapOptions();
private boolean trackCameraPosition = false;
private boolean myLocationEnabled = false;

GoogleMapController build(
int id, Context context, AtomicInteger state, PluginRegistry.Registrar registrar) {
final GoogleMapController controller =
new GoogleMapController(id, context, state, registrar, options);
controller.init();
controller.setMyLocationEnabled(myLocationEnabled);
controller.setTrackCameraPosition(trackCameraPosition);
return controller;
}
Expand Down Expand Up @@ -78,4 +80,9 @@ public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) {
public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
options.zoomGesturesEnabled(zoomGesturesEnabled);
}

@Override
public void setMyLocationEnabled(boolean myLocationEnabled) {
this.myLocationEnabled = myLocationEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
import static io.flutter.plugins.googlemaps.GoogleMapsPlugin.STARTED;
import static io.flutter.plugins.googlemaps.GoogleMapsPlugin.STOPPED;

import android.Manifest;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
Expand Down Expand Up @@ -48,6 +52,7 @@ final class GoogleMapController
OnMapReadyCallback,
OnMarkerTappedListener,
PlatformView {
private static final String TAG = "GoogleMapController";
private final int id;
private final AtomicInteger activityState;
private final MethodChannel methodChannel;
Expand All @@ -56,10 +61,12 @@ final class GoogleMapController
private final Map<String, MarkerController> markers;
private GoogleMap googleMap;
private boolean trackCameraPosition = false;
private boolean myLocationEnabled = false;
private boolean disposed = false;
private final float density;
private MethodChannel.Result mapReadyResult;
private final int registrarActivityHashCode;
private final Context context;

GoogleMapController(
int id,
Expand All @@ -68,6 +75,7 @@ final class GoogleMapController
PluginRegistry.Registrar registrar,
GoogleMapOptions options) {
this.id = id;
this.context = context;
this.activityState = activityState;
this.registrar = registrar;
this.mapView = new MapView(context, options);
Expand Down Expand Up @@ -171,6 +179,7 @@ public void onMapReady(GoogleMap googleMap) {
googleMap.setOnCameraMoveListener(this);
googleMap.setOnCameraIdleListener(this);
googleMap.setOnMarkerClickListener(this);
updateMyLocationEnabled();
}

@Override
Expand Down Expand Up @@ -399,4 +408,28 @@ public void setMinMaxZoomPreference(Float min, Float max) {
public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
googleMap.getUiSettings().setZoomGesturesEnabled(zoomGesturesEnabled);
}

@Override
public void setMyLocationEnabled(boolean myLocationEnabled) {
if (this.myLocationEnabled == myLocationEnabled) {
return;
}
this.myLocationEnabled = myLocationEnabled;
if (googleMap != null) {
amirh marked this conversation as resolved.
Show resolved Hide resolved
updateMyLocationEnabled();
}
}

private void updateMyLocationEnabled() {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
googleMap.setMyLocationEnabled(myLocationEnabled);
} else {
// TODO(amirh): Make the options update fail.
// https://github.com/flutter/flutter/issues/24327
Log.e(TAG, "Cannot enable MyLocation layer as location permissions are not granted");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ interface GoogleMapOptionsSink {
void setTrackCameraPosition(boolean trackCameraPosition);

void setZoomGesturesEnabled(boolean zoomGesturesEnabled);

void setMyLocationEnabled(boolean myLocationEnabled);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package="io.flutter.plugins.googlemapsexample">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<application
android:name="io.flutter.app.FlutterApplication"
Expand Down
6 changes: 4 additions & 2 deletions packages/google_maps_flutter/example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs your location to test the location feature of the Google Maps plugin.</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
Expand All @@ -43,9 +45,9 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
</dict>
</plist>
15 changes: 15 additions & 0 deletions packages/google_maps_flutter/example/lib/map_ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,20 @@ class MapUiBodyState extends State<MapUiBody> {
);
}

Widget _myLocationToggler() {
return FlatButton(
child: Text(
'${_options.myLocationEnabled ? 'disable' : 'enable'} my location'),
onPressed: () {
mapController.updateMapOptions(
GoogleMapOptions(
myLocationEnabled: !_options.myLocationEnabled,
),
);
},
);
}

@override
Widget build(BuildContext context) {
final List<Widget> columnChildren = <Widget>[
Expand Down Expand Up @@ -226,6 +240,7 @@ class MapUiBodyState extends State<MapUiBody> {
_scrollToggler(),
_tiltToggler(),
_zoomToggler(),
_myLocationToggler(),
],
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
- (void)setTiltGesturesEnabled:(BOOL)enabled;
- (void)setTrackCameraPosition:(BOOL)enabled;
- (void)setZoomGesturesEnabled:(BOOL)enabled;
- (void)setMyLocationEnabled:(BOOL)enabled;
@end

// Defines map overlay controllable from Flutter.
Expand Down
14 changes: 11 additions & 3 deletions packages/google_maps_flutter/ios/Classes/GoogleMapController.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,11 @@ - (instancetype)initWithFrame:(CGRect)frame
if ([super init]) {
_viewId = viewId;

NSDictionary* options = args[@"options"];
GMSCameraPosition* camera = toOptionalCameraPosition(options[@"cameraPosition"]);
GMSCameraPosition* camera = toOptionalCameraPosition(args[@"cameraPosition"]);
_mapView = [GMSMapView mapWithFrame:frame camera:camera];
_markers = [NSMutableDictionary dictionaryWithCapacity:1];
_trackCameraPosition = NO;
interpretMapOptions(options, self);
interpretMapOptions(args, self);
timtraversy marked this conversation as resolved.
Show resolved Hide resolved
NSString* channelName =
[NSString stringWithFormat:@"plugins.flutter.io/google_maps_%lld", viewId];
_channel = [FlutterMethodChannel methodChannelWithName:channelName
Expand Down Expand Up @@ -217,6 +216,11 @@ - (void)setZoomGesturesEnabled:(BOOL)enabled {
_mapView.settings.zoomGestures = enabled;
}

- (void)setMyLocationEnabled:(BOOL)enabled {
_mapView.myLocationEnabled = enabled;
_mapView.settings.myLocationButton = enabled;
}

#pragma mark - GMSMapViewDelegate methods

- (void)mapView:(GMSMapView*)mapView willMove:(BOOL)gesture {
Expand Down Expand Up @@ -395,6 +399,10 @@ static void interpretMapOptions(id json, id<FLTGoogleMapOptionsSink> sink) {
if (zoomGesturesEnabled) {
[sink setZoomGesturesEnabled:toBool(zoomGesturesEnabled)];
}
id myLocationEnabled = data[@"myLocationEnabled"];
if (myLocationEnabled) {
[sink setMyLocationEnabled:toBool(myLocationEnabled)];
}
}

static void interpretMarkerOptions(id json, id<FLTGoogleMapMarkerOptionsSink> sink,
Expand Down
30 changes: 30 additions & 0 deletions packages/google_maps_flutter/lib/src/ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class GoogleMapOptions {
this.tiltGesturesEnabled,
this.trackCameraPosition,
this.zoomGesturesEnabled,
this.myLocationEnabled,
});

/// The desired position of the map camera.
Expand Down Expand Up @@ -125,6 +126,31 @@ class GoogleMapOptions {
/// True if the map view should respond to zoom gestures.
final bool zoomGesturesEnabled;

/// True if a "My Location" layer should be shown on the map.
///
/// This layer includes a location indicator at the current device location,
/// as well as a My Location button.
/// * The indicator is a small blue dot if the device is stationary, or a
/// chevron if the device is moving.
/// * The My Location button animates to focus on the user's current location
/// if the user's location is currently known.
///
/// Enabling this feature requires adding location permissions to both native
/// platforms of your app.
/// * On Android add either
/// `<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />`
/// or `<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />`
/// to your `AndroidManifest.xml` file. `ACCESS_COARSE_LOCATION` returns a
/// location with an accuracy approximately equivalent to a city block, while
/// `ACCESS_FINE_LOCATION` returns as precise a location as possible, although
/// it consumes more battery power. You will also need to request these
/// permissions during run-time. If they are not granted, the My Location
/// feature will fail silently.
/// * On iOS add a `NSLocationWhenInUseUsageDescription` key to your
/// `Info.plist` file. This will automatically prompt the user for permissions
/// when the map tries to turn on the My Location layer.
final bool myLocationEnabled;

/// Default user interface options.
///
/// Specifies a map view that
Expand All @@ -138,6 +164,7 @@ class GoogleMapOptions {
/// * responds to tilt gestures; [tiltGesturesEnabled] is true
/// * is silent about camera movement; [trackCameraPosition] is false
/// * responds to zoom gestures; [zoomGesturesEnabled] is true
/// * does not show user location; [myLocationEnabled] is false
static final GoogleMapOptions defaultOptions = GoogleMapOptions(
compassEnabled: true,
cameraPosition: const CameraPosition(target: LatLng(0.0, 0.0)),
Expand All @@ -149,6 +176,7 @@ class GoogleMapOptions {
tiltGesturesEnabled: true,
trackCameraPosition: false,
zoomGesturesEnabled: true,
myLocationEnabled: false,
);

/// Creates a new options object whose values are the same as this instance,
Expand All @@ -172,6 +200,7 @@ class GoogleMapOptions {
tiltGesturesEnabled: change.tiltGesturesEnabled ?? tiltGesturesEnabled,
trackCameraPosition: change.trackCameraPosition ?? trackCameraPosition,
zoomGesturesEnabled: change.zoomGesturesEnabled ?? zoomGesturesEnabled,
myLocationEnabled: change.myLocationEnabled ?? myLocationEnabled,
);
}

Expand All @@ -194,6 +223,7 @@ class GoogleMapOptions {
addIfPresent('tiltGesturesEnabled', tiltGesturesEnabled);
addIfPresent('trackCameraPosition', trackCameraPosition);
addIfPresent('zoomGesturesEnabled', zoomGesturesEnabled);
addIfPresent('myLocationEnabled', myLocationEnabled);
return json;
}
}