停車場找不到自己的車停在哪兒?教你開發一款“Find My Car”App
您會忘記您的車停在哪了嗎?如果會,這款應用是您不錯的一個選擇!
在本指南中,將實現如下功能:
l 使用 華為地圖服務來標記車輛的位置,並在華為地圖上展示前往車輛所在位置的路徑。
l 使用 華為定位服務來獲取使用者的當前位置。
l 使用 Shared Preferences 來儲存車輛停放位置資料。
l 使用 Directions API 來規劃前往車輛所在位置的路徑。
首先,您需要註冊一個華為開發者賬戶,並在 AppGallery Connect 中新增一個應用專案。開啟 “ 地圖服務 ” 和 “ 定位服務 ” 開關,以便在您的應用中使用服務。如果您沒有華為開發者賬戶,不清楚具體步驟,請參考如下連結:
l 配置AGC 資訊
重要 :新增應用時,輸入的應用包名應當與您的 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 = " 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 定位服務文件
原文連結: https://developer.huawei.com/consumer/cn/forum/topic/0201549190057190044?fid=18
原作者:胡椒
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69970551/viewspace-2775835/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 智慧停車場停車怎麼找車
- 停車場無人看管智慧停車系統怎麼停車和找車?
- 智慧停車場
- 怎樣查車停車什麼停車場技術分析
- 高階停車場停車計費解決方案
- 停車場結構圖怎麼畫,自己畫停車位需要什麼工具
- 停車場智慧尋車系統,大型停車場智慧車位導航技術
- 地下車庫找不到車子怎麼辦?在停車場怎麼找車?
- 智慧停車怎麼實現的,停車場找車系統怎麼找車
- 停車場室內導航怎麼用,停車場尋車是怎麼實現的
- 智慧停車場專案
- 停車場管理系統
- 停車機器人上崗 實現停車場無人值守機器人
- 停車場地圖怎樣好看,停車場怎麼畫簡單又漂亮地圖
- 地下停車場怎麼導航,停車場導航技術怎麼實現
- 什麼軟體畫停車場好用,停車場的地圖要怎麼畫才好看地圖
- 停車場導檢視怎麼做,簡單的停車場地圖怎麼畫好看地圖
- 停車場結構圖怎麼做,地下停車場怎麼畫簡單又好看
- 室內停車場地圖怎麼畫,地下停車場導檢視怎麼畫地圖
- 停車場構造圖怎麼畫好看,簡單的停車場地圖怎麼畫圖地圖
- AI開發實踐:關於停車場中車輛識別與跟蹤AI
- 如何在地下停車場快速找到車?地下車庫怎麼快速找車?
- 車牌識別助力“智慧停車”
- 【資料結構】停車場問題資料結構
- 高德地圖附近停車場服務地圖
- 小區地下車庫怎麼進出,停車場尋車功能怎麼用
- 春節停車難?用Python找空車位Python
- 智慧停車場解決方案,反向尋車系統解決方案
- 畫停車位需要什麼工具,可以顯示停車位的地圖有哪些地圖
- [LintCode] Parking Lot 停車場問題
- 地下停車場導航方案,智慧反向尋車系統怎麼做
- 車庫尋車有什麼好辦法,停車場自動尋車系統怎麼用
- 人工智慧並非萬能,智慧停車怕難解決城市停車難題?人工智慧
- 停車場的模擬管理(資料結構 C++)資料結構C++
- 您的檔案加速專車已停穩,請上車!!!
- 解決公務車Bug:停車費管理中匯入停車費用時報資料庫操作異常資料庫
- 一個停車場地圖線上繪製平臺地圖
- 停車場地圖如何繪製,地下車庫地圖怎麼畫好看地圖