Flutter App crash on IOS by using google_maps_flutter

1,181

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>
Share:
1,181
Siro Duschletta
Author by

Siro Duschletta

Updated on December 31, 2022

Comments

  • Siro Duschletta
    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/