HarmonyOS NEXT 適配高德地圖FlutterSDK實現地圖展示,添加覆蓋物和移動Camera

HarmonyOS NEXT 適配高德地圖 Flutter SDK 實現地圖展示,添加覆蓋物和移動 Camera

在現代移動應用開發中,地圖功能是許多應用的核心組成部分之一。HarmonyOS NEXT 提供了強大的跨平臺開發能力,而高德地圖 Flutter SDK 則為開發者提供了豐富的地圖功能。因為高德地圖FlutterSDK已停止維護,并且也沒有鴻蒙測的適配庫,所以才有了下面的內容,本文將詳細介紹如何在 HarmonyOS NEXT 中適配高德地圖 Flutter SDK,實現地圖展示、添加覆蓋物和移動 Camera 的功能。

一、技術亮點

1.1 Flutter 的優勢

  • 高效的構建效率:Flutter 的熱重載特性允許開發者即時預覽代碼更改的影響,極大地提高了開發效率。
  • 跨平臺兼容性:Flutter 應用可以在 Android、iOS 和 Web 等多個平臺上運行,無需為每個平臺單獨開發,從而節省了開發成本。
  • 豐富的組件庫:Flutter 提供了豐富的組件庫,如按鈕、文本框、列表等,幫助開發者輕松創建出色的用戶界面。

1.2 高德地圖 Flutter SDK 的優勢

高德地圖 Flutter SDK 提供了強大的地圖功能,包括地圖展示、覆蓋物添加和 Camera 操作等。通過與 Flutter 的結合,開發者可以輕松實現地圖相關的功能。

二、集成高德地圖 SDK

首先我們的基礎是要先集成高德地圖的FlutterSDK

amap_flutter_map: ^3.0.0

2.1 獲取 SDK

首先,你需要在高德開放平臺注冊并獲取 SDK。別忘了申請你的高德SDK的key,具體可以參考高德地圖的官網文檔

2.2 從ohpm倉庫獲取高德地圖包

 "dependencies": {"@amap/amap_lbs_common": ">=1.2.0","@amap/amap_lbs_map3d": ">=2.2.0"
}

2.3 聲明權限,工程的oh-package.json5文件中添加依賴

module.json5 中添加必要的權限和模塊聲明。

