您会遗记您的车停在哪了吗?如果会,这款利用是您不错的一个抉择!

在本指南中,将实现如下性能:

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/...
原作者:胡椒