
回复
在鸿蒙应用开发中,经常需要跳转第三方地图应用(如 腾讯地图、百度地图、高德地图)进行导航。无论是出行类 App、物流类 App,还是线下活动类应用,都存在“跳转地图导航”的实际需求。写完HarmonyOS应用拉起系列一和二后在鸿蒙开发者社区以及各类技术问答平台上很多开发者都在询问:如何实现直接拉起导航应用。本文结合拉起系列一和实战代码,讲解如何封装 MapNavigator 工具类,实现:
qqmap://
、baidumap://
、amapuri://
),在拉起地图前先判断 App 是否存在,避免跳转失败。需要注意,这些 scheme 必须在 module.json5
的 querySchemes
字段中声明,否则 canOpenLink
会返回错误或不准确的结果。startAbilityByWant
:通过构建 Want
对象携带导航参数,包括起点名称、起点经纬度、终点名称、终点经纬度、导航模式(驾车、步行、公交等)等,精确传递给第三方地图 App。openLink
:通过 URL scheme 拼接导航参数,直接拉起地图应用进行导航,同样支持传递起终点坐标、路线偏好等信息。promptAction.showToast
)告知用户“腾讯地图/百度地图/高德地图未安装”,同时可扩展为引导用户前往应用市场下载。module.json5
中声明了对应的 scheme,鸿蒙系统才能正确识别并允许通过 canOpenLink
或 openLink 拉起第三方 App,否则即便 App 已安装,也会出现“暂无打开方式”的提示。通过封装,开发者只需调用相应方法并传入 起点、终点名称与经纬度,就能轻松实现多地图导航功能,避免重复实现安装判断、参数拼接和异常处理逻辑。
在鸿蒙中,判断应用是否安装通常依赖 bundleManager.canOpenLink(scheme)
。必须在自己应用的 module.json5
中配置对应的 scheme,否则即使应用安装了,也可能返回 false。
示例配置:
"module": {
"querySchemes": [
"qqmap",
"baidumap",
"amapuri"
]
}
qqmap
, baidumap
, amapuri
对应三方地图的 scheme。配置错误是
canOpenLink
返回 false 的常见原因。
封装思路:
export enum MapApp {
TENCENT = 'com.tencent.mapohos',
BAIDU = 'com.baidu.hmmap',
AMAP = 'com.amap.hmapp'
}
export enum MapScheme {
TENCENT = 'qqmap://',
BAIDU = 'baidumap://',
AMAP = 'amapuri://'
}
private isMapInstalled(scheme: string): boolean {
try {
return bundleManager.canOpenLink(scheme);
} catch (err) {
console.error(`canOpenLink failed for ${scheme}`, JSON.stringify(err));
return false;
}
}
querySchemes
中声明,否则返回 false。if (!this.isMapInstalled(MapScheme.TENCENT)) {
this.showNotInstalledMsg('腾讯地图');
}
async openTencentMapByWant(from: string, fromLat: number, fromLng: number,
to: string, toLat: number, toLng: number) {
if (!this.isMapInstalled(MapScheme.TENCENT)) {
this.showNotInstalledMsg('腾讯地图');
return;
}
const want: Want = {
action: 'ohos.want.action.viewData',
uri: `qqmap://map/routeplan?type=drive` +
`&from=${from}&fromcoord=${fromLat},${fromLng}` +
`&to=${to}&tocoord=${toLat},${toLng}` +
`&policy=0&referer=myApp`
};
this.openMethod.startAbilityByWant(want);
}
注意:百度地图在鸿蒙上暂时不支持
canOpenLink
判断,可直接尝试拉起。
async openTencentMapByLink(from: string, fromLat: number, fromLng: number,
to: string, toLat: number, toLng: number) {
if (!this.isMapInstalled(MapScheme.TENCENT)) {
this.showNotInstalledMsg('腾讯地图');
return;
}
const url = `qqmap://map/routeplan?type=drive` +
`&from=${from}&fromcoord=${fromLat},${fromLng}` +
`&to=${to}&tocoord=${toLat},${toLng}` +
`&policy=0&referer=myApp`;
this.openMethod.openLink(url);
}
private showNotInstalledMsg(appName: string) {
promptAction.showToast({ message: `${appName} 未安装` });
}
// 拉起腾讯地图导航
Button('拉起腾讯地图-ByLink').onClick((event: ClickEvent) => {
this.mapNavigator.openTencentMapByLink('我的位置', 39.908823, 116.397470, '天安门', 39.915156, 116.403694)
})
// 拉起百度地图导航
Button('拉起百度地图-ByLink').onClick((event: ClickEvent) => {
this.mapNavigator.openBaiduMapByLink('我的位置', 39.908823, 116.397470, '天安门', 39.915156, 116.403694)
})
// 拉起高德地图导航
Button('拉起高德打车-ByLink').onClick((event: ClickEvent) => {
this.mapNavigator.openAmapByLink('我的位置', 39.908823, 116.397470, '天安门', 39.915156, 116.403694)
})
// 拉起腾讯地图导航
Button('拉起腾讯地图-ByWant').onClick((event: ClickEvent) => {
this.mapNavigator.openTencentMapByWant('我的位置', 39.908823, 116.397470, '天安门', 39.915156, 116.403694)
})
// 拉起百度地图导航
Button('拉起百度地图-ByWant').onClick((event: ClickEvent) => {
this.mapNavigator.openBaiduMapByWant('我的位置', 39.908823, 116.397470, '天安门', 39.915156, 116.403694)
})
// 拉起高德地图导航
Button('拉起高德打车-ByWant').onClick((event: ClickEvent) => {
this.mapNavigator.openAmapByWant('我的位置', 39.908823, 116.397470, '天安门', 39.915156, 116.403694)
})
canOpenLink
失效。通过这种封装方式,业务逻辑只需关注 起点、终点,不必关心每个地图应用的调用差异,极大提高了开发效率与可维护性,以上示例代码和封装逻辑已在 真机上 测试通过,如有异常或适配问题,欢迎大家在 Issues 中提出,我们将持续优化并补充更多地图应用和导航参数的支持。如果大家喜欢或者对这个系列感兴趣欢迎大家在评论区交流讨论。
望一键三连!