使用 google_maps_flutter 在 IOS 上 Flutter App 崩溃
Flutter App crash on IOS by using google_maps_flutter
我正在创建我的第一个 Flutter 应用程序。该应用程序应在地图上的某些地方显示其他内容。对于地图,我使用 google_maps_flutter (https://pub.dev/packages/google_maps_flutter).
Android 一切正常。一旦我在 IOS 上启动应用程序并单击我的应用程序中的“地图”,应用程序就会在没有堆栈跟踪的情况下崩溃。 Android Studio 只是说“丢失与设备的连接”。
我在 Google 云平台上激活了 Android 和 IOS 的 SDK,并在我的项目中的 appDelegate.swift 添加了密钥。
我不明白。有谁知道是什么问题?非常感谢您的帮助 <3
这是我的 Class,其中 returns 带有 Google 地图小部件的脚手架:
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);
},
);
}
});
}
}
});
}
这是我的 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)
}
}
我的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/
这是一个权限问题。在 ios/info.plist 中添加以下权限解决了问题:)
<!-- 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>
我正在创建我的第一个 Flutter 应用程序。该应用程序应在地图上的某些地方显示其他内容。对于地图,我使用 google_maps_flutter (https://pub.dev/packages/google_maps_flutter).
Android 一切正常。一旦我在 IOS 上启动应用程序并单击我的应用程序中的“地图”,应用程序就会在没有堆栈跟踪的情况下崩溃。 Android Studio 只是说“丢失与设备的连接”。
我在 Google 云平台上激活了 Android 和 IOS 的 SDK,并在我的项目中的 appDelegate.swift 添加了密钥。
我不明白。有谁知道是什么问题?非常感谢您的帮助 <3
这是我的 Class,其中 returns 带有 Google 地图小部件的脚手架:
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);
},
);
}
});
}
}
});
}
这是我的 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)
}
}
我的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/
这是一个权限问题。在 ios/info.plist 中添加以下权限解决了问题:)
<!-- 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>