给鸿蒙 App 增加一键唤起地图导航的能力 —— maps_launcher 的鸿蒙使用指南

本文配套仓库:https://atomgit.com/oh-flutter/maps_launcher(TAG:3.0.0-ohos-1.0.0-beta.1,分支:feat/ohos_maps_launcher_3.0.0),文中示例代码位于仓库 example/ 目录。

把用户从应用内一步带到地图应用,是线下门店、外卖配送、出行类应用的高频需求:搜一个地点、看一处坐标、唤起导航。鸿蒙应用同样需要这个能力。本文介绍如何使用鸿蒙化适配后的 Flutter 三方库 maps_launcher,用两个静态方法在鸿蒙 App 内拉起系统导航应用选择面板,由用户在已安装的地图应用中直接选择,并附上 HUAWEI nova 12 Ultra 真机的完整实测记录。

一、最终运行效果

应用启动后输入地点关键词,点击 launchQuery:搜索地点 按钮,系统弹出导航应用选择面板,选择花瓣地图直达搜索结果:

验证点结果
应用启动,Flutter 页面正常渲染通过
点击 launchQuery 按钮,系统弹出导航应用选择面板通过
面板中选择花瓣地图,正常进入其搜索结果页通过
点击 launchCoordinates 按钮,系统提示"暂无可用导航方式",返回 true符合预期(见 FAQ Q1)

在这里插入图片描述

图一:demo 应用在 HUAWEI nova 12 Ultra 真机启动(HarmonyOS 6.1.0 / API 24)

在这里插入图片描述

图二:点击 launchQuery 后系统弹出导航应用选择面板,列出设备上已安装的地图应用

在这里插入图片描述

图三:在面板中选择花瓣地图,直达"上海东方明珠"的搜索结果页

检查要点

  1. 导航应用选择面板由系统 startAbilityByType('navigation') 弹出,属于系统能力,插件与业务方都无需申请任何权限;
  2. 面板中出现哪些应用,由各地图应用自身声明的 linkFeature 决定(详见"七、工作原理"与 FAQ Q1);
  3. 完整实测过程见"六、运行与验证"。

二、maps_launcher 是什么

maps_launcher 原库(pub.dev 3.0.0+1,作者 pikaju)是一个打开设备上地图应用的 Flutter 插件,支持按名称搜索地点与按坐标展示目的地。鸿蒙适配版在其基础上新增了 OpenHarmony / HarmonyOS 平台支持:拉起系统导航应用选择面板,由用户选择导航应用。

几个对使用者友好的特点:

  1. 零权限:面板由系统能力拉起,不需要在 module.json5 中申请任何权限;
  2. 不绑定单一地图:不像深链方案把用户固定在某个地图 App,而是由系统列出设备上已安装的地图应用,交给用户选择;
  3. 跨平台一套代码:Android、iOS、鸿蒙、桌面与 Web 共用同一对接口,运行在哪端就按哪端的方式打开地图。

接口说明:

名称描述类型参数类型返回值必填鸿蒙平台支持
MapsLauncher.launchQuery打开地图应用并展示搜索结果methodquery: StringFuture<bool>
MapsLauncher.launchCoordinates打开地图应用并展示指定坐标methodlatitude: double, longitude: double, [label: String?]Future<bool>

三、环境准备

本文所有实测均在以下环境完成:

版本说明
Flutter(ohos 版)3.41.10-ohos-1.0.1主验证环境,真机实测
编译 SDK6.1.0(23)宿主工程 compatibleSdkVersion 同值,保留带括号的旧格式
真机HUAWEI nova 12 Ultra(ADA-AL10)HarmonyOS 6.1.0.135 / API 24,分辨率 1224 × 2776

两点提醒:

  1. 编译鸿蒙目标需要使用 ohos 版 Flutter SDK,普通 Flutter SDK 无法编译 ohos 产物;
  2. 若在真机上安装应用报"此应用暂不支持在当前设备安装",是宿主工程的 compatibleSdkVersion 高于设备 API 导致的,与插件无关,处理方式见 FAQ Q4。

四、引入依赖

进入工程目录,在 pubspec.yaml 中添加 git 依赖:

dependencies:
  maps_launcher:
    git:
      url: https://atomgit.com/oh-flutter/maps_launcher.git
      # ref: 根据下方表格选择不同框架适配的 TAG 版本
      ref: 3.0.0-ohos-1.0.0-beta.1

执行命令拉取依赖:

flutter pub get

TAG 命名规则:原库版本-ohos-版本号-beta.x

Flutter 框架版本TAG 名称分支名
3.443.0.0-ohos-1.0.0-beta.1feat/ohos_maps_launcher_3.0.0

说明:该 TAG 已在 3.41 系 stable(3.41.10-ohos-1.0.1)真机上实测通过,3.41 用户可直接使用;3.44 canary 引擎的 ArkTS 层要求 API 26,需将宿主工程 compatibleSdkVersion 调整为 26.0.0(见 FAQ Q5)。

五、代码接入

5.1 导入库

import 'package:maps_launcher/maps_launcher.dart';

5.2 按名称搜索地点

