在 HarmonyOS 地图应用开发中,POI(兴趣点)搜索与路径规划是支撑出行、本地生活等核心场景的关键能力。例如,打车 App 需通过 POI 搜索快速定位乘客上车点,导航软件需根据用户选择的出行方式生成最优路线。这篇文章我将基于华为地图 SDK,从功能原理、开发实现、场景优化三方面,拆解 POI 搜索与路径规划的全流程,希望可以帮助大家弄清楚其中的流程。
文章目录
- [一、POI 搜索:从关键词到精准定位](#一、POI 搜索:从关键词到精准定位)
-
- [1. 开发准备:配置依赖与权限](#1. 开发准备:配置依赖与权限)
-
- [(1)集成 SDK 与配置密钥](#(1)集成 SDK 与配置密钥)
- (2)声明必要权限
- [2. 三种 POI 搜索实现方案](#2. 三种 POI 搜索实现方案)
-
- (1)关键词搜索:按名称匹配兴趣点
- (2)周边搜索:基于当前位置找周边设施
- [(3)范围搜索:指定矩形区域内找 POI](#(3)范围搜索:指定矩形区域内找 POI)
- [3. POI 搜索优化技巧](#3. POI 搜索优化技巧)
- 二、路径规划:多出行方式的路线生成
-
- [1. 路径规划核心概念](#1. 路径规划核心概念)
- [2. 驾车路线规划实现(最常用场景)](#2. 驾车路线规划实现(最常用场景))
- [3. 其他出行方式路线规划(步行 / 骑行 / 公交)](#3. 其他出行方式路线规划(步行 / 骑行 / 公交))
- [4. 路径规划可视化与交互优化](#4. 路径规划可视化与交互优化)
- [三、POI 搜索与路径规划的联动场景](#三、POI 搜索与路径规划的联动场景)
- 四、常见问题与解决方案
-
-
- [POI 搜索结果为空:](#POI 搜索结果为空:)
- 路径规划路线不符合预期:
- 接口调用频繁导致限流:
-
- 五、总结
一、POI 搜索:从关键词到精准定位
POI 搜索本质是通过关键词、地理范围等条件,从地图服务数据库中筛选出符合需求的兴趣点(如餐厅、加油站、医院等),并返回其名称、地址、坐标等信息。华为地图 SDK 提供了 "关键词搜索""周边搜索""范围搜索" 三种核心能力,覆盖不同业务场景。
1. 开发准备:配置依赖与权限
(1)集成 SDK 与配置密钥
延续地图基础功能开发流程,需在工程中导入华为地图 SDK 的map-sdk.har包,并在build.gradle中添加依赖。同时,在AbilitySlice初始化时配置 API 密钥,确保服务鉴权通过:
bash
// 初始化地图配置,设置API密钥
MapConfig.getInstance().setApiKey("你的华为地图API密钥");
(2)声明必要权限
POI 搜索依赖网络获取远程数据,需在config.json中添加网络权限,若需结合当前位置实现 "周边搜索",还需补充位置权限:
bash
"reqPermissions": [
{
"name": "ohos.permission.INTERNET" // 网络权限(必选)
},
{
"name": "ohos.permission.LOCATION" // 位置权限(周边搜索需选)
}
]
2. 三种 POI 搜索实现方案
(1)关键词搜索:按名称匹配兴趣点
适用于 "搜索指定名称地点" 场景(如用户输入 "北京故宫" 查找具体位置),通过TextSearch类实现,核心是设置关键词与搜索区域范围:
bash
// 1. 创建关键词搜索实例
TextSearch textSearch = new TextSearch(this);
// 2. 构建搜索参数
TextSearchRequest request = new TextSearchRequest();
request.setQuery("北京故宫"); // 搜索关键词
request.setRegion("北京"); // 限定搜索区域(减少无关结果)
request.setPageSize(10); // 每页返回结果数
request.setPageNum(1); // 当前页码(分页加载用)
// 3. 发起搜索并处理结果
textSearch.search(request, new SearchResultListener<TextSearchResponse>() {
@Override
public void onSearchResult(TextSearchResponse response) {
// 搜索成功:解析POI列表
List<PoiItem> poiItems = response.getPoiList();
if (poiItems != null && !poiItems.isEmpty()) {
for (PoiItem poi : poiItems) {
String poiName = poi.getName(); // POI名称(如"北京故宫博物院")
String poiAddress = poi.getAddress(); // POI地址(如"东城区景山前街4号")
LatLng poiLatLng = poi.getLatLng(); // POI坐标(纬度+经度)
// 将POI信息添加到列表展示,或在地图上标记
addPoiMarkerToMap(poiLatLng, poiName);
}
}
}
@Override
public void onSearchError(SearchError error) {
// 搜索失败:处理错误(如网络异常、关键词无效)
LogUtil.error("POI搜索失败:" + error.getErrorMessage());
}
});
(2)周边搜索:基于当前位置找周边设施
适用于 "查找附近服务" 场景(如用户在商场附近找餐厅、加油站),需结合设备当前坐标,通过NearbySearch类实现:
bash
// 1. 获取设备当前位置(需先申请位置权限并初始化定位)
LatLng currentLatLng = getCurrentDeviceLocation(); // 自定义方法:获取当前坐标
// 2. 创建周边搜索实例
NearbySearch nearbySearch = new NearbySearch(this);
// 3. 构建搜索参数:中心坐标+半径+POI类型
NearbySearchRequest request = new NearbySearchRequest();
request.setLocation(currentLatLng); // 搜索中心(当前位置)
request.setRadius(1000); // 搜索半径(单位:米,此处为1公里)
request.setPoiType("餐饮服务"); // POI类型(支持"加油站""医院""商场"等)
request.setPageSize(15);
// 4. 发起搜索并处理结果(回调逻辑与关键词搜索类似)
nearbySearch.search(request, new SearchResultListener<NearbySearchResponse>() {
@Override
public void onSearchResult(NearbySearchResponse response) {
List<PoiItem> nearbyPoi = response.getPoiList();
// 解析POI信息并展示(如在列表中显示"距离当前位置XX米")
showNearbyPoiList(nearbyPoi, currentLatLng);
}
@Override
public void onSearchError(SearchError error) {
LogUtil.error("周边搜索失败:" + error.getErrorCode());
}
});
(3)范围搜索:指定矩形区域内找 POI
适用于 "限定区域内筛选" 场景(如用户在地图上框选某块区域,查找该区域内的学校),通过BoundSearch类实现,核心是设置矩形区域的对角坐标:
bash
// 1. 定义矩形区域(左上角+右下角坐标,示例:北京市某区域)
LatLng leftTop = new LatLng(39.95, 116.35); // 左上角坐标
LatLng rightBottom = new LatLng(39.90, 116.45); // 右下角坐标
BoundingBox bound = new BoundingBox(leftTop, rightBottom);
// 2. 创建范围搜索实例
BoundSearch boundSearch = new BoundSearch(this);
// 3. 构建搜索参数
BoundSearchRequest request = new BoundSearchRequest();
request.setBoundingBox(bound); // 限定矩形区域
request.setPoiType("学校"); // 搜索"学校"类型POI
// 4. 发起搜索(回调逻辑同上)
boundSearch.search(request, new SearchResultListener<BoundSearchResponse>() {
// 结果处理逻辑...
});
3. POI 搜索优化技巧
结果去重:部分 POI 可能存在重复(如同一建筑的不同入口),可通过对比PoiItem的getPoiId()去重;
联想提示:在用户输入关键词时,通过SuggestionSearch类实现实时联想(如输入 "北" 时提示 "北京故宫""北京大学"),提升输入效率;
缓存策略:对高频搜索结果(如用户常用地址)进行本地缓存,下次搜索时优先读取缓存,减少网络请求。
二、路径规划:多出行方式的路线生成
路径规划是根据起点、终点、途经点及出行方式(步行、驾车、公共交通),计算出最优路线,并返回路线距离、预计时间、转向提示等信息。华为地图 SDK 支持四种核心出行方式,满足不同场景需求。
1. 路径规划核心概念
在实现前需明确三个关键参数:
起点 / 终点:通常为LatLng坐标(可通过 POI 搜索获取,或直接使用设备当前位置);
出行方式:SDK 支持RouteSearchMode.WALKING(步行)、DRIVING(驾车)、TRANSIT(公共交通)、RIDING(骑行)四种;
路线偏好:驾车路线可设置偏好(如 "最短距离""最快时间""躲避拥堵"),步行 / 骑行路线默认优先 "最短路径"。
2. 驾车路线规划实现(最常用场景)
以 "从北京故宫到天安门广场" 的驾车路线规划为例,核心步骤如下:
bash
// 1. 定义起点、终点坐标(可通过POI搜索获取)
LatLng startPoint = new LatLng(39.916527, 116.397128); // 北京故宫坐标
LatLng endPoint = new LatLng(39.908823, 116.397470); // 天安门广场坐标
// 2. 创建路径搜索实例
RouteSearch routeSearch = new RouteSearch(this);
// 3. 构建驾车路线规划参数
DriveRouteSearchRequest request = new DriveRouteSearchRequest();
// 设置起点、终点
request.setOrigin(new SearchLocation(startPoint));
request.setDestination(new SearchLocation(endPoint));
// 设置路线偏好:最快时间(默认),可选"最短距离"(ROUTE_TYPE_SHORTEST)
request.setRouteType(DriveRouteType.ROUTE_TYPE_FASTEST);
// 是否避开高速:0-不避开,1-避开
request.setAvoidHighway(0);
// 4. 发起驾车路线搜索
routeSearch.searchDriveRoute(request, new SearchResultListener<DriveRouteSearchResponse>() {
@Override
public void onSearchResult(DriveRouteSearchResponse response) {
if (response == null || response.getRouteList() == null) return;
// 获取最优路线(通常取第一条)
DriveRouteResult optimalRoute = response.getRouteList().get(0);
// 解析路线核心信息
double routeDistance = optimalRoute.getDistance() / 1000; // 路线距离(公里)
int routeTime = optimalRoute.getDuration() / 60; // 预计时间(分钟)
List<DriveStep> driveSteps = optimalRoute.getSteps(); // 转向步骤列表
// 1. 在地图上绘制路线(使用Polyline绘制路线折线)
drawDriveRouteOnMap(optimalRoute.getPath());
// 2. 展示路线信息(如在页面顶部显示"距离2.5公里,预计15分钟")
showRouteInfo(routeDistance, routeTime);
// 3. 展示转向提示(如"100米后右转进入东长安街")
showDriveSteps(driveSteps);
}
@Override
public void onSearchError(SearchError error) {
LogUtil.error("驾车路线规划失败:" + error.getErrorMessage());
}
});
3. 其他出行方式路线规划(步行 / 骑行 / 公交)
(1)步行路线规划
与驾车规划逻辑类似,只需将请求类型改为WalkRouteSearchRequest:
bash
// 构建步行路线参数
WalkRouteSearchRequest request = new WalkRouteSearchRequest();
request.setOrigin(new SearchLocation(startPoint));
request.setDestination(new SearchLocation(endPoint));
// 发起步行路线搜索
routeSearch.searchWalkRoute(request, new SearchResultListener<WalkRouteSearchResponse>() {
@Override
public void onSearchResult(WalkRouteSearchResponse response) {
// 解析步行路线:距离、时间、步行步骤(如"沿景山前街向东步行300米")
WalkRouteResult walkRoute = response.getRouteList().get(0);
// 绘制步行路线(通常用虚线表示)
drawWalkRouteOnMap(walkRoute.getPath());
}
});
(2)公交路线规划(含地铁、公交)
公交路线需处理多段换乘(如 "公交 + 地铁"),需解析TransitRouteResult中的Segments(路段)信息:
bash
// 构建公交路线参数
TransitRouteSearchRequest request = new TransitRouteSearchRequest();
request.setOrigin(new SearchLocation(startPoint));
request.setDestination(new SearchLocation(endPoint));
request.setTransitType(TransitType.ALL); // 包含公交+地铁
// 发起公交路线搜索
routeSearch.searchTransitRoute(request, new SearchResultListener<TransitRouteSearchResponse>() {
@Override
public void onSearchResult(TransitRouteSearchResponse response) {
TransitRouteResult transitRoute = response.getRouteList().get(0);
// 解析换乘路段(如"地铁1号线:天安门东站→西单站")
List<TransitSegment> segments = transitRoute.getSegments();
for (TransitSegment segment : segments) {
String segmentType = segment.getSegmentType(); // 路段类型:地铁/公交/步行
String lineName = segment.getLineName(); // 线路名称(如"地铁1号线")
// 展示换乘信息
}
}
});
4. 路径规划可视化与交互优化
路线绘制:使用Polyline类在地图上绘制路线,通过不同颜色区分出行方式(如驾车用蓝色、步行用绿色);
途经点添加:支持用户添加多个途经点(通过setWayPoints方法),满足 "多点导航" 需求(如 "家→超市→公司");
实时路况更新:驾车路线可结合TrafficLayer类显示实时路况(红色 = 拥堵、黄色 = 缓行、绿色 = 畅通),动态调整路线。
三、POI 搜索与路径规划的联动场景
在实际应用中,POI 搜索与路径规划常结合使用,形成完整业务流程。以 "外卖配送" 场景为例,完整流程如下:
用户输入地址:通过 POI 关键词搜索,匹配用户填写的 "XX 小区 3 号楼",获取精准坐标作为终点;
获取配送员位置:通过定位服务获取配送员当前位置,作为起点;
生成配送路线:基于 "骑行" 方式规划从配送员位置到用户地址的路线,计算预计送达时间;
实时更新路线:若配送途中遇到道路封闭,通过RouteSearch重新规划路线,并同步更新预计时间。
核心联动代码示例:
bash
// 1. POI搜索获取用户地址(终点)
searchPoiByKeyword("XX小区3号楼", new PoiSearchCallback() {
@Override
public void onPoiFound(LatLng endPoint) {
// 2. 获取配送员当前位置(起点)
LatLng startPoint = getCourierLocation();
// 3. 生成骑行路线
planRidingRoute(startPoint, endPoint, new RoutePlanCallback() {
@Override
public void onRouteGenerated(RidingRouteResult route) {
// 4. 展示路线与预计时间
showRouteAndTime(route);
}
});
}
});
四、常见问题与解决方案
POI 搜索结果为空:
检查关键词是否准确(如 "京故宫" 应改为 "北京故宫");
确认搜索区域范围是否合理(如周边搜索半径过小);
验证 API 密钥是否有效,且已开通 "POI 搜索" 服务权限。
路径规划路线不符合预期:
检查起点 / 终点坐标是否正确(避免经纬度颠倒);
调整路线偏好(如驾车路线从 "最快时间" 改为 "最短距离");
若公交路线缺失,确认该区域是否有公交数据覆盖。
接口调用频繁导致限流:
对 POI 搜索、路径规划接口添加调用频率限制(如同一用户 10 秒内最多发起 3 次请求);
使用 SDK 的 "批量搜索" 接口(如BatchSearch),减少单次请求数量。
五、总结
POI 搜索与路径规划是 HarmonyOS 地图应用的核心能力,通过华为地图 SDK 可快速实现多场景下的功能集成。开发时需注意:
优先基于 SDK 封装的 API 实现基础功能,减少自定义开发成本;
结合业务场景选择合适的 POI 搜索方式与路径规划类型,如外卖场景用 "骑行路线"、打车场景用 "驾车路线";
注重用户体验优化,如 POI 联想提示、路线实时路况、错误友好提示等。
通过本文的流程拆解与代码示例,开发者可高效完成 POI 搜索与路径规划的集成,并根据实际需求进行功能扩展,打造流畅、精准的地图服务体验。