您会遗记您的车停在哪了吗?如果会,这款利用是您不错的一个抉择!
在本指南中,将实现如下性能:
l 应用华为地图服务来标记车辆的地位,并在华为地图上展现返回车辆所在位置的门路。
l 应用华为定位服务来获取用户的以后地位。
l 应用Shared Preferences来存储车辆停放地位数据。
l 应用Directions API来布局返回车辆所在位置的门路。
首先,您须要注册一个华为开发者账户,并在AppGallery Connect中增加一个利用我的项目。开启“地图服务”和“定位服务”开关,以便在您的利用中应用服务。如果您没有华为开发者账户,不分明具体步骤,请参考如下链接:
l 注册华为开发者账户
l 配置AGC信息
l 集成地图服务Flutter插件
l 集成定位服务Flutter插件
重要:增加利用时,输出的利用包名该当与您的Flutter我的项目包名统一。
留神:下载agconnect-services.json文件前,请确保已开明所需的HMS服务。
权限
为失常应用HMS服务,您须要在AndroidManifest.xml文件中增加如下权限:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
增加依赖
实现上述步骤后,需在pubspec.yaml文件中增加对所需HMS服务对应的Flutter插件的依赖。您能够在pub.dev中找到最新版本的插件。
dependencies: flutter: sdk: flutter huawei_map: ^5.0.3+302 huawei_location: ^5.0.0+301 shared_preferences: ^0.5.12+4 http: ^0.12.2
增加插件依赖后,运行flutter pub get命令。
至此,所有增加的插件均已准备就绪。
申请定位权限并获取地位
PermissionHandler _permissionHandler = PermissionHandler(); FusedLocationProviderClient _locationService = FusedLocationProviderClient(); Location _myLocation; LatLng _center; @override void initState() { requestPermission(); super.initState(); } requestPermission() async { bool hasPermission = await _permissionHandler.hasLocationPermission(); if (!hasPermission) hasPermission = await _permissionHandler.requestLocationPermission(); if (hasPermission) getLastLocation(); } getLastLocation() async { _myLocation = await _locationService.getLastLocation(); setState(() { _center = LocationUtils.locationToLatLng(_myLocation); }); }
Location数据类型来自华为定位服务。LatLng数据类型来自华为地图服务。调用getLastLocation办法时会获取到一个Location取值,您须要将其转换为LatLng取值,以便在HuaweiMap控件中应用。
class LocationUtils { static LatLng locationToLatLng(Location location) => LatLng(location.latitude, location.longitude);}
增加HuaweiMap控件和按钮
如果_myLocation变量取值不是null,示意已获取到用户地位,且利用能够启动并将该地位赋值给HuaweiMap控件中的指标属性。
Stack( children: [ HuaweiMap( initialCameraPosition: CameraPosition( target: _center, zoom: _zoom, ), markers: _markers, polylines: _polylines, mapType: MapType.normal, tiltGesturesEnabled: true, buildingsEnabled: true, compassEnabled: true, zoomControlsEnabled: true, rotateGesturesEnabled: true, myLocationButtonEnabled: true, myLocationEnabled: true, trafficEnabled: false, ), Positioned( left: 20, top: 20, child: _isCarParked ? CustomButton( text: "Go to My Car", onPressed: goToMyCar, ) : CustomButton( text: "Set Location", onPressed: parkMyCar, ), ), ],),
应用Stack封装HuaweiMap控件,并增加按钮。按钮名称和性能会随车辆状态的变动而扭转。
停车并设置地位
void parkMyCar() { getLastLocation(); Prefs.setCarLocation(_myLocation); Prefs.setIsCarParked(true); getCarStatus(); } getLastLocation() async { _myLocation = await _locationService.getLastLocation(); setState(() { _center = LocationUtils.locationToLatLng(_myLocation); }); } getCarStatus() async { _isCarParked = await Prefs.getIsCarParked(); setState(() {}); addMarker(); } addMarker() async { if (_isCarParked && _markers.isEmpty) { LatLng carLocation = await Prefs.getCarLocation(); setState(() { _markers.add(Marker( markerId: MarkerId("myCar"), position: carLocation, )); }); } }
增加地位时,获取用户的最初地位,更新_myLocation和_center,在应用SharedPreferences存储数据的Prefs类中设置地位,而后增加一个标记来展现车辆的地位。
如下示例代码中,创立了一个名为Prefs的helper类,并应用SharedPreferences将办法离开。
class Prefs { static const String _latitude = "car_location_latitude"; static const String _longitude = "car_location_longitude"; static const String _isLocationSet = "is_location_set"; static void setCarLocation(Location location) async { SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setDouble(_latitude, location.latitude); prefs.setDouble(_longitude, location.longitude); print("Car's location has been set to (${location.latitude}, ${location.longitude})"); } static Future<LatLng> getCarLocation() async { SharedPreferences prefs = await SharedPreferences.getInstance(); double lat = prefs.getDouble(_latitude); double lng = prefs.getDouble(_longitude); return LatLng(lat, lng); } static void setIsCarParked(bool value) async { SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setBool(_isLocationSet, value); } static Future<bool> getIsCarParked() async { SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getBool(_isLocationSet)?? false; }}
点击Set Location按钮后,将设置以后地位并在利用内存中应用SharedPreferences存储地位。此外,该按钮的名称和性能也将扭转,以便通过扭转后的按钮返回到停车地位。
查找车辆
在返回时,点击Go to My Car按钮。Directions API会查找一条从以后地位到停车地位的路线,而后利用会在华为地图上通过折线来展现该路线。
void goToMyCar() async { getLastLocation(); addMarker(); LatLng carLocation = await Prefs.getCarLocation(); DirectionRequest request = DirectionRequest( origin: Destination( lat: _myLocation.latitude, lng: _myLocation.longitude, ), destination: Destination( lat: carLocation.lat, lng: carLocation.lng, ), ); DirectionResponse response = await DirectionUtils.getDirections(request); drawRoute(response); } drawRoute(DirectionResponse response) { if (_polylines.isNotEmpty) _polylines.clear(); var steps = response.routes[0].paths[0].steps; for (int i = 0; i < steps.length; i++) { for (int j = 0; j < steps[i].polyline.length; j++) { _points.add(steps[i].polyline[j].toLatLng()); } } setState(() { _polylines.add( Polyline( polylineId: PolylineId("route"), points: _points, color: Colors.redAccent), ); }); }
应用Directions API时需特地留神,您须要在HTTP posting前将您编码后的API key增加到URL地址开端。能够通过encodeComponent办法来实现,如下代码所示。
class ApplicationUtils { static String encodeComponent(String component) => Uri.encodeComponent(component); static const String API_KEY = "YOUR_API_KEY"; // HTTPS POST static String url = "https://mapapi.cloud.huawei.com/mapApi/v1/routeService/walking?key=" + encodeComponent(API_KEY);} class DirectionUtils { static Future<DirectionResponse> getDirections(DirectionRequest request) async { var headers = <String, String>{ "Content-type": "application/json", }; var response = await http.post(ApplicationUtils.url, headers: headers, body: jsonEncode(request.toJson())); if (response.statusCode == 200) { DirectionResponse directionResponse = DirectionResponse.fromJson(jsonDecode(response.body)); return directionResponse; } else throw Exception('Failed to load direction response'); }}
例如,如果原始API key是ABC/DFG+,则转换后果为 ABC%2FDFG%2B.。
至此,咱们实现了2大性能:地位存储以及回到存储数据所代表的地位。此外,还增加了一个floatingActionButton(浮动按钮),用来重置地位数据和清屏。
clearScreen() { Prefs.setIsCarParked(false); Prefs.setCarLocation(null); _markers.clear(); _polylines.clear(); getCarStatus(); } Stack( children: [ /* * Other widgets */ Positioned( left: 20, bottom: 20, child: FloatingActionButton( backgroundColor: Colors.blueGrey, child: Icon(Icons.clear), onPressed: clearScreen, ), ), ], ),
您能够在GitHub页面查看残缺的代码。页面链接:GitHub
舒适提醒
l Directions API反对三种门路布局:步行、骑行以及驾车。每种门路布局对应的URL都不同。
l 增加API key到URL开端前,请先对进行编码。否则,您将无奈获取响应。
l 您能够在agconnect-services.json文件中查看您的API key。
更多详情请点击:
l 地图服务文档
l 定位服务文档
l Directions API文档
l 地图服务Demo我的项目
l 定位服务Demo我的项目
原文链接:https://developer.huawei.com/...
原作者:胡椒