final ok = await MapsLauncher.launchQuery('上海东方明珠');

query 是自由文本,地点名称或地址均可。在鸿蒙设备上,它作为目的地搜索文本进入系统导航面板,用户选择某个地图应用后即看到对应的搜索结果。

5.3 展示指定坐标

final ok = await MapsLauncher.launchCoordinates(31.239717, 121.499876, '上海陆家嘴');

latitudelongitude 为必填的经纬度,可选参数 label 作为目的地名称展示。

坐标系提醒:鸿蒙导航面板在中国大陆要求 GCJ-02 坐标系,而原库未对输入坐标系作约定(实际通常为 WGS-84)。在中国大陆启动坐标导航前,建议先完成 WGS-84 到 GCJ-02 的转换,避免数百米级的偏差;中国大陆以外的坐标将原样透传(详见 FAQ Q3)。

5.4 跨平台一套代码

同一对接口在各端的行为:

平台行为
Android打开匹配 geo: URI 的地图应用
iOS打开 Apple Maps
OpenHarmony / HarmonyOS拉起系统导航应用选择面板,由用户选择导航应用
桌面端与 Web通过浏览器打开 Google Maps

两个方法在拉起成功时返回 true,失败时返回 false

5.5 实战:给门店详情页加一个"导航到这里"按钮

实际业务中常见的场景是门店、餐厅、网点的详情页放一个常驻的"导航到这里"按钮。下面是一个可直接使用的组件:

import 'package:flutter/material.dart';
import 'package:maps_launcher/maps_launcher.dart';

class NavigateButton extends StatelessWidget {
  const NavigateButton({
    super.key,
    required this.latitude,
    required this.longitude,
    this.label,
  });

  final double latitude;
  final double longitude;
  final String? label;

  
  Widget build(BuildContext context) {
    return FilledButton.icon(
      icon: const Icon(Icons.navigation),
      label: const Text('导航到这里'),
      onPressed: () async {
        final ok = await MapsLauncher.launchCoordinates(latitude, longitude, label);
        if (!context.mounted || ok) return;
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('未找到可用的地图应用,请先安装')),
        );
      },
    );
  }
}

面板未拉起、设备上没有可用地图应用时返回 false,业务可据此降级提示;返回值的完整语义见 FAQ Q2。

六、运行与验证

以下为 demo 工程的真机实测记录。仓库中 example 的 Bundle Name 为 com.example.example;本轮测试时签名配置临时使用了包名 com.example.demo,仅影响安装包标识、不影响功能验证,仓库已还原为 com.example.example

设备项
机型HUAWEI nova 12 Ultra(ADA-AL10)
系统版本HarmonyOS 6.1.0.135(SP8C00E120R2P6)
API 版本24
分辨率1224 × 2776

6.1 验证一:launchQuery 位置搜索

安装、启动 demo 并模拟点击:

# 构建 hap 后安装(真机安装对 SDK 版本有要求,见 FAQ Q4)
hdc install entry-default-signed.hap

# 启动 demo
hdc shell aa start -b com.example.demo -a EntryAbility

# 模拟点击 launchQuery 按钮(坐标按实际设备与页面布局调整)
hdc shell uitest uiInput click 611 1227

# 在弹出的系统面板中选择花瓣地图
hdc shell uitest uiInput click 611 2249

实测现象与图一、图二、图三一致:Flutter 页面正常渲染;点击 launchQuery 后系统弹出导航应用选择面板,列出设备上已安装的地图应用;选择花瓣地图后正常进入"上海东方明珠"的搜索结果页。

6.2 验证二:launchCoordinates 地点详情

重新拉起 demo,模拟点击坐标按钮:

# 重新启动 demo
hdc shell aa start -b com.example.demo -a EntryAbility

# 模拟点击 launchCoordinates 按钮
hdc shell uitest uiInput click 611 1807

在这里插入图片描述

图四:点击 launchCoordinates 后系统提示"暂无可用导航方式",设备上的地图应用均未声明 DetailLocation 能力,面板无可选应用

系统提示"暂无可用导航方式",而接口返回值为 true:拉起动作本身已由系统完成,只是面板内没有声明 DetailLocation 能力的应用可选。这是设备应用生态的现状,不是插件缺陷,机制解释见 FAQ Q1。

实测结论:

验证点结果
应用启动,Flutter 页面正常渲染通过
点击 launchQuery,系统弹出导航应用选择面板通过
面板中选择花瓣地图,正常进入其搜索结果页通过
点击 launchCoordinates,系统提示"暂无可用导航方式",返回 true符合预期(见 FAQ Q1)
全程无需申请任何权限通过

七、工作原理

整个调用链路如下:

Dart: MapsLauncher.launchQuery / launchCoordinates
  → MethodChannel('maps_launcher')
    → ArkTS: MapsLauncherPlugin.onMethodCall
      → 组装 wantParam 并 startAbilityByType('navigation')
        → 系统弹出导航应用选择面板

Dart 侧通过 Platform.operatingSystem == 'ohos' 识别鸿蒙平台:鸿蒙上走 MethodChannel 调用原生插件,其余平台沿用原库的 url_launcher 逻辑。

