Flutter App crash on IOS by using google_maps_flutter
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>
Siro Duschletta
Updated on December 31, 2022Comments
-
Siro Duschletta over 1 year
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/