{
..."requestPermissions": [{"name": 'ohos.permission.INTERNET',}
]
...

三、地圖展示

3.1 接下來進入正題,既然是適配高德FlutterSDK,那肯定需要我們在鴻蒙端做一些重要工作

首先我們需要創建一個AMapView這個類的作用是接收Dart測過來的消息

/*** @FileName : AMapView* @Author : kirk.wang* @Time : 2025/5/7 17:19* @Description :*/
import { BinaryMessenger, MethodCall, MethodCallHandler, MethodChannel,MethodResult,StandardMethodCodec } from "@ohos/flutter_ohos";
import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'import { common } from "@kit.AbilityKit";
import { AMapBuilder } from "./AMapComponent";export class AMapView extends PlatformView implements MethodCallHandler {methodChannel: MethodChannel;args?: ESObject;constructor(context: common.Context, viewId: number , args: ESObject, message: BinaryMessenger) {super();this.args = argsthis.methodChannel = new MethodChannel(message, `amap_flutter_map_${viewId}`, StandardMethodCodec.INSTANCE);this.methodChannel.setMethodCallHandler(this);}onMethodCall(call: MethodCall, result: MethodResult): void {// 接受Dart側發來的消息let method: string = call.method;let link1: SubscribedAbstractProperty<number> = AppStorage.link('numValue');switch (method) {case 'getMessageFromFlutterView':let value: ESObject = call.args;link1.set(value)console.log("nodeController receive message from dart: ");result.success(true);break;}}getView(): WrappedBuilder<[Params]> {return new WrappedBuilder(AMapBuilder);}public sendMessage = () => {console.log("nodeController sendMessage")//向Dart側發送消息this.methodChannel.invokeMethod('getMessageFromOhosView', 'natvie - ');}dispose(): void {}}

3.2 這個AMapView在什么時候用呢,創建一個AMapPlatformViewFactory類繼承自 PlatformViewFactory,用于創建和管理地圖相關的原生視圖(PlatformView)

import { Any, BinaryMessenger, MessageCodec, PlatformView, PlatformViewFactory } from "@ohos/flutter_ohos";
import { common } from "@kit.AbilityKit";
import { AMapView } from "./AMapView";export default class AMapPlatformViewFactory extends PlatformViewFactory {message: BinaryMessenger;constructor(message: BinaryMessenger, createArgsCodes: MessageCodec<Object>) {super(createArgsCodes)this.message = message;}public create(context: common.Context, viewId: number, args: Any): PlatformView {return new AMapView(context, viewId, args, this.message);}}

3.3 創建地圖插件,注冊工廠類

/*** @FileName : AMapFlutterMapPlugin* @Author : kirk.wang* @Time : 2025/5/8 10:15* @Description : 高德地圖插件*/
import {Any,BasicMessageChannel, FlutterPlugin, FlutterPluginBinding,MethodChannel,StandardMessageCodec} from "@ohos/flutter_ohos";
import AMapPlatformViewFactory from "./AMapPlatformViewFactory";export default class AMapFlutterMapPlugin implements FlutterPlugin {onDetachedFromEngine(binding: FlutterPluginBinding): void {this.channel?.setMethodCallHandler(null)}private channel?:MethodChannel;private basicChannel?: BasicMessageChannel<Any>;private VIEW_TYPE : string = "com.amap.flutter.map";getUniqueClassName(): string {return "AMapFlutterMapPlugin"}onAttachedToEngine(binding: FlutterPluginBinding): void {binding.getPlatformViewRegistry().registerViewFactory(this.VIEW_TYPE, new AMapPlatformViewFactory(binding.getBinaryMessenger(),StandardMessageCodec.INSTANCE))}
}

3.3 創建地圖主視圖,然后根據傳遞的數據設置鴻蒙端的高德原生地圖,在AMapView里有一個getView,就是返回的下面的視圖代碼

/*** @FileName : AMapComponent* @Author : kirk.wang* @Time : 2025/5/8 14:20* @Description : 地圖主視圖*/
import {AMap,BitmapDescriptorFactory,CameraUpdateFactory,LatLng,MapsInitializer,MapView,MapViewComponent,MapViewManager,MarkerOptions
} from '@amap/amap_lbs_map3d'
import { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'
import { AMapView } from './AMapView'
import { ArrayList, HashMap, List } from '@kit.ArkTS';
import image from '@ohos.multimedia.image';
import json from '@ohos.util.json';const key = "你在高德地圖申請的鴻蒙端的key";@Component
struct AMapComponent {@Prop params: ParamscustomView: AMapView = this.params.platformView as AMapView@StorageLink('numValue') storageLink: string = "first"@State bkColor: Color = Color.RedaMap?: AMap;aboutToAppear(): void {MapsInitializer.setApiKey(key);MapsInitializer.setDebugMode(true);MapViewManager.getInstance().registerMapViewCreatedCallback((mapview?: MapView, mapViewName?: string) => {if (!mapview) {return;}mapview!.onCreate();mapview!.getMapAsync((map) => {this.aMap = map;})})}build() {Stack() {MapViewComponent({ mapViewName: "harmony_map_demo" }).zIndex(0)}.direction(Direction.Ltr).width('100%').height('100%')}
}@Builder
export function AMapBuilder(params: Params) {AMapComponent({ params: params }).backgroundColor(Color.Yellow)
}

四、添加覆蓋物

4.1 根據接收的數據來設置覆蓋物,設置地圖中心點以及縮放級別

在地圖上添加覆蓋物時,需要將 Flutter Widget 轉換為圖片,然后通過原生的 Marker 接口添加到地圖上。查看高德Flutter插件可知發送參數的信息,也可以在鴻蒙測斷點查看,注意 以下接收數據的key不可更改,否則無法接收到數據,例如:markersToAdd、initialCameraPosition等
Flutter傳輸的字節數組在鴻蒙端接收有問題,導致這個地方卡了好幾天┭┮﹏┭┮

  aboutToAppear(): void {MapsInitializer.setApiKey(key);MapsInitializer.setDebugMode(true);let tempList = this.customView.args?.get("markersToAdd") as List<Map<String, Object>>;let optionsList = new ArrayList<MarkerOptions>()try {tempList.forEach(async (op) => {let options = new MarkerOptions()options.setAlpha(op.get('alpha') as number);let anchor = op.get('anchor') as Array<number>options.setAnchor(anchor[0], anchor[1]);options.setClickable(op.get('clickable') as boolean);options.setDraggable(op.get('draggable') as boolean);options.setInfoWindowEnable(op.get('infoWindowEnable') as boolean);let positionList = op.get('position') as Array<number>if (positionList.length === 2) {options.setPosition(new LatLng(positionList[0], positionList[1]));}options.setZIndex(op.get('zIndex') as number);let icon = op.get('icon') as Array<string | Uint8Array>;if (icon.length >= 2) {try {//因chanel傳值導致數據被破壞,無法正確識別Uint8Array參數,所以需要json轉換后重新生成Uint8Array//將數據轉成JSON字符串let jsonStr = json.stringify(icon[1]);//JSON字符串格式化成maplet obj = json.parse(jsonStr) as HashMap<string, number>;// 將對象轉換為數組const array = Object.keys(obj).map((key): number => obj[key]);if (Array.isArray(array)) {//根據最新的數組生成Uint8Arraylet icon1 = new Uint8Array(array);//拷貝字節數組const buffer1 = icon1.buffer.slice(0);//通過字節數組生成圖片let imageSource: image.ImageSource = image.createImageSource(buffer1);let decodingOption: image.DecodingOptions = {editable: true,}imageSource.createPixelMap(decodingOption).then(async (pixelmap: PixelMap) => {//向options添加圖片信息options.setIcon(BitmapDescriptorFactory.fromPixelMapSync(pixelmap));//將options添加到數組optionsList.add(options);})}} catch (error) {console.error('Error:', error);}}});} catch (e) {console.log("===============Alpha:error:" + e);}

4.2 將 Flutter Widget 添加到地圖

MapViewManager.getInstance().registerMapViewCreatedCallback((mapview?: MapView, mapViewName?: string) => {if (!mapview) {return;}mapview!.onCreate();mapview!.getMapAsync((map) => {this.aMap = map;//向地圖添加Markersif (optionsList !== null && optionsList.length > 0) {this.aMap?.addMarkers(optionsList);}})})}

五、設置地圖中心點以及縮放級別

5.1 移動 Camera

通過調用地圖的 moveCamera 方法,可以移動地圖的 Camera。

  aboutToAppear(): void {...MapViewManager.getInstance().registerMapViewCreatedCallback((mapview?: MapView, mapViewName?: string) => {if (!mapview) {return;}mapview!.onCreate();mapview!.getMapAsync((map) => {this.aMap = map;let cameraPosition = this.customView.args?.get("initialCameraPosition") as Map<String, Object>;let targetList = cameraPosition.get('target') as Array<number>//設置地圖中心點以及縮放級別this.aMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(targetList[0], targetList[1]),cameraPosition.get('zoom') as number));...})})}

至此鴻蒙端的開發工作至此結束

七、Flutter端處理

找到Flutter端的method_channel_amap_flutter_map.dart,里面有個buildView函數,里面有判斷只支持

 @overrideWidget buildView(Map<String, dynamic> creationParams,Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,void Function(int id) onPlatformViewCreated) {if (defaultTargetPlatform == TargetPlatform.android) {creationParams['debugMode'] = kDebugMode;return AndroidView(viewType: VIEW_TYPE,onPlatformViewCreated: onPlatformViewCreated,gestureRecognizers: gestureRecognizers,creationParams: creationParams,creationParamsCodec: const StandardMessageCodec(),);} else if (defaultTargetPlatform == TargetPlatform.iOS) {return UiKitView(viewType: VIEW_TYPE,onPlatformViewCreated: onPlatformViewCreated,gestureRecognizers: gestureRecognizers,creationParams: creationParams,creationParamsCodec: const StandardMessageCodec(),);} // else if (defaultTargetPlatform == TargetPlatform.ohos) {//   return OhosView(//     viewType: VIEW_TYPE,//     onPlatformViewCreated: onPlatformViewCreated,//     gestureRecognizers: gestureRecognizers,//     creationParams: creationParams,//     creationParamsCodec: const StandardMessageCodec(),//   );// }return Text('當前平臺:$defaultTargetPlatform, 不支持使用高德地圖插件');}

將我注釋掉的代碼放開即可!接下來就可以在你的鴻蒙設備上調試了。完全按照我的代碼,除了高德的key,其余的都不要隨便更改哦,否則可能運行出來有問題

六、總結

通過上述步驟,你可以在 HarmonyOS NEXT 中適配高德地圖 Flutter SDK,實現地圖展示、添加覆蓋物和移動 Camera 的功能。Flutter 的跨平臺特性和高德地圖的強大功能相結合,為開發者提供了極大的便利。

希望本文能夠幫助你在 HarmonyOS NEXT 中成功集成高德地圖 Flutter SDK,并實現所需的地圖功能。如果你在開發過程中遇到任何問題,可以參考高德地圖的官方文檔,或在相關社區尋求幫助。

七、參考

  • Flutter中的高德地圖適配鴻蒙

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906225.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906225.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906225.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

三鍵標準、多鍵usb鼠標數據格式

三鍵標準usb鼠標數據格式 滾輪上滾 滾輪下滾 鼠標快速上移 鼠標快速右移 鼠標快速左移 鼠標右鍵單擊_抬起 鼠標中鍵單擊_抬起 鼠標左鍵單擊_抬起 鼠標左鍵先按_右鍵再按_同時抬起 鼠標左右鍵同時按下_同時抬起 鼠標左右鍵同時按下_右鍵先抬 多鍵usb鼠標…

軟件架構風格系列(7):閉環控制架構

文章目錄 引言一、閉環控制架構&#xff1a;讓系統學會“自我調節”的魔法&#xff08;一&#xff09;從溫控系統理解核心原理&#xff08;二&#xff09;核心組件解析 二、架構設計圖&#xff1a;閉環控制的“四大核心環節”三、Java實戰&#xff1a;手寫一個智能溫控系統&…

Python中的組合數據類型

一、列表類型 列表是指一系列的按特定順序排列的元素組成。使用[]定義列表&#xff0c;元素與元素之間使用英文的逗號分隔&#xff0c;列表中的元素可以是任意的數據類型。 #直接使用[]創建 lst[hello,world,99.8,100] print(lst)#可以使用內置的list()函數創建列表 lst2list(h…

集合進階2

Java不可變集合、Stream流與方法引用深度解析 一、不可變集合&#xff08;Immutable Collections&#xff09;進階指南 1.1 不可變集合核心特性 防御性編程&#xff1a;防止外部修改數據&#xff08;如傳遞集合給第三方庫時&#xff09;線程安全&#xff1a;天然支持多線程讀…

MySQL企業版免費開啟,強先體驗

近期Oracle突然宣布&#xff0c;MySQL企業版面向開發者免費開放下載&#xff0c;這一消息瞬間引爆DBA圈。作為數據庫領域的“頂配車型”&#xff0c;企業版長期因高昂授權費讓中小團隊望而卻步&#xff0c;如今免費開放無異于“勞斯萊斯開進菜市場”。 本文將深度拆解企業版的…

數據要素及征信公司數據要素實踐

數據要素及征信公司數據要素實踐 1.數據要素的定義與核心特征2.征信公司應用數據要素的實踐路徑3.總結1.數據要素的定義與核心特征 數據要素是數字經濟時代的新型生產要素,指以電子形式存在、通過計算方式參與生產經營活動并創造價值的數據資源。 其核心特征包括: 新型生產…

Golang 范型

引言 Go 從 1.18 開始正式支持泛型&#xff0c;帶來了更強的類型抽象能力&#xff0c;使得我們可以編寫更通用、可復用的代碼。本文檔將介紹下泛型與應用的一些內容 什么是泛型 泛型&#xff08;Generic&#xff09;是一種允許你編寫“參數化類型”的編程方式。你可以將類型…

vue-ganttastic甘特圖label標簽橫向滾動固定方法

這個甘特圖之前插件里&#xff0c;沒有找到能固定label標簽在屏幕上的辦法&#xff0c;用css各種辦法都沒有實現&#xff0c;所以我我直接手寫定位&#xff0c;用js監聽滾動條滾動的距離&#xff0c;然后同步移動甘特圖label標簽&#xff0c;造成一種定位的錯覺&#xff0c;以下…

VS2017編譯openssl3.0.8

openssl是一個功能豐富且自包含的開源安全工具箱。它提供的主要功能有:SSL協議實現(包括SSLv2、SSLv3和TLSv1)、大量軟算法(對稱/非對稱/摘要)、大數運算、非對稱算法密鑰生成、ASN.1編解碼庫、證書請求(PKCS10)編解碼、數字證書編解碼、CRL編解碼、OCSP協議、數字證書驗證、P…

16【架構進階】Flask藍圖與應用工廠模式:構建企業級Web應用的核心技巧

【架構進階】Flask藍圖與應用工廠模式&#xff1a;構建企業級Web應用的核心技巧 前言&#xff1a;為什么應用架構決定項目的天花板&#xff1f; 在Flask開發中&#xff0c;隨著項目規模的擴大&#xff0c;如何組織代碼結構成為決定項目可維護性和擴展性的關鍵因素。單文件應用…

系統架構設計-案例分析總結

系統架構設計-案例分析總結 2024年下半年系統架構設計師案例第1題 2022年下半年系統架構設計師案例第1題第2題 2021年下半年系統架構設計師案例第1題第2題 2024年下半年系統架構設計師案例 題&#xff1a;效用樹可用性中ping/echo策略和心跳策略比較 第1題 閱讀以下關于面向質…

軟件架構風格系列(6):解釋器架構

文章目錄 引言一、從計算器到規則引擎&#xff1a;解釋器架構的核心本質&#xff08;一&#xff09;什么是解釋器架構&#xff1f;&#xff08;二&#xff09;核心組件&#xff1a;構建“語言理解系統”的三駕馬車 二、架構設計圖&#xff1a;從輸入到執行的完整鏈路三、Java實…

Serverless 的未來與進階:持續學習之路

Serverless 的未來與進階&#xff1a;持續學習之路 恭喜你&#xff0c;堅持走到了《輕松入門 Serverless》系列博客的最后一篇&#xff01; 回顧我們的旅程&#xff0c;我們一起&#xff1a; 揭開了 Serverless 的神秘面紗&#xff0c;理解了它的核心思想、關鍵特征以及 Faa…

設備數據看板助力自動化工廠實現生產智能精細化管理

工廠數字化轉型需要實現自動化設備生產現場可視化、設備系統間的互聯互通&#xff0c;以及數據的智能決策。然而&#xff0c;當前許多制造企業仍面臨著傳統單機設備同質化嚴重、數字化服務能力不足、售后成本高企、系統集成效率低下等挑戰。企業如何通過自動化裝備看板和實時數…

pcie phy電氣層(PCS)詳解gen1、2 (rx)

注&#xff1a;推薦大家查看英文原版&#xff0c;筆者大部分內容也為翻譯&#xff1b; S IP&#xff1a; 1. pcie供電&#xff1a; Vph&#xff1a; 1.2&#xff0c;1.5&#xff0c; 1.8V high voltage IO supply&#xff1b; Vp/VptxX/Vpdig &#xff1a;analog supply&am…

Java—— File詳解

說明 File對象就表示一個路徑&#xff0c;可以是文件的路徑、也可以是文件夾的路徑 這個路徑可以是存在的&#xff0c;也允許是不存在的 獲取File對象 方法名稱說明public File(String pathname)根據文件路徑創建文件對象public File(String parent,String child)根據父路徑名…

【數字圖像處理】半開卷復習提綱

1&#xff1a;要求 2張A4紙以內&#xff0c;正反面均可寫 &#xff08;不過博主由于墨水浸到背面了&#xff0c;采用了把2張單面通過雙面膠粘起來的方法&#xff0c;結果考前半個小時都在用這個難用的雙面膠。。。&#xff09; 2&#xff1a;提綱內容 3&#xff1a;提示 考的…

Neovim 如何安裝和配置縮進標識插件 indent-blankline.nvim

Neovim 0.9 以?lazy.nvim?為核心的現代化配置指南 一次性搞定插件管理、UI 優化與高效行跳轉 適用平臺&#xff1a;Linux&#xff0f;macOS&#xff0f;WSL&#xff0f;Windows (Neovim ≥?0.9) 目錄 為什么選?lazy.nvim安裝與初始化 2.1 創建配置目錄 2.2 克隆?lazy.nvi…

VulnHub | Breach - 1

&#x1f31f; 關注這個靶場的其它相關筆記&#xff1a;[網安靶場] 紅隊綜合滲透靶場 —— VulnHub 靶場筆記合集 Breach: 1 ~ VulnHubBreach: 1, made by mrb3n. Download & walkthrough links are available.https://vulnhub.com/entry/breach-1,152/ 0x01&#xff1a;…

城市綜合管廊監測與維護一體化解決方案

一、 方案概述 城市綜合管廊監測主要源于現代城市對地下管線管理的迫切需求。隨著城市化進程的加快&#xff0c;地下管線作為城市的“生命線”&#xff0c;其重要性日益凸顯。傳統的地下管線管理方式存在分散、低效、易產生信息孤島和管理盲區等問題&#xff0c;已無法滿足現代…