鸿蒙侧通过 startAbilityByType('navigation')sceneType 区分场景:

sceneType场景必填参数对应接口
3位置搜索destinationNamelaunchQuery
4地点详情destinationLatitude、destinationLongitudelaunchCoordinates

系统还定义了路线规划(sceneType 1)与导航(sceneType 2)等场景,当前适配未覆盖,欢迎扩展(见 FAQ Q6)。

鸿蒙侧插件实现(ArkTS)核心有两段。一段是按接口组装 wantParam,以 launchQuery 为例:

case 'launchQuery': {
  const query: string | undefined = call.argument('query');
  // 位置搜索场景(sceneType: 3):destinationName 为搜索关键字(必填)
  const wantParam: Record<string, Object> = {
    'sceneType': 3,
    'destinationName': query
  };
  this.startNavigationAbility(wantParam, result);
  break;
}

另一段是发起拉起并回传结果。MethodResult 只允许回复一次,而 startAbilityByType 的异步回调(onError/onResult)与同步 AsyncCallback 可能先后触发,replyOnce 保证 Future<bool> 恰好 resolve 一次:

let replied: boolean = false;
const replyOnce = (value: boolean): void => {
  if (!replied) { replied = true; result.success(value); }
};
const abilityStartCallback: common.AbilityStartCallback = {
  onError: (code: number, name: string, message: string) => { replyOnce(false); },
  onResult: (abilityResult: common.AbilityResult) => { replyOnce(true); }
};
try {
  context.startAbilityByType('navigation', wantParam, abilityStartCallback, (err: BusinessError) => {
    if (err) { replyOnce(false); } else { replyOnce(true); }
  });
} catch (err) { replyOnce(false); }

面板中出现哪些应用,由各地图应用在自身 module.json5 的 skills.uris 中声明的 linkFeature 决定(Navigation、RoutePlan、PlaceSearch、DetailLocation 四类)。实测设备上已安装的地图应用均声明了 PlaceSearch,因此 launchQuery 的面板能正常列出它们;但均未声明 DetailLocation,launchCoordinates 便提示"暂无可用导航方式"。

八、常见问题

Q1:launchCoordinates 提示"暂无可用导航方式"是怎么回事?

面板内可选哪些应用由各地图应用声明的 linkFeature 决定。实测设备上的地图应用只声明了 PlaceSearch(位置搜索)能力,未声明 DetailLocation(地点详情)能力,所以搜索场景一切正常、坐标详情场景没有可选应用。此时拉起动作本身已完成,接口返回 true。随着地图应用逐步补齐 linkFeature 声明,该场景会自然可用。

Q2:返回 true 就代表地图应用被打开了吗?

true 表示"拉起动作成功完成"(系统回调确认),不保证面板里有应用可选,也不代表某个具体地图应用完成了展示。对可用性敏感的业务,建议结合自身目标场景做功能实测(参考 Q1)。

Q3:中国大陆的坐标为什么偏了几百米?

坐标系问题。鸿蒙导航面板在中国大陆要求 GCJ-02,而多数业务数据(尤其来自 GPS 或国际地图服务)是 WGS-84。在中国大陆启动坐标导航前先做 WGS-84 到 GCJ-02 的转换;中国大陆以外的坐标原样透传即可。

Q4:真机安装 demo 时提示"此应用暂不支持在当前设备安装"?

这是宿主工程的 compatibleSdkVersion 高于真机 API 版本导致的安装校验失败,与插件无关。将 compatibleSdkVersion 调整为不高于真机 API 的版本(如 6.1.0(23),注意保留带括号的旧格式)即可。本文配套仓库的 example 已用此配置在 nova 12 Ultra(API 24)上安装实测通过。

Q5:用 3.44 canary 构建时报 API 版本错误?

3.44 canary 引擎的 ArkTS 层要求 API 26,需将宿主工程 compatibleSdkVersion 改为 26.0.0。本文实测使用的 3.41.10-ohos-1.0.1 搭配 6.1.0(23) 即可在 API 24 真机运行。

Q6:想直接拉起路线规划或导航怎么办?

系统面板还定义了路线规划(sceneType 1)与导航(sceneType 2)等场景,当前适配覆盖位置搜索与地点详情两类。如业务需要,可参考"七、工作原理"扩展 wantParam,欢迎提 PR 共建。

九、结语

回顾一下:在 pubspec.yaml 中以 git TAG 引入 maps_launcher,调用 MapsLauncher.launchQuery()MapsLauncher.launchCoordinates() 两个静态方法,即可在鸿蒙 App 内把用户带进地图应用:搜索场景由系统面板列出已安装的地图应用,用户一键直达;同一段代码在 Android、iOS、桌面与 Web 上也各自生效。插件零权限、不绑定单一地图,已在 nova 12 Ultra 真机(HarmonyOS 6.1.0 / API 24)完整实测。

使用中发现任何问题,欢迎到配套仓库提 Issue,也欢迎发 PR 共建。

相关链接

欢迎加入 CPF-Flutter 鸿蒙社区,社区入口、环境搭建指南和本文相关链接统一放在这里:

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