鸿蒙 Map Kit 实战:调用华为地图服务,开发一个“周边美食搜索”原子化服务卡片

标签:#HarmonyOS #MapKit #SiteKit #元服务 #ArkTS #LBS


🍱 前言:当 LBS 遇上万能卡片

传统的找店流程:解锁手机 -> 找 App -> 点击启动 -> 等广告 -> 搜索“美食” -> 筛选附近。
鸿蒙元服务流程:点亮屏幕 -> 看一眼桌面卡片

这背后的技术链路其实并不复杂:

  1. 定位:获取用户当前经纬度。
  2. 搜索 (Site Kit):根据坐标搜索周边 POI (兴趣点)。
  3. 展示 (Form):将数据渲染到轻量级的卡片上。
  4. 导航 (Map Kit):点击卡片,拉起地图进行导航。

数据流转图 (Mermaid):

1. 刷新卡片/定时更新
2. 获取经纬度
3. 返回坐标
4. 调用周边搜索 API
5. 返回餐厅列表 JSON
6. updateForm (更新数据)
7. 点击某餐厅

用户桌面

FormExtensionAbility

Location Kit

Huawei Site Kit

桌面卡片 UI

应用主页/地图页


🛠️ 一、 准备工作:AGC 配置

在使用华为地图服务前,必须在 AppGallery Connect (AGC) 上开通权限。

  1. 注册开发者账号:登录华为开发者联盟。
  2. 创建项目与应用:获取client_id
  3. 开启 API:在“我的项目” -> “API管理”中,开启Map KitSite Kit
  4. 配置工程:在module.json5中配置client_id
