I'm creating my first Flutter app. The app should show among other things on some places on a map. For the map I use google_maps_flutter (https://pub.dev/packages/google_maps_flutter).
Everything works fine on Android. As soon as I start the app on IOS and click on "Map" in my app, the app crashes without stacktrace. Android Studio just says "Lost connection to Device".
I have the SDK for Android and IOS active on the Google Cloud Platform and have added the key in the appDelegate.swift in my project.
I dont get it. Does anyone know what the problem could be? Thanks a lot for your help <3
This is my Class, which returns the Scaffold with Google Maps Widget:
class WaterMapScreen extends StatefulWidget {
@override
State<WaterMapScreen> createState() => _WaterMapScreenState();
}
class _WaterMapScreenState extends State<WaterMapScreen> {
GetIt getIt = GetIt.instance;
WaterService waterService;
List<Section> sectionList;
Location _location = new Location();
StreamController<FavSection> _streamController =
StreamController<FavSection>();
Set<Polygon> polygonSet = new Set();
UserService userService;
FavSection _selectedSection;
_WaterMapScreenState() {
waterService = getIt.get<WaterService>();
userService = getIt.get<UserService>();
}
initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_outlined, color: Colors.orange),
onPressed: () {
Navigator.pop(context);
}),
title: Text(
"Entdecken",
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.orange),
),
),
body: Stack(children: <Widget>[
getGoogleMapWithPolygons(),
CustomSlidingPanel(stream: _streamController.stream),
]),
);
}
FutureBuilder getGoogleMapWithPolygons() {
return FutureBuilder(
future: fetchSectionListWithFavorites(),
builder: (BuildContext context, AsyncSnapshot sectionListAsync) {
switch (sectionListAsync.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(color: Colors.orange));
default:
if (sectionListAsync.hasError) {
print('Error: ${sectionListAsync.error}');
return new Center(child: Text('Es ist ein Fehler aufgetreten'));
} else {
return FutureBuilder(
future: _location.getLocation(),
builder:
(BuildContext context, AsyncSnapshot locationAsync) {
switch (locationAsync.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(
color: Colors.orange));
default:
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(locationAsync.data.latitude,
locationAsync.data.longitude),
zoom: 10),
myLocationButtonEnabled: true,
mapType: MapType.normal,
myLocationEnabled: true,
polygons: sectionListAsync.data
.where((item) =>
item.section.gewaesserTyp == "SEE" ||
item.section.gewaesserTyp == "WEIER")
.map<Polygon>(
(item) => Polygon(
polygonId: PolygonId(item.section.id),
points: item.section.paths
.map<LatLng>((path) =>
LatLng(path.lat, path.lng))
.toList(),
fillColor: Colors.orange.withOpacity(0.5),
strokeColor: Colors.deepOrange,
strokeWidth: 5,
consumeTapEvents: true,
onTap: () {
_streamController
.add(_selectedSection = item);
},
),
)
.toSet(),
polylines: sectionListAsync.data
.where((item) =>
item.section.gewaesserTyp == "BACH" ||
item.section.gewaesserTyp == "FLUSS")
.map<Polyline>(
(item) => Polyline(
polylineId: PolylineId(item.section.id),
points: item.section.paths
.map<LatLng>((path) =>
LatLng(path.lat, path.lng))
.toList(),
color: Colors.deepOrange,
width: 5,
consumeTapEvents: true,
onTap: () {
_streamController
.add(_selectedSection = item);
},
),
)
.toSet(),
onTap: (LatLng latLng) {
_streamController.add(_selectedSection = null);
},
);
}
});
}
}
});
}
This is my appDelegate.swift:
import UIKit
import Flutter
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("MyTopSecretApiKey")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
My pubspec.yaml:
name: fishr
description: Mobile Fishing Guide
version: 1.0.0+5
environment:
sdk: ">=2.2.2 <3.0.0"
dependencies:
shared_preferences: ^2.0.6
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
font_awesome_flutter: ^9.0.0
flutter_bloc: ^7.0.0
http: ^0.13.1
meta: ^1.1.6
equatable: ^2.0.0
get_it: ^7.1.3
google_maps_flutter: ^2.0.3
location: ^4.1.1
url_launcher: ^6.0.3
expansion_tile_card: ^2.0.0
settings_ui: ^1.0.0
simple_animations: ^3.1.1
popover: ^0.2.2
charts_flutter: ^0.10.0
syncfusion_flutter_charts: ^19.1.64
sliding_up_panel: ^2.0.0+1
flutter_speed_dial: ^3.0.5
flutter_native_splash: ^1.1.8+4
flutter_launcher_icons: ^0.9.0
lint: ^1.5.3
introduction_screen: ^2.1.0
buy_me_a_coffee_widget: ^2.0.0-nullsafety.0
material_floating_search_bar: ^0.3.4
dev_dependencies:
mockito: ^5.0.10
# test_coverage: ^0.4.2
bloc_test: ^8.0.0
flutter_test:
sdk: flutter
flutter_icons:
android: "launcher_icon"
ios: true
image_path: "assets/icon/icon.png"
flutter_native_splash:
color: "#ffffff"
image: "assets/icon/splash_regular.png"
color_dark: "#262626"
image_dark: "assets/icon/splash_dark.png"
android: true
ios: true
flutter:
uses-material-design: true
assets:
- assets/images/
- assets/icon/
- assets/water/
It was an Permission Issue. Adding the following permissions in the ios/info.plist solved the problem :)
<!-- Permission options for the `location` group -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Need location when in use</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Always and when in use!</string>
<key>NSLocationUsageDescription</key>
<string>Older devices need location.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Can I have location always?</string>