"module": { "metadata": [ { "name": "client_id", "value": "你的_CLIENT_ID" // ⚠️ 别忘了这个! } ] }

📡 二、 核心逻辑:获取定位与周边搜索

我们需要在EntryFormAbility(卡片的生命周期管理类) 或者后台 Service 中处理逻辑。为了演示清晰,我们直接看核心的 API 调用。

首先,申请权限ohos.permission.LOCATIONohos.permission.APPROXIMATELY_LOCATION

1. 引入模块
import{site}from'@kit.MapKit';// 鸿蒙 Next 中 Site Kit 已集成在 Map Kit 命名空间下import{geoLocationManager}from'@kit.LocationKit';
2. 封装搜索函数

我们需要调用 Site Kit 的nearbySearch接口。

asyncfunctionsearchNearbyFood(lat:number,lng:number){// 1. 构建搜索请求letsearchRequest:site.NearbySearchRequest={location:{latitude:lat,longitude:lng},query:"美食",// 搜索关键词radius:1000,// 搜索半径 1公里pageSize:4,// 卡片位置有限,只拿前4个pageIndex:1,poiType:[site.LocationType.RESTAURANT]// 指定类型为餐厅};try{// 2. 调用华为 Site Kitletresult=awaitsite.nearbySearch(searchRequest);if(result.sites){// 3. 转换数据格式,用于卡片渲染letfoodList=result.sites.map(item=>{return{name:item.name,address:item.formatAddress,distance:item.distance,// 如果有图片 url,也可以放这里};});returnfoodList;}}catch(err){console.error("Search failed: "+JSON.stringify(err));}return[];}

🖼️ 三、 界面实现:ArkTS 卡片 UI

卡片 UI (Widget) 和普通 Page 的写法略有不同,它更轻量。

FoodCard.ets:

@Entry@Componentstruct FoodCard{// 接收 FormExtensionAbility 传来的数据@LocalStorageProp('foodList')foodList:Array<any>=[];build(){Column(){Text('附近美食推荐').fontSize(14).fontWeight(FontWeight.Bold).padding({left:12,top:10,bottom:5}).width('100%')if(this.foodList.length===0){Text('正在定位中...').fontSize(12).margin(10)}else{// 使用 Grid 布局展示 4 个餐厅Grid(){ForEach(this.foodList,(item:any)=>{GridItem(){Column(){// 模拟餐厅图标Image($r('app.media.icon_food')).width(30).height(30).borderRadius(8)Text(item.name).fontSize(10).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis}).margin({top:4})Text(`${item.distance}m`).fontSize(9).fontColor(Color.Gray)}// 点击事件:拉起主应用,并传递参数.onClick(()=>{postCardAction(this,{action:'router',abilityName:'EntryAbility',params:{targetPage:'MapPage',poiName:item.name,lat:item.location.latitude,lng:item.location.longitude}});}).backgroundColor('#F5F5F5').borderRadius(8).padding(8).width('100%').height(80)}})}.columnsTemplate('1fr 1fr 1fr 1fr')// 4列.columnsGap(8).padding(12)}}.width('100%').height('100%').backgroundColor(Color.White)}}

🗺️ 四、 落地页:Map Kit 导航展示

当用户点击卡片上的餐厅时,跳转到 App 内的MapPage。这里我们需要使用 Map Component 展示具体位置。

MapPage.ets:

import{MapComponent,mapCommon,map}from'@kit.MapKit';@Entry@Componentstruct MapPage{@StatemapController:map.MapComponentController=newmap.MapComponentController();// 从路由参数中获取的目标坐标targetLat:number=0;targetLng:number=0;targetName:string="";aboutToAppear(){// 获取路由参数逻辑 (略)}build(){Stack(){// 地图组件MapComponent({mapOptions:{position:{target:{latitude:this.targetLat,longitude:this.targetLng},zoom:15// 缩放级别}},mapCallback:(err,controller)=>{if(!err){this.mapController=controller;// 地图加载完成后,添加一个标记this.addMarker();}}}).width('100%').height('100%')}}addMarker(){letmarkerOptions:mapCommon.MarkerOptions={position:{latitude:this.targetLat,longitude:this.targetLng},title:this.targetName,clickable:true};this.mapController.addMarker(markerOptions);}}

⚠️ 五、 避坑指南

  1. Client ID 报错:如果你发现地图白屏或者搜索报错 6004/010001,99% 是因为module.json5里的client_id没配对,或者指纹证书(SHA256)没在 AGC 后台录入。
  2. 定位延迟:在卡片上直接做实时定位(GPS)非常耗电且慢。最佳实践是:App 主程序启动时缓存最后一次位置,或者在 FormAbility 的onUpdateForm中使用“上次已知位置”快速刷新,再异步发起精确定位更新。
  3. 模拟器问题:DevEco Studio 的模拟器默认定位可能在海上。记得在模拟器的设置里手动 Mock 一个经纬度(比如深圳坂田)。

🎯 总结

通过Site Kit强大的数据能力和Map Kit的渲染能力,配合鸿蒙的元服务卡片,我们用很低的代码成本,就实现了一个原生级的“周边美食猎手”。

这种“服务找人”的体验,正是 HarmonyOS Next 极力推崇的开发范式。

Next Step:
现在的卡片是静态刷新的。尝试引入ArkTS 卡片动画,当数据加载出来时,给 GridItem 加一个渐入效果,让卡片看起来更灵动!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1159988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言的贝叶斯网络模型的实践

在现代的生态、环境以及地学研究中&#xff0c;变量和变量间的因果关系推断占据了非常重要的地位。在实践中&#xff0c;变量间的因果关系研究往往求助于昂贵的实验&#xff0c;但所得结果又经常与天然环境中的实际因果联系相差甚远。统计学方法是研究天然环境中变量间关系的好…

收藏!5个递进式AI项目,让你从普通开发者跃升15万年薪架构师

AI领域正经历深刻分化&#xff0c;大多数开发者仍构建简单API封装&#xff0c;而市场急需能处理生产级复杂性的系统架构师。两者薪资差距高达15万美元。本文系统介绍5个递进式项目&#xff1a;从入门级移动应用到大师级自主工作流&#xff0c;帮助掌握编排、记忆系统和本地推理…

Bigtreetech M8P + CB2 烧写klipper 详细指南

文章目录烧写前准备烧写系统烧录系统到 eMMC1、下载烧录文件2、确保“烧录前准备完成”3、安装驱动烧录完成后调整参考链接启用Klipper系统&#xff0c;调整配置打开系统串口通讯MobaXterm串口连接&#xff0c;根据图来操作成功连接效果Wifi连接操作记得往CB2上按上天线&#x…

R3nzSkin英雄联盟皮肤修改终极指南:从新手到高手的完整教程

R3nzSkin英雄联盟皮肤修改终极指南&#xff1a;从新手到高手的完整教程 【免费下载链接】R3nzSkin Skin changer for League of Legends (LOL).Everyone is welcome to help improve it. 项目地址: https://gitcode.com/gh_mirrors/r3n/R3nzSkin R3nzSkin是一款功能强大…

通信原理篇---数字通信系统

核心比喻&#xff1a;从“送手写信”到“发电报”还记得模拟通信是 “邮差送手写信” 吗&#xff1f; 数字通信完全不同&#xff0c;它更像是 “发电报”。过程对比&#xff1a;你想说的话&#xff08;比如&#xff1a;“明天9点见面”&#xff09;模拟送信&#xff1a;把这句话…

提示工程架构师实战:用提示工程解决数字化转型中的「数据-业务断层」问题

提示工程架构师实战:用提示工程解决数字化转型中的「数据-业务断层」问题 一、前言:数字化转型的「隐痛」——数据与业务的「平行宇宙」 在过去10年的数字化转型浪潮中,我见过太多企业陷入这样的困境: 数据团队花费数百万搭建了数据仓库/湖,生成了几百张报表,但业务团队…

Verilog 概述

Verilog 概述 Verilog 是一种硬件描述语言&#xff08;Hardware Description Language&#xff0c;HDL&#xff09;&#xff0c;用于描述数字电路的行为和结构。它广泛应用于 FPGA、ASIC&#xff08;专用集成电路&#xff09;的设计流程中。Verilog 的设计流程通常包括设计、仿…

Rust CLI 实战:用 clap + tokio 写一个多线程“m3u8 视频下载器”,速度跑满宽带

标签&#xff1a; #Rust #Tokio #CLI #网络编程 #m3u8 #高性能&#x1f680; 前言&#xff1a;为什么是 Rust&#xff1f; 极速启动&#xff1a;编译成二进制文件&#xff0c;没有任何依赖&#xff0c;即点即用。内存安全&#xff1a;下载几千个分片&#xff0c;不用担心内存泄…

WebAssembly 图像处理:用 Rust 编写 Wasm 模块,在浏览器前端实现“本地图片压缩”

标签&#xff1a; #WebAssembly #Rust #Frontend #ImageProcessing #Wasm #Performance&#x1f4c9; 前言&#xff1a;为什么要用 Wasm 做压缩&#xff1f;方案优点缺点Server 端压缩兼容性好&#xff0c;算法可控浪费上行带宽&#xff0c;服务器 CPU 压力大JS Canvas 压缩简单…

Redis事务相关命令面试必问!

文章目录Redis事务相关的命令有哪几个&#xff1f;什么是 Redis 事务&#xff1f;Redis 事务相关的命令有哪些&#xff1f;第一部分&#xff1a;MULTI —— 开启一个事务示例代码&#xff1a;闫工小贴士&#xff1a;第二部分&#xff1a;EXEC —— 执行事务示例代码&#xff1a…

AgeMem让AI自主管理记忆,性能提升49.59%,超越现有方法8.5%,技术干货必收藏

AgeMem是阿里巴巴与武汉大学团队提出的新型记忆管理系统&#xff0c;将记忆操作通过"工具调用"方式整合进Agent策略中&#xff0c;使Agent能自主决定何时记忆、何时遗忘。该方法采用三阶段渐进式强化学习策略&#xff0c;在多个基准测试上性能提升近50%&#xff0c;显…

Java程序员必看!收藏这篇,AI大模型时代如何突破35岁危机实现自我救赎

Java程序员在AI时代面临技术更新、竞争加剧和年龄焦虑等危机。本文指出AI是赋能工具而非敌人&#xff0c;程序员可通过学习AI技术成为"AIJava"复合型人才。建议从基础概念入手&#xff0c;掌握Python和AI工具&#xff0c;通过实践积累经验&#xff0c;实现从开发者到…

Spring Boot @GetMapping注解:从应用到原理深度解析

在Spring Boot Web开发中&#xff0c;GetMapping是我们最常用的注解之一&#xff0c;它简洁高效地实现了HTTP GET请求与处理器方法的绑定。本文将从「应用实践」和「底层原理」两个核心维度&#xff0c;带你全面掌握这个注解——既会教你如何灵活运用&#xff0c;也会拆解其背后…

从焦虑到逆袭:30岁前端开发者的全栈+AI转型实战,干货路线图建议收藏

文章是一位30岁前端开发者的转型自述&#xff0c;讲述了他在AI时代面临的职业焦虑和转型决心。作者认为纯前端技能在AI冲击下护城河太浅&#xff0c;决定转型"全栈AI独立开发"。他详细规划了三阶段学习路线&#xff1a;第一阶段用Next.jsSupabase突破舒适区&#xff…

计算机就业真相:AI岗位暴涨39.62%,传统开发降温!程序员必看,收藏这篇转型指南

2024-2025年计算机就业呈现"冷热分化"现象&#xff1a;AI相关岗位需求暴增(机器学习工程师涨39.62%)&#xff0c;传统开发岗位需求下降。AI不是替代程序员&#xff0c;而是筛选工具&#xff0c;淘汰只会写重复代码的人&#xff0c;留下会用AI提效的人。未来"AI技…

7年前端老鸟的崩溃时刻:AI一天写完我一周的代码,收藏这篇焦虑自救指南

一位7年前端开发者分享使用AI完成项目的震撼经历&#xff0c;表达对职业价值危机的焦虑。AI技术迅猛发展&#xff0c;能快速生成代码&#xff0c;让传统编程技能面临挑战。作者尝试通过跳槽、写博客等方式应对&#xff0c;但仍对未来不确定。文章引发技术人员思考&#xff1a;在…

2026必备!本科生论文难题TOP10 AI论文平台测评

2026必备&#xff01;本科生论文难题TOP10 AI论文平台测评 2026年本科生论文写作工具测评&#xff1a;如何选择高效助手 随着人工智能技术的不断进步&#xff0c;越来越多的本科生开始借助AI论文平台来提升写作效率、优化内容质量。然而&#xff0c;面对市场上琳琅满目的工具&a…

解锁AI原生应用与向量数据库的协同奥秘

解锁AI原生应用与向量数据库的协同奥秘 关键词:AI原生应用、向量数据库、向量嵌入、相似度检索、多模态AI 摘要:当AI从“工具”进化为“原生能力”,当数据从“表格”变为“高维向量”,一场关于智能应用的革命正在发生。本文将用“奶茶店点单”“图书馆找书”等生活化案例,…

python基于flask框架的大学生英语四六级学习平台的设计与实现

目录大学生英语四六级学习平台的设计与实现&#xff08;基于Flask框架&#xff09;开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;大学生英语四六级学习平台的设计与实现&#xff08;基于Fl…

告别冗长Prompt!Skills才是AI Agent的真正核心,程序员必收藏

文章探讨AI Agent中Skill的价值&#xff0c;将其分为格式转换型和隐性知识型两类。Skill本质上是Prompt中能力层的外置化&#xff0c;实现模块化维护。其核心价值在于治理调度、渐进式披露、固化版本和沉淀隐性经验。当任务重复、边界清晰、质量敏感或上下文拥挤时&#xff0c;…