更新记录

1.0.0(2026-11-05)

  • 新增完整业务串联示例:搜索选择起终点、真实驾车分段预览、Navi独立重新算路并由用户启动模拟。
  • 新增示例页面一次性交接归属与可信来源返回,旧页面迟到失败、隐藏与卸载不会清除后来准备的行程。
  • 新增前台圆形围栏会话、真实SDK注册与关系观察、精确自有移除、状态和能力查询及完整示例;首条关系可能是初始状态,不提供后台或进程恢复。
  • 新增围栏原始超时预算、迟到隔离、隐藏/撤隐私清理及鸿蒙定位/导航双向资源门禁,区分SDK名单观察与系统资源停止。
  • 新增插件屏幕网格聚合、原生热力瓦片和海量点层,支持独立显隐、替换、读取、移除与点击关联。
  • 新增专属点沿输入路径移动、真实SDK活动和终态、按请求停止,以及地图区域临时PNG、完整度三态和自有图片回收。
  • 新增高级地图能力/实例状态、标准组件13方法与advanced-event,以及完整地图进阶演示;取消后的未确认原生管线继续保留占用。
  • 新增离线城市目录、单项下载/暂停/恢复/删除、真实阶段和缓存状态、会话身份与退出清理,以及完整离线地图演示;SDK 11+ 需高阶服务授权。
  • 新增驾车巡航启动、停止、真实统计/设施/电子眼/拥堵事件与独立位置确认,复用标准导航组件。
  • 新增导航和巡航内置播报初始配置、运行开关与真实配置读取。
  • 新增独立中文系统语音、按请求停止、能力和占用查询、隐藏/撤回隐私清理及完整巡航语音演示。
  • 新增隐私配置、原生 SDK 初始化和重复初始化处理。
  • 新增平台能力与运行状态查询。
  • 新增 uni-app x 首页与接入配置演示页。
  • 新增三端原生地图标准组件、相机控制、可视区域与地图类型切换。
  • 新增实时路况、指南针、比例尺、统一缩放按钮及四类手势配置。
  • 新增地图加载、相机变化、点击、长按、错误与销毁事件。
  • 新增独立多实例、暂停恢复、销毁重建及隐私撤回时统一清理。
  • 新增地图三标签演示页与统一线性图标资源。
  • 新增前台定位权限检查、权限申请、应用授权设置及单次定位。
  • 新增定位请求 ID、取消、超时、同类排它与迟到结果处理。
  • 新增定位坐标、精度、可用运动指标和地址结果,附定位演示页。
  • 新增按类型与 ID 管理标记、折线、圆和多边形,支持完整替换、样式、显隐与清理。
  • 新增本地 PNG/JPEG 图片标记、实际位置读取、标记点击、气泡点击与拖动事件。
  • 新增默认气泡控制、覆盖物能力与实际清单、坐标范围适配及覆盖物演示页。
  • 新增前台持续与后台定位会话、运行条件检查、通知许可申请及按会话启停。
  • 新增原生有界轨迹、状态与位置事件、前后台恢复、首点期限和隐私撤回清理。
  • 新增持续定位多标签演示页、实际轨迹地图及鸿蒙宿主后台能力配置示例。
  • 新增输入提示、新版POI关键词/周边/矩形/多边形搜索、单地点详情及五组扩展字段。
  • 新增搜索请求ID、并发关联、超时/取消/迟到隔离、原生等待与retired状态查询及能力边界。
  • 新增地点搜索完整示例、真实列表/地图/详情联动、分页与统一图标。
  • 新增正向/逆向地理编码、结构化地址与周边道路/路口/POI/AOI、行政区树和完整边界查询。
  • 新增多起点距离矩阵、逐项错误与输入编号关联、独立地理请求取消/超时/回执状态。
  • 新增SDK距离/面积计算、来源坐标至GCJ-02转换,以及地图实例本地逻辑像素双向投影。
  • 新增地理信息三标签与地图工具四标签完整示例,提供嵌套结果分页、行政树和边界浏览、真实地图联动及首页入口。
  • 新增驾车、步行、骑行、公交和货车原生路线规划,支持策略、多方案、途经点、避让和车辆参数。
  • 新增完整路段、交通/城市扩展、公交步行/线路备选/铁路/出租及出入口结果,保留空值和单位来源。
  • 新增独立路线请求取消/超时/隐私处理、能力与资源状态,以及五种方式完整演示和真实分段地图预览。
  • 新增驾车导航标准组件、Navi独立算路与真实路径组、行前预览与选路、GPS和模拟模式、内置导航语音及核心状态事件。
  • 新增导航概览、跟随、路况、取消等待、前台退出与结束重建、纯能力/占用查询及导航配置/展示完整示例。
  • 新增步行、骑行和燃油货车导航,按出行方式应用真实算路、预览选路、GPS/模拟与原生视图。
  • 新增各方式速度与交通图层能力、完整货车尺寸重量参数、固定方式实例和状态结果关联。

平台兼容性

uni-app(5.34)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× × × × × × × × ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × - × ×

uni-app x(5.34)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × √ - 6.0 ×

lizhao 高德地图

为 uni-app x 提供高德原生地图、覆盖物与高级图层、前台及后台定位、地点和地理信息查询、五种方式路线规划、驾车/步行/骑行/燃油货车 GPS 与模拟导航、巡航、系统语音、离线底图与前台圆形围栏。包含测量、坐标转换、地图截图及搜索到模拟导航的完整示例,使用统一隐私、初始化和错误处理接口。

功能特色

功能 实现效果 使用示例
隐私配置 分别设置政策已展示、包含高德说明与用户同意 setMapPrivacy
初始化 配置当前平台 Key,同 Key 可重复调用 initializeMap
运行状态 查看初始化、隐私、Key 绑定及鉴权状态 getMapStatus
平台能力 查询当前公开功能、最低系统及坐标系 getMapCapabilities
原生地图 标准、卫星、夜间地图与实时路况 lizhao-map 组件
相机与区域 中心、缩放、俯仰、旋转及实际可视边界 setCamera、getCamera、getBounds
控件与手势 指南针、比例尺、缩放按钮及四类手势 options、zoom-controls
实例与事件 独立多地图、暂停、销毁重建及点击/长按 active、destroy、map-event
前台权限 只读检查、系统申请、精确/大致区分和应用设置 getMapLocationPermission、requestMapLocationPermission
单次定位 坐标、精度、可用指标和地址,支持超时与取消 getMapLocation、cancelMapLocationRequest
持续与后台定位 前台显式启停、后台运行条件、通知许可及状态事件 startMapLocationSession、stopMapLocationSession、getMapLocationBackgroundStatus
有界轨迹 原生保管位置,返回前台读取、地图连线、清空缓冲 getMapLocationSessionTrack、clearMapLocationSessionTrack
输入提示 城市/类型/中心偏好,区分有无ID和坐标的真实提示 getMapInputTips
地点搜索 V2关键词、周边、矩形和多边形范围,分页与五组扩展 searchMapPois
地点详情 单ID真实POI、商业/室内/导航点/子POI/照片 getMapPoiDetail
搜索管理 ID取消、并发隔离、能力与原生retired记录状态 cancelMapSearchRequest、getMapSearchCapabilities、getMapSearchState
地址与行政区 正向/逆向编码、结构化地址、附近道路/路口/POI/AOI及行政区树/边界 geocodeMapAddress、reverseGeocodeMapCoordinate、searchMapDistricts
距离矩阵 多起点到单终点,直线/驾车/步行距离与时长、逐项失败 getMapDistanceMatrix
SDK本地工具 两点距离、矩形/多边形面积、来源坐标至GCJ-02 calculateMapDistance、calculateMapArea、convertMapCoordinate
实例投影 GCJ-02与当前地图本地逻辑像素互转 coordinateToScreen、screenToCoordinate
路线规划 驾车、步行、骑行、公交、货车,多方案与真实分段 planMapRoute
路线管理 独立请求、取消、超时、策略与平台能力查询 cancelMapRouteRequest、getMapRouteCapabilities、getMapRouteState
原生导航 驾车、步行、骑行和燃油货车;真实方案预览与选路、GPS/模拟、内置语音、实时引导与结束重建 lizhao-map-navi 组件
导航管理 纯能力/占用查询、取消等待、前台退出和真实回收状态 getMapNaviCapabilities、getMapNaviState、组件实例方法
驾车巡航 无需目的地的巡航检测,真实统计、设施、电子眼与拥堵回执 startCruise、cruise-start/update
语音控制 实例内置播报开关与独立中文系统语音,按请求停止与读取回收状态 setVoiceEnabled、speakMapText、stopMapSpeech
离线底图 城市目录、单城下载/暂停/恢复/删除、真实进度与缓存状态 九项离线会话 API;SDK 11+ 需高阶服务授权
标记与气泡 图片、拖动、旋转、显隐、透明度及气泡控制 upsertMarkers、setMarkerCallout
线面覆盖物 折线、圆、多边形的几何与描边/填充样式 upsertPolylines、upsertCircles、upsertPolygons
覆盖物管理 按类型与 ID 替换/移除、实际位置、清空及范围适配 getOverlaySummary、getMarkerPosition、fitCoordinates
高级数据层 屏幕网格聚合、原生热力瓦片和原生海量点 setMarkerClusters、setHeatmap、setMultiPoints
点移动与截图 专属点沿输入路径移动、当前地图区域临时 PNG startPointMove、takeMapSnapshot、advanced-event
前台圆形围栏 独立会话、真实注册回执、SDK关系观察与自有清理 七项围栏API;首条关系可能是初态,不等于物理跨界
完整业务串联 搜索两地点、Search驾车方案与分段地图、Navi重新算路后主动模拟 example/uniappx/journey.uvue,不复用Search路线凭据

适合哪些场景

场景 推荐能力 接入方式或边界
接入高德原生 SDK 隐私配置与初始化 使用对应平台申请的 Key
展示当前配置状态 状态查询 返回值不包含 Key 内容
处理错误与重复操作 初始化、统一错误码 Key 在进程内绑定,更换需重启应用
展示地点和浏览区域 原生地图、相机与边界查询 坐标为 GCJ-02,实际相机以事件或 getter 为准
对照多个地点 独立地图实例 每个组件拥有独立实例 ID、参数和事件
定位当前地点 前台权限与单次定位 用户主动触发,分别显示系统权限、SDK 配置与实际结果
记录移动过程 持续会话与有界轨迹 单次与持续互斥;前台模式退后台即停,后台模式须满足各端条件
查找地点和选择目标 输入提示、关键词/周边/范围、详情 列表选中联动真实地图,无坐标提示不制造位置
地址解析与区域浏览 地理编码、行政区树与真实边界 地址匹配不同于POI关键词搜索,树和边界保留实际SDK数据
估算范围与跨系接入 SDK距离/面积、坐标转换和实例投影 标明单位与SDK差异,转换值不变不能证明已转换或失败
对比多个起点的行驶成本 距离矩阵 按SDK一基ID关联输入,逐项失败不显示为0米/0秒
出行方案与货运预览 五种方式、途经点、避让、公交换乘与车辆参数 搜索结果用于预览;方案ID不能直接用于导航
多种出行方式的路线演示与行程引导 原生导航地图、行前方案、模拟/GPS和状态事件 两模式创建前均需前台定位;GPS需精确位置;一个实例启动一次,退出后重建
无目的地驾车提醒 巡航统计、设施与拥堵 精确定位、系统服务与前台;真实位置回执不等于巡航数据已经确认
前台中文文字播报 独立系统语音与状态 无需地图Key、SDK初始化或定位;仍需插件隐私同意,与任意导航实例互斥
提前准备目的地底图 离线城市目录和单项任务 用户主动选城;需要高德离线高阶服务,离线搜索/导航不在本能力保证内
选择地点或标注设施 标记、气泡、拖动事件 拖动后读取原生实际位置;多气泡先查能力
绘制路径与服务区域 折线、圆、多边形 半径为米,其他尺寸为逻辑像素,颜色与透明度分开
浏览密集点位与分布 聚合、热力、海量点 聚合使用插件网格算法;热力和海量点使用真实 SDK 图层
展示预设点移动或导出地图区域 点移动与地图截图 输入路径不是定位/导航;截图仅为当前地图区域,不含宿主界面
前台观察指定圆形区域的关系 精确定位与SDK圆形围栏 不提供后台、进程重启恢复或位置payload;SDK名单缺失不证明系统定位停止
验证搜索到导航的跨页面流程 地点选择、路线预览与模拟导航 两引擎分别算路;只传一次性关联ID,地点载荷保存在进程内

下载与导入

宿主 示例代码位置
uni-app x 接入配置 uni_modules/lizhao-map/example/uniappx/setup.uvue
uni-app x 地图控制 uni_modules/lizhao-map/example/uniappx/map.uvue
uni-app x 权限与定位 uni_modules/lizhao-map/example/uniappx/location.uvue
uni-app x 标记与覆盖物 uni_modules/lizhao-map/example/uniappx/overlays.uvue
uni-app x 持续与后台定位 uni_modules/lizhao-map/example/uniappx/tracking.uvue
uni-app x 地点搜索 uni_modules/lizhao-map/example/uniappx/search.uvue
uni-app x 地理信息 uni_modules/lizhao-map/example/uniappx/geocoding.uvue
uni-app x 数值与坐标工具 uni_modules/lizhao-map/example/uniappx/tools.uvue
uni-app x 路线规划 uni_modules/lizhao-map/example/uniappx/routes.uvue
uni-app x 导航配置 uni_modules/lizhao-map/example/uniappx/navigation.uvue
uni-app x 导航展示 uni_modules/lizhao-map/example/uniappx/navigation-view.uvue
uni-app x 巡航与语音 uni_modules/lizhao-map/example/uniappx/cruise.uvue
uni-app x 离线底图 uni_modules/lizhao-map/example/uniappx/offline.uvue
uni-app x 地图进阶 uni_modules/lizhao-map/example/uniappx/advanced-map/advanced-map.uvue
uni-app x 前台围栏 uni_modules/lizhao-map/example/uniappx/geofence.uvue
uni-app x 完整业务串联 uni_modules/lizhao-map/example/uniappx/journey.uvue
uni-app 当前尚未提供此宿主演示

从基础到进阶

基础功能配置示例(简单示例)

在 uni-app x 页面按钮中调用。apiKey 替换为宿主的当前平台 Key,隐私状态必须来自宿主实际展示和用户选择。

import { setMapPrivacy, initializeMap } from '@/uni_modules/lizhao-map'

function configureMap(apiKey: string) {
  try {
    setMapPrivacy({ shown: true, contains: true, agreed: true })
    const result = initializeMap({ apiKey: apiKey })
    console.log(result.errMsg, result.platform, result.sdkVersion)
    console.log(result.initialized, result.authVerified)
  } catch (error) {
    const failure = error as IUniError
    console.log(failure.errSubject, failure.errCode, failure.errMsg)
    console.log(failure.data, failure.cause)
  }
}

initialized=true 表示本地 SDK 配置完成。authVerified 当前始终为 false;插件不会根据配置或地图/定位回调推断已完成独立 Key 鉴权。实际 SDK 服务错误可通过请求结果和数字诊断检查。

高级示例

先在接入页完成隐私与初始化,然后在页面中放置地图。父容器须有明确高度。ready 来自原生地图加载回调,不表示联网鉴权已经得到独立验证。

<template>
  <view class="map-area">
    <LizhaoMap @map-event="onMapEvent" />
  </view>
</template>

<script setup lang="ts">
import LizhaoMap from '@/uni_modules/lizhao-map/components/lizhao-map/lizhao-map.uvue'
import type { MapEventDetail } from '@/uni_modules/lizhao-map'

function onMapEvent(event: MapEventDetail): void {
  if (event.type === 'ready') console.log('地图已就绪', event.instanceId)
  if (event.type === 'error') console.log(event.errCode, event.errMsg)
}
</script>

<style>
.map-area { height: 300px; }
</style>

以下查询可用于页面恢复。availableFeatures 仅列出本插件当前开放的功能。

import { getMapStatus, getMapCapabilities } from '@/uni_modules/lizhao-map'

function inspectMap() {
  const status = getMapStatus()
  console.log(status.platform, status.sdkVersion)
  console.log(status.initialized, status.keyConfigured, status.authVerified)
  console.log(status.privacy.shown, status.privacy.contains, status.privacy.agreed)

  const capabilities = getMapCapabilities()
  console.log(capabilities.platform, capabilities.supported)
  console.log(capabilities.availableFeatures, capabilities.minimumOSVersion)
  console.log(capabilities.coordinateType)
  if (!capabilities.supported) {
    console.log('请在支持的平台使用原生接入功能')
  }
}

进阶示例

使用组件 ref 操作同一个实例。以下函数分别演示标准、卫星、夜间三种地图,以及合法的 0 和 false。提交完整参数对象,实际缩放和角度可能受平台 SDK 限制,应读取实际结果。

import type { MapViewContext, MapType } from '@/uni_modules/lizhao-map'

function changeMap(context: MapViewContext, mapType: MapType): void {
  context.setCamera({ latitude: 31.2304, longitude: 121.4737, zoom: 13, tilt: 0, bearing: 0 })
  context.setOptions({
    mapType: mapType, traffic: false, compass: true, scale: true,
    gestures: { scroll: true, zoom: true, rotate: false, tilt: false }
  })
}

function compareLayers(context: MapViewContext): void {
  changeMap(context, 'normal')
  // 在对应按钮中分别调用,切换后观察地图。
  // changeMap(context, 'satellite')
  // changeMap(context, 'night')
}

隐私撤回会使初始化状态失效,并销毁本插件已经创建的所有地图。以下三个配置分别演示缺少展示、缺少高德说明和用户拒绝,实际业务只提交当前真实状态。再次同意并初始化后,需要移除旧组件并创建新组件。

import { setMapPrivacy, getMapStatus } from '@/uni_modules/lizhao-map'

function demonstratePrivacyStates() {
  setMapPrivacy({ shown: false, contains: false, agreed: false })
  console.log(getMapStatus().initialized)
  setMapPrivacy({ shown: true, contains: false, agreed: false })
  console.log(getMapStatus().privacy.contains)
  setMapPrivacy({ shown: true, contains: true, agreed: false })
  console.log(getMapStatus().privacy.agreed)
}

完整示例

以下为可放入 .uvue 的地图操作页。先在接入配置页初始化。相机属性是目标值,事件读数单独保存,避免拖动地图时反复回写目标。

<template>
  <view class="demo">
    <view class="map-area">
      <LizhaoMap v-if="mounted" :key="generation" ref="map"
        :camera="camera" :options="options" :active="active" :zoom-controls="true"
        @map-event="onMapEvent" />
    </view>
    <text>{{ message }}</text>
    <text>{{ actualCamera }}</text>
    <text>{{ boundsText }}</text>
    <text>{{ pointText }}</text>
    <button :disabled="!ready" @click="applyConfiguration">应用相机和图层</button>
    <button :disabled="!ready" @click="inspectView">读取实际相机和范围</button>
    <button :disabled="!ready" @click="toggleActive">{{ active ? '暂停地图' : '恢复地图' }}</button>
    <button :disabled="!mounted" @click="removeMap">销毁地图</button>
    <button :disabled="rebuilding" @click="rebuildMap">重建地图</button>
  </view>
</template>

<script setup lang="ts">
import { ref, nextTick, onUnmounted } from 'vue'
import { onShow, onHide, onUnload } from '@dcloudio/uni-app'
import LizhaoMap from '@/uni_modules/lizhao-map/components/lizhao-map/lizhao-map.uvue'
import { getMapStatus } from '@/uni_modules/lizhao-map'
import type { MapCamera, MapEventDetail, MapViewContext, MapViewOptions } from '@/uni_modules/lizhao-map'

const map = ref<MapViewContext | null>(null)
const mounted = ref(false)
const generation = ref(0)
const rebuilding = ref(false)
const active = ref(true)
const ready = ref(false)
const message = ref('请先完成接入配置')
const actualCamera = ref('')
const boundsText = ref('')
const pointText = ref('')
const camera = ref<MapCamera>({ latitude: 39.9042, longitude: 116.4074, zoom: 12, tilt: 0, bearing: 0 })
const options = ref<MapViewOptions>({
  mapType: 'normal', traffic: false, compass: true, scale: true,
  gestures: { scroll: true, zoom: true, rotate: true, tilt: true }
})
let leaving = false

function onMapEvent(event: MapEventDetail): void {
  if (leaving) return
  if (event.type === 'error') {
    if (event.errCode !== 9101009) ready.value = false
    message.value = `${event.errCode}: ${event.errMsg}`
    return
  }
  message.value = `${event.instanceId}: ${event.type}`
  if (event.type === 'ready') ready.value = true
  if (event.type === 'destroyed') ready.value = false
  if (event.type === 'ready' || event.type === 'camera-change') {
    actualCamera.value = `${event.latitude}, ${event.longitude}; zoom=${event.zoom}, tilt=${event.tilt}, bearing=${event.bearing}`
  }
  if (event.type === 'map-click' || event.type === 'map-long-press') {
    pointText.value = `${event.type}: ${event.pointLatitude}, ${event.pointLongitude}`
  }
}

function withMap(operation: (context: MapViewContext) => void): void {
  const context = map.value
  if (context === null || !ready.value) return
  try {
    operation(context)
  } catch (error) {
    const failure = error as IUniError
    message.value = `${failure.errCode}: ${failure.errMsg}`
  }
}

function applyConfiguration(): void {
  camera.value = { latitude: 31.2304, longitude: 121.4737, zoom: 13, tilt: 30, bearing: 90 }
  options.value = { ...options.value, mapType: 'night', traffic: true }
  withMap(context => {
    context.setCamera(camera.value)
    context.setOptions(options.value)
  })
}

function inspectView(): void {
  withMap(context => {
    const value = context.getCamera()
    const bounds = context.getBounds()
    actualCamera.value = `${value.latitude}, ${value.longitude}; zoom=${value.zoom}, tilt=${value.tilt}, bearing=${value.bearing}`
    boundsText.value = `西南 ${bounds.southwest.latitude}, ${bounds.southwest.longitude}; 东北 ${bounds.northeast.latitude}, ${bounds.northeast.longitude}`
  })
}

function toggleActive(): void {
  active.value = !active.value
  withMap(context => context.setActive(active.value))
}

function removeMap(): void {
  try { map.value?.destroy() }
  catch (_) { message.value = '销毁异常,请检查原生环境' }
  finally { mounted.value = false; ready.value = false }
}

async function rebuildMap(): Promise<void> {
  if (rebuilding.value || leaving) return
  rebuilding.value = true
  mounted.value = false
  ready.value = false
  try {
    await nextTick()
    if (leaving) return
    generation.value += 1
    mounted.value = getMapStatus().initialized
    message.value = mounted.value ? '等待地图就绪' : '请先完成接入配置'
  } finally { rebuilding.value = false }
}

onShow(() => {
  active.value = true
  if (!mounted.value && getMapStatus().initialized) mounted.value = true
})
onHide(() => { active.value = false })
onUnload(() => { leaving = true })
onUnmounted(() => { active.value = false; mounted.value = false; map.value = null })
</script>

<style>
.demo { flex: 1; padding: 16px; }
.map-area { height: 300px; }
</style>

完整输入表单、三类地图切换、手势开关、第二实例、事件读数和有容量限制的日志见 example/uniappx/map.uvue。

单次定位与地图初始化分别调用。先在接入配置页同意真实隐私政策并初始化,然后检查/申请权限,最后由用户点击获取一次位置。权限拒绝会作为 success 中的真实权限状态返回;只有定位失败才调用该定位请求的 fail。

import { getMapLocationPermission, requestMapLocationPermission, getMapLocation,
  cancelMapLocationRequest, openMapLocationSettings } from '@/uni_modules/lizhao-map'
import type { MapLocationResult, MapFail } from '@/uni_modules/lizhao-map'

function inspectPermission(): void {
  const result = getMapLocationPermission()
  console.log(result.requestId, result.platform, result.state)
  console.log(result.accuracy, result.serviceEnabled, result.canAskAgain)
}

function requestPermission(): string {
  return requestMapLocationPermission({
    timeoutMs: 60000,
    success: result => {
      console.log(result.requestId, result.state, result.accuracy)
      if (result.state === 'granted') console.log('可以由用户主动获取位置')
      else if (result.canAskAgain) console.log('用户准备好后可再次申请')
      else console.log('请查看应用授权设置或系统限制')
    },
    fail: showFailure,
    complete: () => console.log('权限等待结束')
  })
}

function locateOnce(): string {
  return getMapLocation({
    accuracy: 'high', timeoutMs: 10000, needAddress: false,
    success: showLocation,
    fail: showFailure,
    complete: () => console.log('本次定位请求结束')
  })
}

function showLocation(result: MapLocationResult): void {
  console.log(result.requestId, result.platform, result.coordinateType)
  console.log(result.latitude, result.longitude, result.accuracy)
  console.log(result.altitude ?? '未返回', result.speed ?? '未返回', result.bearing ?? '未返回')
  console.log(result.timestamp == null ? '未返回时间' : new Date(result.timestamp).toISOString())
  console.log(result.provider, result.isMock == null ? '未提供模拟标记' : result.isMock)
  const address = result.address
  if (address !== null) {
    console.log(address.formattedAddress, address.country, address.province, address.city, address.district)
    console.log(address.street, address.streetNumber, address.adCode, address.cityCode, address.poiName)
  } else console.log('未请求或未返回地址')
}

function showFailure(error: MapFail): void {
  const diagnostic = error.data as { requestId?: string; nativeErrorCode?: number | null } | null
  console.log(error.errSubject, error.errCode, error.errMsg)
  console.log(diagnostic?.requestId, diagnostic?.nativeErrorCode)
  if (error.errCode === 9101014) console.log('已取消等待')
  if (error.errCode === 9101012) console.log('请在系统设置中开启定位服务,再返回检查')
}

function cancelRequest(requestId: string): void {
  cancelMapLocationRequest(requestId)
}

function openApplicationSettings(): string {
  return openMapLocationSettings({
    success: result => console.log(result.requestId, result.platform, result.opened),
    fail: showFailure,
    complete: () => console.log('设置跳转请求结束,返回页面后重新检查权限')
  })
}

将返回的请求 ID 保存在页面实例内,取消时传回该 ID。回调保证在调用返回后交付;同类请求在进程内排它,未结束时再次发起返回 9101016。设置请求成功仅表示系统受理跳转,不表示用户已经改过授权。

在需要地址的按钮中调用 getMapLocation({ accuracy: 'balanced', timeoutMs: 20000, needAddress: true, success: showLocation, fail: showFailure })。请求精度是期望策略,实际精度与系统精确/大致授权分别显示。Android 大致权限下,balanced 自动使用可工作的单次策略,不扩大 OS 授权。

等待地图 ready 后,在同一个 ref 上绘制与更新。iconBase64 传入本地 PNG/JPEG 的 base64 内容;不填写时使用 SDK 默认标记。以下函数放入页面脚本,由按钮或 ready 分支调用,不能在组件创建前调用。

import type { MapViewContext, MapEventDetail, MapMarkerIcon } from '@/uni_modules/lizhao-map'

function drawOverlays(context: MapViewContext, iconBase64: string): void {
  const icon: MapMarkerIcon | null = iconBase64 === '' ? null : { imageBase64: iconBase64, width: 32, height: 32 }
  try {
    context.upsertMarkers([
      { id: 'start', position: { latitude: 39.9042, longitude: 116.4074 },
        title: '起点', snippet: '长按拖动后查看真实坐标', visible: true, draggable: true,
        rotation: 0, opacity: 1, zIndex: 2, anchorX: 0.5, anchorY: 1, icon: icon },
      { id: 'end', position: { latitude: 39.9142, longitude: 116.4274 }, title: '终点', snippet: '第二个标记' }
    ])
    context.upsertPolylines([{ id: 'path', points: [
      { latitude: 39.9042, longitude: 116.4074 }, { latitude: 39.9092, longitude: 116.4174 },
      { latitude: 39.9142, longitude: 116.4274 }
    ], strokeColor: '#14878f', strokeWidth: 4, strokeOpacity: 0.8, dashed: true, visible: true, zIndex: 1 }])
    context.upsertCircles([{ id: 'service', center: { latitude: 39.9092, longitude: 116.4174 }, radius: 600,
      strokeColor: '#14878f', strokeWidth: 2, strokeOpacity: 1, fillColor: '#14878f', fillOpacity: 0.18,
      visible: true, zIndex: 0 }])
    context.upsertPolygons([{ id: 'area', points: [
      { latitude: 39.9022, longitude: 116.4114 }, { latitude: 39.9072, longitude: 116.4114 },
      { latitude: 39.9072, longitude: 116.4214 }, { latitude: 39.9022, longitude: 116.4214 }
    ], strokeColor: '#c66a28', strokeWidth: 2, strokeOpacity: 1, fillColor: '#c66a28', fillOpacity: 0.15,
      visible: true, zIndex: 1 }])
    context.fitCoordinates([
      { latitude: 39.8992, longitude: 116.4014 }, { latitude: 39.9192, longitude: 116.4334 }
    ], 32)
    const capability = context.getOverlayCapabilities()
    console.log(capability.multipleCallouts, capability.customMarkerImage, capability.markerDrag)
    context.setMarkerCallout('start', true, true)
    if (capability.multipleCallouts) context.setMarkerCallout('end', true, false)
    else console.log('当前只支持单个默认气泡,再打开一个会替换前一个')
    const summary = context.getOverlaySummary()
    console.log(summary.markerIds, summary.polylineIds, summary.circleIds, summary.polygonIds)
  } catch (error) {
    const failure = error as IUniError
    console.log(failure.errCode, failure.errMsg)
  }
}

function onOverlayEvent(context: MapViewContext, event: MapEventDetail): void {
  const id = event.overlayId ?? ''
  if (event.type === 'marker-click' || event.type === 'marker-callout-click') {
    console.log(event.instanceId, event.overlayType, id, event.pointLatitude, event.pointLongitude)
  }
  if (event.type === 'marker-drag-start' || event.type === 'marker-drag' || event.type === 'marker-drag-end') {
    console.log(event.type, id, event.pointLatitude, event.pointLongitude)
  }
  if (event.type === 'marker-drag-end' && id !== '') {
    try {
      const actual = context.getMarkerPosition(id)
      console.log('拖动后原生读数', actual.latitude, actual.longitude)
    } catch (error) { console.log((error as IUniError).errCode) }
  }
}

function updateAndRemoveOverlays(context: MapViewContext): void {
  try {
    const position = context.getMarkerPosition('start')
    context.setMarkerCallout('start', false)
    // 整条替换而非局部 patch;0 和 false 都是有效值。
    context.upsertMarkers([{ id: 'start', position: position, visible: false, opacity: 0,
      rotation: 0, draggable: false, anchorX: 0, anchorY: 0, zIndex: 0, icon: null }])
    context.removeOverlays([{ type: 'polyline', id: 'path' }, { type: 'circle', id: 'service' }, { type: 'polygon', id: 'area' }])
    console.log(context.getOverlaySummary().markerIds)
    context.clearOverlays()
    console.log(context.getOverlaySummary())
  } catch (error) { console.log((error as IUniError).errCode, (error as IUniError).errMsg) }
}

upsert 按当前地图、覆盖物类型和 ID 定位对象,是整条替换:省略 title、icon 或样式时恢复默认。隐藏标记会关闭其气泡。移除不存在 ID 是空操作;读取不存在标记返回 9101017。默认气泡是否能同时显示多个以 getOverlayCapabilities 为准,不支持时用 exclusive=false 请求显示会明确失败;关闭不受此限制。

持续定位由用户在前台点击后启动,不隐式申请定位或通知许可。先在定位示例完成前台授权。以下示例适用于已完成隐私和 SDK 初始化的页面;后台模式先核对真实条件,配置未知时仍须由系统正式启动校验。

import { ref } from 'vue'
import { onShow, onHide, onUnload } from '@dcloudio/uni-app'
import {
  startMapLocationSession, stopMapLocationSession, getMapLocationSessionState,
  getMapLocationSessionTrack, clearMapLocationSessionTrack,
  getMapLocationBackgroundStatus, requestMapLocationNotificationPermission,
  cancelMapLocationRequest
} from '@/uni_modules/lizhao-map'
import type { MapLocationSessionTrack, MapFail } from '@/uni_modules/lizhao-map'

const track = ref<MapLocationSessionTrack | null>(null)
const message = ref('尚未开始')
let ownedSessionId = ''
let notificationRequestId = ''
let pageVisible = true
let disposed = false

function explain(error: MapFail) {
  if (!disposed && pageVisible) message.value = error.errCode.toString() + ' · ' + error.errMsg
}

// 绑定到独立“申请通知”按钮;拒绝作为正常状态返回。iOS为not-required。
function requestNotification() {
  if (notificationRequestId.length > 0) return
  notificationRequestId = requestMapLocationNotificationPermission({
    timeoutMs: 60000,
    success: result => {
      if (!disposed && pageVisible) message.value = result.state +
        ';频道=' + (result.channelEnabled == null ? '不适用或尚未创建' : result.channelEnabled ? '已开启' : '已关闭') +
        ';可再次申请=' + result.canAskAgain.toString()
    },
    fail: explain,
    complete: () => { notificationRequestId = '' }
  })
}

function begin(background: boolean) {
  try {
    if (background) {
      const access = getMapLocationBackgroundStatus()
      message.value = access.reason + ';配置=' + access.configurationState
      if (!access.supported || !access.canStart) return
      // requiresSettings=true时由用户单独点击openMapLocationSettings进入系统设置。
    }
    ownedSessionId = startMapLocationSession({
      mode: background ? 'background' : 'foreground', accuracy: 'high',
      intervalMs: 2000, distanceFilter: 0, needAddress: false,
      startupTimeoutMs: 10000, maxPoints: 500,
      androidNotification: { id: 2611706, title: '位置记录进行中', text: '正在使用位置信息,点击返回应用' },
      onEvent: event => {
        if (disposed || !pageVisible) return
        const state = event.state
        message.value = state.phase + ';累计=' + state.receivedPointCount.toString() +
          ';保留=' + state.storedPointCount.toString() + ';未保留=' + state.discardedPointCount.toString()
        if (event.type == 'error' && event.error != null) explain(event.error)
        if (event.type == 'location' && event.point != null) {
          const point = event.point
          // receivedAt是接收时间;location.timestamp为原始位置时间,可能为null或0。
          const fix = point.location
          message.value = fix.latitude.toString() + ',' + fix.longitude.toString() +
            ';精度=' + fix.accuracy.toString() + '米;序号=' + point.sequence.toString()
        }
      }
    })
  } catch (error) { explain(error as MapFail) }
}

function readTrack() {
  if (ownedSessionId.length == 0) return
  try { track.value = getMapLocationSessionTrack(ownedSessionId) }
  catch (error) { explain(error as MapFail) }
}
function clearTrack() {
  if (ownedSessionId.length == 0) return
  try { clearMapLocationSessionTrack(ownedSessionId); readTrack() }
  catch (error) { explain(error as MapFail) }
}
function stop() {
  if (ownedSessionId.length == 0) return
  try { stopMapLocationSession(ownedSessionId); readTrack() }
  catch (error) { explain(error as MapFail) }
}

onHide(() => { pageVisible = false })
onShow(() => {
  pageVisible = true
  if (disposed) return
  try {
    const state = getMapLocationSessionState()
    if (state.sessionId == ownedSessionId && ownedSessionId.length > 0) {
      message.value = state.phase + ';停止原因=' + state.stopReason
      readTrack() // 补齐后台期间原生缓存的点;不依赖后台JS定时器。
    }
  } catch (error) { explain(error as MapFail) }
})
onUnload(() => {
  disposed = true
  pageVisible = false
  if (notificationRequestId.length > 0) cancelMapLocationRequest(notificationRequestId)
  if (ownedSessionId.length > 0) stopMapLocationSession(ownedSessionId)
})

begin(false)只在前台持续;App退后台会停止。begin(true)在满足条件时继续原生定位,不承诺进程被系统终止后恢复。停止可能先进入stopping,待 SDK 与系统后台资源真实释放后才进入终态,此时重新开始前仍会返回9101016。轨迹最多2000点;应用长期存档应自行在前台按序号导出。

单次定位的成功或取消回调表示结果等待已结束,底层 SDK 可能仍在清理。若紧接着开始新的单次或持续定位收到9101016,应等待资源释放后重试,不能通过重复创建管理器绕过互斥。

地点搜索不需要先申请定位权限。以下输入中心均为手动查询条件,返回地点只有在 position !== null 时才能绘制。先在配置页完成真实隐私同意和当前平台 Key 初始化,再按按钮调用四种模式之一。

import { searchMapPois } from '@/uni_modules/lizhao-map'
import type { MapPoiSearchMode, MapPoiSearchOptions, MapPoiSearchResult } from '@/uni_modules/lizhao-map'

function queryPlaces(mode: MapPoiSearchMode, page: number,
  showResult: (result: MapPoiSearchResult) => void): string {
  const options: MapPoiSearchOptions = {
    mode, keyword: '咖啡', types: '050000', page, pageSize: 20,
    includeFields: ['children', 'business', 'indoor', 'navi', 'photos'], timeoutMs: 10000,
    success: result => {
      console.log(result.requestId, result.platform, result.coordinateType)
      console.log(result.query, result.count, result.items.length)
      // count 保留 SDK 原始计数;当前页为空不等于请求失败。
      if (result.items.length === 0) console.log('本页没有地点,请调整条件或返回上一页')
      if (result.suggestions !== null) {
        console.log(result.suggestions.keywords)
        for (const city of result.suggestions.cities) {
          console.log(city.name, city.cityCode, city.adCode, city.count)
        }
      }
      showResult(result)
    },
    fail: error => console.log(error.errCode, error.data),
    complete: () => console.log('本次等待结束')
  }
  if (mode === 'keyword') {
    options.city = '杭州'; options.cityLimit = true
    options.center = { latitude: 30.2741, longitude: 120.1551 }; options.sort = 'distance'
  } else if (mode === 'nearby') {
    options.keyword = ''; options.types = ''; options.city = ''; options.cityLimit = false
    options.center = { latitude: 30.2741, longitude: 120.1551 }
    options.radius = 0; options.sort = 'distance'
    // radius=0 原样传给 SDK,不回退为3000;是否有地点以服务响应为准。
  } else if (mode === 'rectangle') {
    options.sort = 'comprehensive'
    options.rectangle = {
      southWest: { latitude: 30.25, longitude: 120.13 },
      northEast: { latitude: 30.29, longitude: 120.18 }
    }
  } else {
    options.sort = 'comprehensive'
    options.polygon = [
      { latitude: 30.25, longitude: 120.13 },
      { latitude: 30.29, longitude: 120.13 },
      { latitude: 30.29, longitude: 120.18 },
      { latitude: 30.25, longitude: 120.18 }
    ] // 公开参数不重复首尾;插件在需要的 SDK 边界闭合。
  }
  return searchMapPois(options)
}

// 四个按钮分别调用 queryPlaces('keyword'/'nearby'/'rectangle'/'polygon', 1, showResult)。
// 翻页时使用成功结果的 query 条件与 query.page + 1;条件改变后重置为第1页。

提示可能是品牌词、线路或地点。不要把提示名称当成坐标;仅有 ID 的提示也不保证可用于 POI 详情。详情使用实际搜索结果 ID,并按 requestId 关联请求;原厂可能返回别名 poi.id。

import { getMapInputTips, getMapPoiDetail } from '@/uni_modules/lizhao-map'
import type { MapPoi, MapInputTip } from '@/uni_modules/lizhao-map'

function readPoi(poi: MapPoi): void {
  console.log(poi.id, poi.name, poi.type, poi.typeCode, poi.address)
  console.log(poi.province, poi.provinceCode, poi.city, poi.cityCode, poi.district, poi.adCode)
  console.log(poi.position, poi.distanceToCenterMeters) // null不变成0;估算距离不是路线距离。
  if (poi.business !== null) {
    const value = poi.business
    console.log(value.businessArea, value.openingHoursToday, value.openingHoursWeek)
    console.log(value.telephone, value.tags, value.rating, value.averageCost)
    console.log(value.parkingType, value.alias, value.cpId) // 评分/消费保留SDK文本。
  }
  if (poi.indoor !== null) {
    console.log(poi.indoor.hasIndoorMap, poi.indoor.poiId, poi.indoor.floor, poi.indoor.floorName)
    // floor=0、hasIndoorMap=false均为合法值;floor=null表示SDK未提供。
  }
  if (poi.navi !== null) console.log(poi.navi.poiId, poi.navi.entry, poi.navi.exit, poi.navi.gridCode)
  for (const child of poi.children) {
    console.log(child.id, child.name, child.address, child.type, child.typeCode, child.position)
  }
  for (const photo of poi.photos) console.log(photo.title, photo.url)
}
function requestDetail(realPoiId: string): string {
  return getMapPoiDetail({
    id: realPoiId, includeFields: ['children', 'business', 'indoor', 'navi', 'photos'], timeoutMs: 15000,
    success: result => {
      console.log(result.requestId, result.platform, result.coordinateType)
      console.log(result.requestedId, result.includeFields); readPoi(result.poi)
    },
    fail: error => console.log(error.errCode === 9101021 ? '未找到此地点' : '详情失败', error.errCode, error.data),
    complete: () => console.log('详情等待结束')
  })
}
function requestTips(selectTip: (tip: MapInputTip) => void): string {
  return getMapInputTips({
    keyword: '咖啡', city: '杭州', cityLimit: false, types: '050000',
    center: { latitude: 30.2741, longitude: 120.1551 }, timeoutMs: 10000,
    success: result => {
      console.log(result.requestId, result.platform, result.coordinateType)
      console.log(result.keyword, result.city, result.cityLimit, result.types, result.center)
      if (result.tips.length === 0) console.log('提示为空,请换一个关键词')
      for (const tip of result.tips) {
        console.log(tip.id, tip.name, tip.district, tip.adCode, tip.address, tip.typeCode, tip.position)
        selectTip(tip) // 交给列表选择;position=null时只允许按词继续搜索。
      }
    },
    fail: error => console.log(error.errCode, error.data),
    complete: () => console.log('提示等待结束')
  })
}

页面应只取消自己持有的 ID。下例可放入页面脚本,展示并发隔离、重复查询保护、地图联动、迟到结果隔离和退出清理。将 showPage(context) 绑定搜索按钮,把地图 ready 后得到的 ref 传入;列表选择调用 choose(index, context),并由界面单独展示列表与错误。

import { onHide, onShow, onUnload } from '@dcloudio/uni-app'
import { searchMapPois, cancelMapSearchRequest, getMapSearchCapabilities, getMapSearchState } from '@/uni_modules/lizhao-map'
import type { MapViewContext, MapPoi, MapFail } from '@/uni_modules/lizhao-map'

let visible = true, disposed = false, generation = 0
let ownedRequestId = '', items: MapPoi[] = []
function inspectSearch(): void {
  const capabilities = getMapSearchCapabilities()
  console.log(capabilities.platform, capabilities.supported, capabilities.inputTips, capabilities.poiModes)
  console.log(capabilities.poiDetail, capabilities.optionalFields, capabilities.poiSuggestions)
  console.log(capabilities.cancellation, capabilities.maxPage, capabilities.maxPageSize)
  console.log(capabilities.maxPolygonVertices, capabilities.maxPendingRequests, capabilities.note)
  const state = getMapSearchState()
  console.log(state.platform, state.pendingRequestIds, state.retiredRequestCount, state.maxPendingRequests)
}
function cancelOwned(): void {
  generation++
  const id = ownedRequestId; ownedRequestId = ''
  if (id !== '') cancelMapSearchRequest(id)
}
function showPage(context: MapViewContext): void {
  if (!visible || disposed || ownedRequestId !== '') return
  const current = ++generation
  try {
    ownedRequestId = searchMapPois({
      mode: 'keyword', keyword: '', types: '050000', city: '杭州', cityLimit: false,
      sort: 'comprehensive', page: 1, pageSize: 20, includeFields: [], timeoutMs: 10000,
      success: result => {
        if (disposed || !visible || current !== generation || result.requestId !== ownedRequestId) return
        items = result.items; context.clearOverlays()
        const markers = items.filter(value => value.position !== null).map((value, index) => ({
          id: 'result-' + index, position: value.position!, title: value.name, snippet: value.address
        }))
        if (markers.length > 0) context.upsertMarkers(markers)
        if (markers.length === 1) context.setCamera({ ...markers[0].position, zoom: 16, tilt: 0, bearing: 0 })
        if (markers.length > 1) context.fitCoordinates(markers.map(value => value.position), 32)
      },
      fail: error => { if (!disposed && visible && current === generation) explain(error) },
      complete: () => { if (current === generation) ownedRequestId = '' }
    })
  } catch (error) { ownedRequestId = ''; explain(error as MapFail) }
}
function choose(index: number, context: MapViewContext): void {
  const value = items[index]
  if (value !== undefined && value.position !== null) {
    context.setCamera({ ...value.position, zoom: 16, tilt: 0, bearing: 0 })
  }
}
function explain(error: MapFail): void { console.log(error.errCode, error.errMsg, error.data) }
onHide(() => { visible = false; cancelOwned() })
onShow(() => { visible = true; inspectSearch() })
onUnload(() => { disposed = true; visible = false; cancelOwned(); items = [] })

同一页面可分别保存提示、列表和详情 ID,最多共4个原生自有记录。取消或超时后 Android/鸿蒙仍可能保留等待 SDK 回执的记录,不能通过循环重试绕过上限;原始示例页同时演示三类请求独立状态、取消、并发操作和完整字段读取。

地理信息与地点搜索使用独立请求通道。以下示例分别演示地址匹配、逆编码、行政区和多起点矩阵;在页面按钮调用 runGeo(...),页面隐藏/退出时只取消本例持有的ID。

import { onHide, onShow, onUnload } from '@dcloudio/uni-app'
import { geocodeMapAddress, reverseGeocodeMapCoordinate, searchMapDistricts, getMapDistanceMatrix,
  cancelMapGeoRequest, getMapGeoCapabilities, getMapGeoState } from '@/uni_modules/lizhao-map'
import type { MapGeocodeAddress, MapReverseGeocodeAddress, MapDistrictNode, MapDistanceMatrixResult, MapFail } from '@/uni_modules/lizhao-map'

let geoVisible = true, geoDisposed = false
const ownedGeoIds: string[] = []
function finishGeo(id: string): void { const index = ownedGeoIds.indexOf(id); if (index >= 0) ownedGeoIds.splice(index, 1) }
function cancelGeo(): void { const ids = ownedGeoIds.splice(0); for (const id of ids) cancelMapGeoRequest(id) }
function explainGeo(error: MapFail): void { if (geoVisible && !geoDisposed) console.log(error.errCode, error.errMsg, error.data) }
function runGeo(kind: 'geocode' | 'reverse' | 'district' | 'matrix'): string {
  if (!geoVisible || geoDisposed) return ''
  let id = ''
  const complete = () => finishGeo(id)
  if (kind === 'geocode') id = geocodeMapAddress({
    address: '浙江省杭州市西湖区文三路', city: '杭州', country: '中国', timeoutMs: 10000,
    success: result => {
      if (!geoVisible || geoDisposed || !ownedGeoIds.includes(result.requestId)) return
      console.log(result.requestId, result.platform, result.coordinateType, result.query, result.count)
      if (result.items.length === 0) console.log('没有地址匹配,请补全结构化地址')
      for (const item of result.items) readGeocode(item)
    }, fail: explainGeo, complete
  })
  if (kind === 'reverse') id = reverseGeocodeMapCoordinate({
    position: { latitude: 30.2741, longitude: 120.1551 }, radius: 0, includeNearby: true,
    poiTypes: '050000|060000', overseaSort: 'distance', timeoutMs: 10000,
    success: result => {
      if (!geoVisible || geoDisposed || !ownedGeoIds.includes(result.requestId)) return
      console.log(result.requestId, result.platform, result.coordinateType, result.query)
      if (result.address === null) console.log('SDK未提供地址,不生成空地址或坐标')
      else readReverseAddress(result.address)
    }, fail: explainGeo, complete
  })
  if (kind === 'district') id = searchMapDistricts({
    keywords: '杭州', subDistrict: 1, showBoundary: true, page: 1, pageSize: 20, timeoutMs: 15000,
    success: result => {
      if (!geoVisible || geoDisposed || !ownedGeoIds.includes(result.requestId)) return
      console.log(result.requestId, result.platform, result.coordinateType, result.query, result.count)
      for (const node of result.items) readDistrict(node)
    }, fail: explainGeo, complete
  })
  if (kind === 'matrix') id = getMapDistanceMatrix({
    origins: [{ latitude: 30.2741, longitude: 120.1551 }, { latitude: 30.28, longitude: 120.16 }],
    destination: { latitude: 30.285, longitude: 120.17 }, mode: 'driving', strategy: 4,
    includeExtensions: false, timeoutMs: 15000,
    success: result => {
      if (!geoVisible || geoDisposed || !ownedGeoIds.includes(result.requestId)) return
      readMatrix(result)
    }, fail: explainGeo, complete
  })
  ownedGeoIds.push(id) // 回调在返回ID后交付,不会先于此行执行。
  return id
}
function readGeocode(item: MapGeocodeAddress): void {
  console.log(item.formattedAddress, item.province, item.city, item.cityCode, item.district, item.adCode)
  console.log(item.township, item.neighborhood, item.building, item.country, item.postCode, item.level, item.position)
  if (item.position === null) console.log('此匹配没有可绘制坐标')
}
function readReverseAddress(item: MapReverseGeocodeAddress): void {
  console.log(item.formattedAddress)
  const component = item.addressComponent
  if (component !== null) {
    console.log(component.country, component.countryCode, component.province, component.city, component.cityCode)
    console.log(component.district, component.adCode, component.township, component.townCode, component.neighborhood, component.building)
    if (component.streetNumber !== null) {
      const street = component.streetNumber
      console.log(street.street, street.number, street.position, street.direction, street.distanceMeters)
    }
    for (const area of component.businessAreas) console.log(area.name, area.position)
  }
  for (const road of item.roads) console.log(road.id, road.name, road.position, road.direction, road.distanceMeters)
  for (const road of item.intersections) console.log(road.position, road.distanceMeters, road.direction,
    road.firstRoadId, road.firstRoadName, road.secondRoadId, road.secondRoadName)
  for (const poi of item.pois) console.log(poi.id, poi.name, poi.type, poi.typeCode, poi.address, poi.province,
    poi.provinceCode, poi.city, poi.cityCode, poi.district, poi.adCode, poi.telephone, poi.direction,
    poi.businessArea, poi.position, poi.distanceMeters)
  for (const aoi of item.aois) console.log(aoi.id, aoi.name, aoi.adCode, aoi.position, aoi.areaSquareMeters, aoi.distanceMeters, aoi.type)
}
function readDistrict(node: MapDistrictNode): void {
  console.log(node.name, node.level, node.cityCode, node.adCode, node.center, node.children.length)
  for (const boundary of node.boundaries) {
    console.log('实际边界点数', boundary.length)
    // 绘制时使用真实顶点;大边界按覆盖物上限分段,不截断查询结果。
    const first = boundary[0], last = boundary[boundary.length - 1]
    if (first !== undefined && last !== undefined) console.log(first.latitude, first.longitude, last.latitude, last.longitude)
  }
  for (const child of node.children) readDistrict(child)
}
function readMatrix(result: MapDistanceMatrixResult): void {
  console.log(result.requestId, result.platform, result.coordinateType, result.query)
  for (const item of result.items) {
    console.log(item.originId, item.destinationId, item.originIndex, item.destinationIndex)
    if (item.success) console.log(item.distanceMeters, '米', item.durationSeconds, '秒', item.errorCode, item.reason)
    else console.log('该起点失败', item.errorCode, item.reason, item.distanceMeters, item.durationSeconds)
  }
}
function inspectGeo(): void {
  const value = getMapGeoCapabilities()
  console.log(value.platform, value.supported, value.geocode, value.reverseGeocode, value.district, value.distance)
  console.log(value.areaModes, value.coordinateSources, value.mapProjection, value.distanceMatrixModes, value.cancellation)
  console.log(value.maxPendingRequests, value.maxMatrixOrigins, value.maxDistrictDepth, value.maxDistrictPage, value.maxDistrictPageSize)
  console.log(value.maxAreaVertices, value.maxDistrictNodes, value.maxBoundaryPoints, value.note)
  const state = getMapGeoState()
  console.log(state.platform, state.pendingRequestIds, state.retiredRequestCount, state.maxPendingRequests)
}
onHide(() => { geoVisible = false; cancelGeo() })
onShow(() => { geoVisible = true; inspectGeo() })
onUnload(() => { geoDisposed = true; geoVisible = false; cancelGeo() })

逆编码 includeNearby=false 使用基础信息,此时 poiTypes 留空且 overseaSort 保持默认。overseaSort='score' 只在扩展查询中传入,并按原厂说明仅海外生效。行政区 subDistrict=0 表示不返回下级;设置1、2、3分别请求对应深度,showBoundary=false 可减少数据。矩阵可将mode改为straight/walking,非驾车strategy保持4且不向服务发送;步行距离受原厂覆盖和服务范围限制,逐项读取错误。

本地工具需要已同意隐私和SDK初始化,不申请定位或占用在线四槽。以下代码绑定到地图ready后的操作按钮;map-local屏幕点以当前地图左上角为原点,单位为逻辑px。

import { calculateMapDistance, calculateMapArea, convertMapCoordinate } from '@/uni_modules/lizhao-map'
import type { MapViewContext, MapCoordinateSource, MapFail } from '@/uni_modules/lizhao-map'

function useSdkTools(context: MapViewContext, fromType: MapCoordinateSource): void {
  try {
    const from = { latitude: 30.2741, longitude: 120.1551 }
    const to = { latitude: 30.28, longitude: 120.16 }
    const distance = calculateMapDistance({ from, to })
    console.log(distance.platform, distance.coordinateType, distance.distanceMeters, '米', distance.method)
    const rectangle = calculateMapArea({ mode: 'rectangle', rectangle: { southWest: from, northEast: to } })
    const polygon = calculateMapArea({ mode: 'polygon', polygon: [from, { latitude: 30.28, longitude: 120.1551 }, to] })
    for (const area of [rectangle, polygon]) console.log(area.platform, area.coordinateType, area.mode, area.areaSquareMeters, '平方米', area.method)
    const converted = convertMapCoordinate({ position: from, fromType })
    console.log(converted.platform, converted.inputPosition, converted.fromType, converted.toType, converted.position)
    console.log(converted.changed, converted.dataAvailable, converted.method)
    if (!converted.changed) console.log('数值未变:可能同系、区域差异或SDK回退,不能据此验证转换成功')
    const pixel = context.coordinateToScreen(to)
    const roundTrip = context.screenToCoordinate({ x: pixel.x, y: pixel.y })
    const localOrigin = context.screenToCoordinate({ x: 0, y: 0 })
    console.log(pixel.x, pixel.y, '地图内逻辑px', roundTrip.latitude, roundTrip.longitude, localOrigin)
  } catch (error) {
    const failure = error as MapFail
    console.log(failure.errCode, failure.errMsg, failure.data)
  }
}

fromType从gcj02/wgs84/bd09/mapbar/mapabc/soso/aliyun/google选择;目标只提供GCJ-02,不虚构SDK没有的逆向转换。gcj02为identity复制。SDK可能对同系、区域外或内部异常原样返回;changed仅表示数值变化,dataAvailable仅表示SDK对输出GCJ-02坐标的数据覆盖判断,不是Key或转换正确性验证。SDK距离/面积是估算,三端算法和浮点可能不同;不等于驾车路线长度或测绘精度。

路线请求先返回ID,回调异步交付。下例使用驾车全部参数;避让道路与避让面互斥,要演示避让面时清空avoidRoad。坐标必须为GCJ-02,起终点POI ID可不填。

import { planMapRoute, cancelMapRouteRequest, getMapRouteCapabilities, getMapRouteState } from '@/uni_modules/lizhao-map'
import type { MapRouteResult, MapRouteOptions, MapRouteMode, MapCoordinate, MapViewContext } from '@/uni_modules/lizhao-map'

let routeRequest = ''
let routeResult: MapRouteResult | null = null
const routeFrom = { position: { latitude: 39.908823, longitude: 116.397470 }, poiId: '' }
const routeTo = { position: { latitude: 39.984120, longitude: 116.307484 }, poiId: '' }

function loadDrivingRoute() {
  if (routeRequest.length > 0) return
  routeRequest = planMapRoute({
    mode: 'driving', from: routeFrom, to: routeTo, timeoutMs: 10000,
    driving: { strategy: 32, waypoints: [{ latitude: 39.941, longitude: 116.36 }],
      avoidPolygons: [], avoidRoad: '示例道路', plate: '', carType: 0,
      useFerry: true, includeTraffic: true, includeCities: true },
    success: result => {
      routeResult = result
      console.log(result.requestId, result.platform, result.coordinateType, result.mode, result.provider)
      console.log(result.query, result.origin, result.destination, result.taxiCostYuan)
      console.log(result.navigationReusable, result.scalarPresenceKnown)
      if (result.routes.length === 0) console.log('本次查询没有方案')
      for (const route of result.routes) {
        console.log(route.id, route.index, route.distanceMeters, route.durationSeconds, route.durationSource)
        console.log(route.strategyDescription, route.restrictionCode, route.tollsYuan, route.tollDistanceMeters, route.trafficLights)
        for (const step of route.steps ?? []) {
          console.log(step.instruction, step.orientation, step.road, step.distanceMeters, step.durationSeconds)
          console.log(step.action, step.assistantAction, step.roadType, step.tollsYuan, step.tollDistanceMeters, step.tollRoad, step.trafficLights)
          console.log(step.polyline, step.cities, step.traffic)
        }
      }
    },
    fail: error => { console.log(error.errCode, error.errMsg, error.data) },
    complete: () => { routeRequest = '' }
  })
}
function stopRouteRequest() {
  if (routeRequest.length > 0) cancelMapRouteRequest(routeRequest)
}
function inspectRouteSupport() {
  const caps = getMapRouteCapabilities()
  console.log(caps.platform, caps.supported, caps.modes, caps.drivingStrategyValues, caps.transitStrategyValues, caps.truckStrategyValues)
  console.log(caps.alternativeCounts, caps.maxTransitAlternatives, caps.truckSizeValues, caps.indoorWalking, caps.trafficModes, caps.cityModes)
  console.log(caps.navigationReusable, caps.scalarPresenceKnown, caps.cancellation, caps.maxPendingRequests, caps.maxWaypoints)
  console.log(caps.maxAvoidPolygons, caps.maxAvoidVertices, caps.maxRoutes, caps.maxSteps, caps.maxTransitSegments, caps.maxAuxiliaryItems, caps.maxGeometryPoints, caps.note)
  const state = getMapRouteState()
  console.log(state.platform, state.pendingRequestIds, state.retiredRequestCount, state.maxPendingRequests)
}

按选定方式只传对应参数组,其他组不传。以下函数分别展示步行、骑行、公交与货车的全部配置;起终点和POI ID由调用者传入真实值。公交策略6要求两端POI ID均非空。

import { planMapRoute, getMapRouteCapabilities } from '@/uni_modules/lizhao-map'
import type { MapRouteMode, MapRouteOptions, MapRouteEndpoint, MapRouteResult } from '@/uni_modules/lizhao-map'

function planOtherRoute(mode: MapRouteMode, from: MapRouteEndpoint, to: MapRouteEndpoint, receive: (result: MapRouteResult) => void): string {
  const caps = getMapRouteCapabilities()
  const options: MapRouteOptions = { mode, from, to, timeoutMs: 10000,
    success: receive, fail: error => console.log(error.errCode, error.errMsg, error.data), complete: () => console.log('本次等待结束') }
  if (mode === 'walking') options.walking = { alternativeRoute: 3, indoor: caps.indoorWalking }
  if (mode === 'riding') options.riding = { alternativeRoute: 3 }
  if (mode === 'transit') options.transit = {
    originCityCode: '010', destinationCityCode: '010', strategy: 0, includeNightBuses: false,
    alternativeRoute: 5, maxTransfers: 4, includeAllSubwayExits: true,
    originAdCode: '110101', destinationAdCode: '110108', date: '', time: '09:30'
  }
  if (mode === 'truck') options.truck = {
    strategy: 1, waypoints: [], size: 2, heightMeters: 1.6, widthMeters: 2.5,
    grossWeightTons: 0.9, ratedLoadTons: 10, axles: 2, plateProvince: '', plateNumber: '',
    includeTraffic: caps.trafficModes.includes('truck'), includeCities: caps.cityModes.includes('truck')
  }
  if (mode === 'driving') options.driving = {
    strategy: 32, avoidRoad: '', avoidPolygons: [{ points: [
      { latitude: 39.93, longitude: 116.37 }, { latitude: 39.93, longitude: 116.38 }, { latitude: 39.94, longitude: 116.38 }
    ] }]
  }
  return planMapRoute(options)
}

方案选择保留真实分段。公交每段busLines是备选线路,选一条绘制;铁路只展示站点和车次,SDK没有轨道几何。不要把空几何补为起终点直线。以下函数展示一次方案选择与换乘字段读取;context来自已ready的地图实例。

import type { MapRouteResult, MapCoordinate, MapPolyline, MapViewContext } from '@/uni_modules/lizhao-map'

function drawSelectedRoute(result: MapRouteResult, index: number, context: MapViewContext) {
  const route = result.routes[index]
  if (route == null) return
  const lines: MapPolyline[] = []
  const points: MapCoordinate[] = []
  function append(segment: MapCoordinate[]) {
    if (segment.length < 2) return
    if (!segment.some(point => point.latitude !== segment[0].latitude || point.longitude !== segment[0].longitude)) {
      console.log('本段坐标相同,只保留结果字段,不提交退化折线')
      return
    }
    if (segment.length > 5000) { console.log('当前分段超过单覆盖物5000点,请按保留边界点方式拆段'); return }
    const line: MapPolyline = { id: 'route-' + lines.length.toString(), points: segment, strokeColor: '#2377E8', strokeWidth: 5 }
    lines.push(line)
    for (const point of segment) points.push(point)
  }
  for (const step of route.steps ?? []) append(step.polyline)
  const transit = route.transit
  if (transit != null) {
    console.log(transit.costYuan, transit.nightBus, transit.walkingDistanceMeters, transit.busDistanceMeters)
    for (const segment of transit.segments) {
      if (segment.walking != null) {
        console.log(segment.walking.origin, segment.walking.destination, segment.walking.distanceMeters, segment.walking.durationSeconds)
        for (const step of segment.walking.steps) append(step.polyline)
      }
      for (const line of segment.busLines) console.log(line.id, line.name, line.type, line.cityCode, line.distanceMeters, line.durationSeconds,
        line.departureStop, line.arrivalStop, line.viaStopCount, line.viaStops, line.firstTimeText, line.lastTimeText)
      if (segment.busLines.length > 0) append(segment.busLines[0].polyline)
      if (segment.taxi != null) {
        console.log(segment.taxi.origin, segment.taxi.destination, segment.taxi.originName, segment.taxi.destinationName,
          segment.taxi.distanceMeters, segment.taxi.durationSeconds, segment.taxi.priceText, segment.taxi.priceYuan)
        append(segment.taxi.polyline)
      }
      if (segment.railway != null) {
        console.log(segment.railway.id, segment.railway.name, segment.railway.trip, segment.railway.type, segment.railway.distanceMeters, segment.railway.durationSeconds)
        console.log(segment.railway.departureStation, segment.railway.arrivalStation, segment.railway.viaStops, segment.railway.spaces, segment.railway.alternatives)
      }
      console.log(segment.entrance, segment.exit)
    }
  }
  context.clearOverlays()
  if (lines.length > 0) {
    for (let start = 0; start < lines.length; start += 500) context.upsertPolylines(lines.slice(start, start + 500))
  }
  else console.log('此方案没有可绘制的真实分段')
  // 只用真实轨迹中的四个极值点适配视口,绘制仍保留各段完整几何。
  const fit: MapCoordinate[] = []
  if (points.length > 0) {
    let north = points[0], south = points[0], east = points[0], west = points[0]
    for (const point of points) {
      if (point.latitude > north.latitude) north = point
      if (point.latitude < south.latitude) south = point
      if (point.longitude > east.longitude) east = point
      if (point.longitude < west.longitude) west = point
    }
    fit.push(north, south, east, west)
    if (Math.abs(north.latitude) <= 85 && Math.abs(south.latitude) <= 85 && east.longitude - west.longitude < 180) context.fitCoordinates(fit, 24)
    else console.log('当前轨迹超出自动视口适配范围')
  }
}

驾车导航:真实算路、选路与结束重建

先完成上面的隐私与初始化。两种导航模式创建引擎时都会定位;下例只在用户点击后创建。取消是取消插件等待,旧 SDK 请求可能继续占用资源。模拟用于演示;GPS 还须精确位置。完整输入、状态与分页结果可直接查看插件内两张导航示例页。

<template>
  <view class="example">
    <lizhao-map-navi v-if="mounted" :key="viewKey" ref="navi" class="navigation" :active="active" :traffic="traffic" @navi-event="onNaviEvent" />
    <scroll-view class="controls" direction="vertical">
      <button class="action" @click="requestPermission">主动申请前台定位</button>
      <button class="action" @click="createView">创建新的导航实例</button>
      <input class="plate" v-model="plate" placeholder="可选:本次实际车牌" />
      <button class="action" @click="calculate">按手动坐标算路</button>
      <button class="action" @click="calculateFromHere">按 SDK 当前位置算路</button>
      <button class="action" @click="readRoutes">读取并选择真实方案</button>
      <button class="action" @click="start('emulator')">以 60 km/h 开始模拟</button>
      <button class="action" @click="start('gps')">开始 GPS 导航</button>
      <button class="action" @click="run(view => view.cancelCalculation())">取消本次算路等待</button>
      <button class="action" @click="run(view => view.showOverview())">全览实际路线</button>
      <button class="action" @click="run(view => view.followVehicle())">导航中跟随车辆</button>
      <button class="action" @click="toggleTraffic">切换真实路况图层</button>
      <button class="action" @click="readState">读取实例与全局状态</button>
      <button class="action" @click="run(view => view.stop())">停止并结束本次实例</button>
      <button class="action" @click="run(view => view.setActive(false))">结束前台使用</button>
      <button class="action" @click="run(view => view.destroy())">销毁本次实例</button>
      <text class="output">{{ output }}</text>
    </scroll-view>
  </view>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { onHide, onShow, onUnload } from '@dcloudio/uni-app'
import { getMapStatus, getMapLocationPermission, requestMapLocationPermission, cancelMapLocationRequest, getMapNaviCapabilities, getMapNaviState } from '@/uni_modules/lizhao-map'
import type { MapNaviViewContext, MapNaviCalculateOptions, MapNaviEvent, MapNaviMode } from '@/uni_modules/lizhao-map'

const navi = ref<MapNaviViewContext | null>(null)
const mounted = ref(false), active = ref(true), traffic = ref(false), viewKey = ref(0)
const plate = ref(''), output = ref('请先完成接入配置,再主动检查权限。')
let visible = true, exited = false, permissionId = ''
let privacyTimer: ReturnType<typeof setInterval> | null = null
function checkPrivacy(): void {
  if (exited || !visible) return
  const privacy = getMapStatus().privacy
  if (!privacy.shown || !privacy.contains || !privacy.agreed) {
    plate.value = ''; output.value = '隐私条件未满足,已清除本页车牌与结果。'
    try { navi.value?.setActive(false) } catch (_) {}
  }
}
function run(operation: (view: MapNaviViewContext) => void): void {
  if (exited || !visible) return
  try { if (navi.value === null) throw new Error('请先创建实例'); operation(navi.value) }
  catch (error) { const value = error as { errCode?: number }; output.value = '操作未完成,请检查状态与参数;错误码:' + (value.errCode ?? '未创建') }
}
function requestPermission(): void {
  if (exited || !visible || permissionId !== '') return
  permissionId = requestMapLocationPermission({
    timeoutMs: 60000,
    success: result => { if (!exited && visible) output.value = `权限 ${result.state} / 精度 ${result.accuracy} / 服务 ${result.serviceEnabled}` },
    fail: error => { if (!exited && visible) output.value = '授权未完成:' + error.errCode },
    complete: () => { permissionId = '' }
  })
}
function createView(): void {
  if (exited || !visible) return
  const capabilities = getMapNaviCapabilities(), status = getMapStatus(), permission = getMapLocationPermission(), global = getMapNaviState()
  if (!capabilities.supported || !status.initialized || !status.privacy.agreed || permission.state !== 'granted' || !permission.serviceEnabled || global.busy) {
    output.value = '请检查平台、初始化、前台授权和系统服务;回收中不能创建新实例。'
    return
  }
  viewKey.value += 1; active.value = true; mounted.value = true
}
function query(): MapNaviCalculateOptions {
  return {
    start: { position: { latitude: 39.9042, longitude: 116.4074 }, name: '起点', poiId: '' },
    end: { position: { latitude: 39.9841, longitude: 116.3075 }, name: '终点', poiId: '' },
    waypoints: [{ position: { latitude: 39.938, longitude: 116.36 }, name: '途经点', poiId: '' }],
    strategy: 10,
    vehicle: { vehicleType: 0, plateNumber: plate.value.trim(), avoidRestrictions: plate.value.trim() !== '' },
    timeoutMs: 30000
  }
}
function calculate(): void { run(view => { output.value = '请求ID:' + view.calculate(query()) }) }
function calculateFromHere(): void { const options = query(); options.start = null; run(view => { output.value = '当前位置请求:' + view.calculate(options) }) }
function readRoutes(): void {
  run(view => {
    const result = view.getRoutes(), route = result.routes[0]
    if (route == null) return
    view.selectRoute(route.routeId)
    output.value = `本代${result.generation},${result.coordinateType};SDK键${route.sdkRouteId},路径标识${route.nativePathId ?? '未提供'};${route.distanceMeters ?? '未知'}米/${route.durationSeconds ?? '未知'}秒,费用${route.tollCostYuan ?? '未知'}元,红绿灯${route.trafficLightCount ?? '未知'},标签${route.labels.join('、')},真实轨迹${route.polyline.length}点`
  })
}
function start(mode: MapNaviMode): void {
  run(view => { if (mode === 'gps') view.start({ mode: 'gps' }); else view.start({ mode: 'emulator', emulatorSpeedKmh: 60 }) })
}
function toggleTraffic(): void { run(view => { const next = !traffic.value; view.setTraffic(next); traffic.value = next }) }
function readState(): void { run(view => { const state = view.getState(), global = getMapNaviState(); output.value = `${state.phase}/${state.releaseState};当前模式${state.mode ?? '未启动'},待回执${state.pendingCalculation};全局占用${global.busy}` }) }
function onNaviEvent(event: MapNaviEvent): void {
  if (exited || !visible) return
  if (event.type === 'ready') output.value = '原生视图已就绪,请主动算路。'
  else if (event.type === 'calculate-start') output.value = '等待导航 SDK 真实方案:' + event.requestId
  else if (event.type === 'calculate-success' || event.type === 'route-selected' || event.type === 'route-updated') {
    if (event.routes !== null) output.value = `${event.routes.routes.length}个真实方案,所选${event.routes.selectedRouteId};请核对地图轨迹`
  } else if (event.type === 'progress' && event.info !== null) {
    const info = event.info
    output.value = `${info.currentRoad} → ${info.nextRoad};剩余${info.remainingDistanceMeters ?? '未知'}米/${info.remainingDurationSeconds ?? '未知'}秒,本段${info.stepRemainingDistanceMeters ?? '未知'}米/${info.stepRemainingDurationSeconds ?? '未知'}秒,平台转向码${info.maneuverCode ?? '未提供'}`
  } else if (event.type === 'location' && event.location !== null) {
    output.value = `${event.location.coordinateType}:${event.location.latitude},${event.location.longitude};${event.location.speedKmh ?? '未知'}km/h`
  } else if (event.type === 'gps-signal') output.value = `GPS原因${event.reason},平台等级${event.gpsSignalLevel ?? '未提供'}`
  else if (event.type === 'waypoint') output.value = '途经点 SDK 原索引:' + (event.waypointIndex ?? '未提供')
  else if (event.type === 'off-route' || event.type === 'traffic-reroute') output.value = 'SDK触发重算:' + event.type
  else if (event.type === 'navigation-start') output.value = 'SDK已报告导航开始:' + event.state.mode
  else if (event.type === 'error') output.value = `${event.errCode} ${event.errMsg},原生码${event.nativeErrorCode ?? '未提供'}`
  else if (event.type === 'arrive' || event.type === 'emulator-end' || event.type === 'stop' || event.type === 'destroyed' || event.type === 'calculate-cancel' || event.type === 'close-request') {
    output.value = `本次状态${event.type},释放${event.state.releaseState};再次使用需重建,不能复用旧凭据`
  }
}
onShow(() => { visible = true; checkPrivacy(); if (privacyTimer === null) privacyTimer = setInterval(checkPrivacy, 1000) })
onHide(() => { visible = false; try { navi.value?.setActive(false) } catch (_) {} })
onUnload(() => { exited = true; if (privacyTimer !== null) clearInterval(privacyTimer); privacyTimer = null; if (permissionId !== '') cancelMapLocationRequest(permissionId) })
</script>

<style>
.example { flex: 1; height: 100%; background-color: #f3f6f7; }
.navigation { width: 100%; height: 300px; }
.controls { flex: 1; padding: 12px; }
.action { min-height: 44px; margin-bottom: 8px; font-family: sans-serif; font-size: 14px; }
.plate { height: 44px; margin-bottom: 8px; padding: 10px; font-family: sans-serif; font-size: 14px; background-color: #ffffff; }
.output { font-family: sans-serif; font-size: 14px; line-height: 24px; color: #365766; white-space: normal; }
</style>

vehicleType 还可取2纯电客车/4插混客车,策略仅采用下表十项。车牌是本机用户输入,示例未写真实标识;不用车牌限行时设空车牌和 avoidRestrictions:false。模拟速度可选10/60/120等整速;GPS不传模拟速度。一个实例只启动一次,结束后应先核对全局释放,再按新key重建。原生 adapter 类 MapNaviController 供App自定义标准组件使用;普通页面优先直接使用 lizhao-map-navi,以获得完整挂载、ready交付与卸载清理。

步行、骑行与货车导航

下面是可替换上例的最小多方式页面;请先在接入配置中完成隐私、初始化和前台定位授权。切换方式前先停止并移除当前实例,再选择方式创建。页面隐藏时停止并移除自己的实例,重新显示后需主动创建,不自动恢复。步行和骑行不传客车、货车或途经点;货车参数与路线搜索中的参数互相独立。

<template>
  <view class="multi-navi">
    <view class="transport-options">
      <button v-for="item in choices" :key="item.value" class="multi-action" :disabled="mounted" @click="transport = item.value">{{ item.label }}</button>
    </view>
    <button class="multi-action" :disabled="mounted" @click="create">创建 {{ transport }} 导航</button>
    <lizhao-map-navi v-if="mounted" :key="revision" ref="navi" class="multi-map" :transport="transport" :active="active" :traffic="traffic" @navi-event="onEvent" />
    <button class="multi-action" :disabled="!prepared" @click="start('emulator')">按本方式速度模拟</button>
    <button class="multi-action" :disabled="!prepared" @click="start('gps')">开始 GPS 导航</button>
    <button class="multi-action" :disabled="!mounted" @click="stop">停止并移除本实例</button>
    <text class="multi-output">{{ output }}</text>
  </view>
</template>
<script setup lang="ts">
import { ref, onBeforeUnmount } from 'vue'
import { onHide } from '@dcloudio/uni-app'
import { getMapNaviCapabilities, getMapNaviState, getMapStatus, getMapLocationPermission } from '@/uni_modules/lizhao-map'
import type { MapNaviTransport, MapNaviMode, MapNaviViewContext, MapNaviCalculateOptions, MapNaviEvent } from '@/uni_modules/lizhao-map'
const choices: Array<{ value: MapNaviTransport; label: string }> = [
  { value: 'driving', label: '驾车' }, { value: 'walking', label: '步行' },
  { value: 'riding', label: '骑行' }, { value: 'truck', label: '货车' }
]
const transport = ref<MapNaviTransport>('walking'), navi = ref<MapNaviViewContext | null>(null)
const mounted = ref(false), active = ref(true), traffic = ref(false), prepared = ref(false), revision = ref(0)
const output = ref('选择方式后创建;切换方式需要先结束旧实例。')
function create(): void {
  const capabilities = getMapNaviCapabilities(), state = getMapNaviState(), status = getMapStatus(), permission = getMapLocationPermission()
  if (!capabilities.transports.includes(transport.value)) { output.value = '当前平台未开放此方式'; return }
  if (!status.initialized || !status.privacy.agreed || !status.privacy.shown || !status.privacy.contains || permission.state !== 'granted' || !permission.serviceEnabled || state.busy) {
    output.value = '请完成接入与定位授权,并等待旧导航资源释放'; return
  }
  revision.value++; prepared.value = false; active.value = true; traffic.value = false; mounted.value = true
}
function query(): MapNaviCalculateOptions {
  const base: MapNaviCalculateOptions = {
    start: { position: { latitude: 39.993308, longitude: 116.473199 }, name: '起点', poiId: '' },
    end: { position: { latitude: 39.998877, longitude: 116.481234 }, name: '目的地', poiId: '' }, timeoutMs: 30000
  }
  if (transport.value === 'walking' || transport.value === 'riding') return { ...base, strategy: 1001 }
  if (transport.value === 'truck') return { ...base, strategy: 10, waypoints: [], truck: {
    vehicleType: 1, plateNumber: '', avoidRestrictions: false, size: 2, heightMeters: 1.6, widthMeters: 2.5,
    lengthMeters: 6, grossWeightTons: 10, ratedLoadTons: 2, axles: 2, includeWeight: true
  } }
  return { ...base, strategy: 10, waypoints: [], vehicle: { vehicleType: 0, plateNumber: '', avoidRestrictions: false } }
}
function onEvent(event: MapNaviEvent): void {
  if (!mounted.value || !active.value) return
  output.value = event.state.transport + ' · ' + event.type + ' · ' + event.errCode
  if (event.type === 'ready') { try { navi.value?.calculate(query()) } catch (_) { output.value = '算路未受理,请检查参数与状态' } }
  if (event.routes !== null) output.value = event.routes.transport + ' · 实际方案数 ' + event.routes.routes.length
  prepared.value = event.state.phase === 'prepared' && event.state.releaseState === 'owned'
  if (event.type === 'error') output.value = event.errMsg
}
function start(mode: MapNaviMode): void {
  if (!mounted.value || !active.value || !prepared.value) return
  if (mode === 'gps' && getMapLocationPermission().accuracy !== 'full') { output.value = 'GPS导航需要精确位置授权'; return }
  const profile = getMapNaviCapabilities().transportProfiles.find(item => item.transport === transport.value)
  if (profile === undefined) { output.value = '未取得本方式能力'; return }
  try {
    navi.value?.start(mode === 'gps' ? { mode: 'gps' } : { mode: 'emulator', emulatorSpeedKmh: profile.emulatorSpeedDefaultKmh })
    output.value = '已提交启动,请等待真实 navigation-start 事件'
  } catch (_) { output.value = '启动未受理,请核对权限、路线与本方式参数' }
}
function stop(): void { try { navi.value?.stop() } catch (_) { output.value = '停止未确认,请核对全局回收状态' } finally { prepared.value = false; active.value = false; mounted.value = false } }
onHide(stop)
onBeforeUnmount(() => { try { navi.value?.destroy() } catch (_) {} })
</script>
<style>
.multi-navi { flex: 1; }
.transport-options { flex-direction: row; flex-wrap: wrap; }
.multi-map { height: 300px; width: 100%; }
.multi-action { min-height: 44px; margin: 4px; font-size: 14px; }
.multi-output { margin: 12px; font-size: 14px; line-height: 24px; white-space: normal; }
</style>

读取 transportProfiles 可取得本方式速度、途经点上限与 trafficLayer。iOS步行/骑行的交通图层能力为false,不能打开组件traffic或调用setTraffic;这不会影响真实路线预览和导航。鸿蒙步行/骑行使用公开普通算路接口,取消、超时或退出后若无法安全确认回执归属,资源可能持续占用;请读取全局状态,仍未释放时需重启应用。货车服务、真实GPS/模拟与内置语音需要有效高德Key、相应服务和匹配原生环境。

巡航与中文系统语音

巡航需要先在接入配置完成隐私、初始化及精确定位授权;系统语音只需要真实隐私同意、前台和可用中文系统资源。下面保留两者的资源边界:播报前先结束自己的导航组件,读取两类占用,不能用空闲倒计时代替释放确认。完整字段及失败处理见 example/uniappx/cruise.uvue。

<template>
  <view>
    <view v-if="mounted" class="cruise-map">
      <LizhaoMapNavi ref="view" transport="driving" :voice-enabled="false" @navi-event="onNavi" />
    </view>
    <button @click="create">创建巡航实例(初始静音)</button>
    <button :disabled="!ready" @click="startCruise">启动设施和电子眼检测</button>
    <button :disabled="!ready" @click="enableVoice">启用本实例播报</button>
    <button @click="closeCruise">结束自己的巡航</button>
    <button @click="speak">播报中文提示</button>
    <button @click="stopSpeech">停止自己的播报</button>
    <button @click="refresh">读取释放状态</button>
    <text>{{ output }}</text>
  </view>
</template>
<script setup lang="ts">
import { ref, onBeforeUnmount } from 'vue'
import { onHide } from '@dcloudio/uni-app'
import LizhaoMapNavi from '@/uni_modules/lizhao-map/components/lizhao-map-navi/lizhao-map-navi.uvue'
import { getMapNaviState, getMapSpeechState, getMapSpeechCapabilities, speakMapText, stopMapSpeech } from '@/uni_modules/lizhao-map'
import type { MapNaviViewContext, MapNaviEvent } from '@/uni_modules/lizhao-map'
const view = ref<MapNaviViewContext | null>(null)
const mounted = ref(false), ready = ref(false), output = ref('等待主动操作')
let speechId = '', leaving = false
function fail(error: unknown): void { if (!leaving) output.value = '操作未完成:' + String((error as { errCode?: number }).errCode ?? 9101024) }
function refresh(): void { try { const n = getMapNaviState(), s = getMapSpeechState(); output.value = '导航占用=' + n.busy + ';语音占用=' + s.busy + ';语音回收=' + s.releaseState } catch (e) { fail(e) } }
function create(): void {
  try { if (getMapNaviState().busy || getMapSpeechState().busy) { refresh(); return }; mounted.value = true } catch (e) { fail(e) }
}
function startCruise(): void { try { view.value?.startCruise({ mode: 3, startupTimeoutMs: 60000 }); ready.value = false } catch (e) { fail(e) } }
function enableVoice(): void { try { view.value?.setVoiceEnabled(true); output.value = '内置播报配置=' + view.value?.getState().voiceEnabled } catch (e) { fail(e) } }
function onNavi(e: MapNaviEvent): void {
  if (leaving) return
  if (e.type === 'ready') ready.value = true
  if (e.type === 'cruise-start') output.value = '已收到巡航专属回执;位置确认=' + e.state.locationConfirmed
  if (e.cruise !== null) {
    const c = e.cruise
    if (c.kind === 'statistics') output.value = c.statistics === null ? '本次统计未提供' : '距离=' + String(c.statistics.distanceMeters) + '米;时间=' + String(c.statistics.elapsedSeconds) + '秒'
    else if (c.kind === 'facilities' || c.kind === 'cameras') output.value = c.facilities === null ? '本次未提供设施数组' : '本次设施数=' + c.facilities.length
    else output.value = c.congestion === null ? '本次拥堵已清除' : c.congestion.roadName + ':' + String(c.congestion.lengthMeters) + '米'
  }
  if (e.type === 'error') output.value = e.errMsg
}
function closeCruise(): void { try { view.value?.stop() } catch (e) { fail(e) }; mounted.value = false; ready.value = false }
function speak(): void {
  try {
    const cap = getMapSpeechCapabilities()
    if (!cap.supported || getMapNaviState().busy || getMapSpeechState().busy) { refresh(); return }
    speechId = speakMapText({ text: '请确认当前位置与道路情况。', language: 'zh-CN', timeoutMs: 60000, onEvent: e => {
      if (leaving || e.requestId !== speechId) return
      output.value = e.type + ';实际语言=' + String(e.state.actualLanguage) + ';错误=' + e.errCode
      if (e.type === 'complete' || e.type === 'stop' || e.type === 'error') refresh()
    } })
  } catch (e) { fail(e) }
}
function stopSpeech(): void { try { if (speechId !== '') stopMapSpeech(speechId); refresh() } catch (e) { fail(e) } }
onHide(() => { closeCruise(); stopSpeech() })
onBeforeUnmount(() => { leaving = true; try { if (speechId !== '') stopMapSpeech(speechId) } catch (_) {} })
</script>
<style>
.cruise-map { height: 280px; width: 100%; }
</style>

cruise-starting 只表示已提交;专属统计、设施、电子眼或拥堵的真实回执(包含真实空/清除)才确认 cruising。统计可能需要移动才返回;只有位置不能证明巡航专属数据已生效。停止后此实例不能再次启动。语音回调终态仍可能 busy=true,再次使用前读状态;主动停止立即取消自己的排队用户回调,资源回收由 getMapSpeechState() 确认。

离线城市目录和单项管理

先完成隐私和地图初始化。固定 SDK 11+ 的离线地图需要高德高阶服务开通,supported=true 只表示接口可用,不能证明 Key 已获授权。离线包用于底图,搜索、定位和导航分别按其 SDK 条件运行。完整目录筛选、任务、手动地图坐标和日志见 example/uniappx/offline.uvue。

import { startMapOfflineSession, stopMapOfflineSession, getMapOfflineCatalog,
  downloadMapOfflineCity, pauseMapOfflineCity, resumeMapOfflineCity, removeMapOfflineCity,
  getMapOfflineState, getMapOfflineCapabilities } from '@/uni_modules/lizhao-map'
import type { MapOfflineAction, MapOfflineCity, MapOfflineEvent } from '@/uni_modules/lizhao-map'

let sessionId = '', operationId = '', selected: MapOfflineCity | null = null
function failure(error: unknown): void { console.log('离线操作失败', error) }
function receive(event: MapOfflineEvent): void {
  if (event.sessionId !== sessionId) return
  if (event.type === 'ready' && event.catalog !== null) {
    const catalog = event.catalog
    console.log('目录', catalog.generation, catalog.version, catalog.cities.length)
    selected = catalog.cities.length > 0 ? catalog.cities[0] : null
    if (selected !== null) console.log(selected.id, selected.name, selected.cityCode, selected.adCode, selected.actions)
  }
  if (event.operationId !== '' && event.operationId !== operationId) return
  if (event.city !== null) {
    selected = event.city
    console.log('实际阶段', selected.status, selected.nativeStatus, selected.nativeDownloadStatus,
      selected.progressPercent, selected.packageBytes, selected.downloadedBytes, selected.expectedDownloadBytes)
  }
  if (event.type === 'download-complete') console.log('SDK确认已完成', event.reason)
  if (event.type === 'paused') console.log('SDK确认已暂停')
  if (event.type === 'removed') console.log('所选项SDK缓存已移除', event.reason)
  if (event.type === 'error') console.log(event.errCode, event.nativeErrorCode, event.reason)
  console.log('owner与管线', event.state.busy, event.state.pending, event.state.releaseState)
}
export function openOffline(): void {
  try {
    const capabilities = getMapOfflineCapabilities()
    if (!capabilities.supported) { console.log(capabilities.note); return }
    console.log(capabilities.requiresAdvancedService, capabilities.deleteConfirmation)
    sessionId = startMapOfflineSession({ timeoutMs: 30000, onEvent: receive })
  } catch (error) { failure(error) }
}
export function refreshOfflineCatalog(): void {
  try {
    const catalog = getMapOfflineCatalog(sessionId)
    selected = catalog.cities.find(city => city.id === selected?.id) ?? null
    console.log('真实快照', catalog.timestamp, catalog.cities)
  } catch (error) { failure(error) }
}
export function operateOffline(action: MapOfflineAction): void {
  try {
    const city = selected
    if (city === null || !city.actions.includes(action)) return
    const options = { sessionId: sessionId, cityId: city.id,
      timeoutMs: action === 'download' || action === 'resume' ? 900000 : 60000 }
    if (action === 'download') operationId = downloadMapOfflineCity(options)
    if (action === 'pause') operationId = pauseMapOfflineCity(options)
    if (action === 'resume') operationId = resumeMapOfflineCity(options)
    // UI先明确提示删除范围并确认,再调用这一分支;确认后重新核对会话和城市身份。
    if (action === 'remove') operationId = removeMapOfflineCity(options)
  } catch (error) { failure(error) }
}
// 页面退出时调用。主动停止立即静默自己的回调;已下载数据保留。
export function closeOffline(): void {
  const ownId = sessionId
  sessionId = ''; operationId = ''; selected = null
  try { stopMapOfflineSession(ownId) } catch (error) { failure(error) }
  try { console.log('实际回收状态', getMapOfflineState()) } catch (error) { failure(error) }
}

城市 id 是当前会话目录中的不透明凭据;新会话应重取,不能用城市区号或行政区码替代。busy 表示会话拥有资源,目录就绪时仍为 true;pending 才表示未决 SDK 任务。会话最多一项任务,暂停可以接管自己下载/恢复的停止意图。返回操作 ID 仅代表受理,真实完成以对应事件为准。

Android/鸿蒙的阶段百分比可能从下载 100 回到解压 0,100 不能当作完成,也不能反推字节。iOS 的网络下载完成也不等于解压完成。解压阶段不保证能暂停;暂停先遇到完整安装时可能返回 download-complete。请求尚未提交 SDK 就被取消时返回错误 9101014,不伪报已暂停。

鸿蒙固定 SDK 的下载回执没有请求 ID。同一城市失败后重试,若在新活动确认前收到与旧初态相同的错误,插件无法可靠归属该回执,会发 error(9101027,reason='ambiguous-download-receipt')结束用户等待,并保留 busy=true / releaseState='uncertain'。后续只处理自己任务的安全停止与确认;没有可确认回执时不能强制重建,可能需要重启应用。重复暂停不会替换已经等待确认的暂停请求。

聚合、热力、海量点、点移动与地图截图

在已完成隐私和初始化的 App 中,等待本组件 map-event 的 ready 后操作。以下代码可放入一个页面;完整参数、状态与日志示例见 example/uniappx/advanced-map/advanced-map.uvue。

宿主须在页面 onHide 设置 active=false,在 onShow 恢复,退出时卸载组件。Android、鸿蒙的高级地图前台门禁依赖这项生命周期转发;iOS另检查系统App状态。foregroundOnly=true 表示前台使用约束,不表示各端都自动观察整个App后台,也不提供后台点移动、截图或自动续播。

<template>
  <view>
    <LizhaoMap ref="map" style="height: 300px;" :active="active"
      @map-event="onMapEvent" @advanced-event="onAdvancedEvent" />
    <button :disabled="!ready" @click="installLayers">创建三种数据层</button>
    <button :disabled="!ready" @click="inspectClusters">读取聚合</button>
    <button :disabled="!ready" @click="changeVisibility">隐藏/显示聚合</button>
    <button :disabled="!ready" @click="removeCluster">移除聚合</button>
    <button :disabled="!ready" @click="movePoint">移动专属点</button>
    <button :disabled="moveId === ''" @click="stopMove">停止本次移动</button>
    <button :disabled="!ready" @click="snapshotMap">截取地图</button>
    <button :disabled="snapshotId === ''" @click="cancelSnapshot">取消截图等待</button>
    <button :disabled="savedImageId === ''" @click="removeImage">删除本图临时文件</button>
    <button :disabled="!ready" @click="readState">读取高级状态</button>
    <button :disabled="!ready" @click="clearAdvanced">清理高级资源</button>
    <text>{{ message }}</text>
  </view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { onHide, onShow, onUnload } from '@dcloudio/uni-app'
import LizhaoMap from '@/uni_modules/lizhao-map/components/lizhao-map/lizhao-map.uvue'
import { getMapAdvancedCapabilities } from '@/uni_modules/lizhao-map'
import type { MapViewContext, MapEventDetail, MapAdvancedEvent } from '@/uni_modules/lizhao-map'
const map = ref<MapViewContext | null>(null), active = ref(true), ready = ref(false), message = ref('等待地图就绪')
const moveId = ref(''), snapshotId = ref(''), savedImageId = ref('')
let leaving = false, visible = true
const cap = getMapAdvancedCapabilities()
console.log(cap.platform, cap.supported, cap.clusterAlgorithm, cap.heatmapRadiusUnit, cap.note)
function run(operation: (view: MapViewContext) => void): void {
  if (leaving || !cap.supported || !ready.value || map.value === null) return
  try { operation(map.value) }
  catch (error) { const failure = error as { errCode?: number }; message.value = `操作失败:${failure.errCode ?? 9101028}` }
}
function onMapEvent(event: MapEventDetail): void { if (!leaving) ready.value = event.type === 'ready' || ready.value && event.type !== 'error' && event.type !== 'destroyed' }
function installLayers(): void { run(view => {
  const points = [
    { id: '0', coordinate: { latitude: 39.9042, longitude: 116.4074 } },
    { id: '地点二', coordinate: { latitude: 39.906, longitude: 116.409 } }
  ]
  view.setMarkerClusters({ id: 'clusters', points, gridSize: 60, visible: true })
  view.setHeatmap({ id: 'heat', points: points.map((point, index) => ({ coordinate: point.coordinate, weight: index === 0 ? 0 : 1 })), radius: 12, opacity: 0, visible: false })
  view.setMultiPoints({ id: 'multi', points, iconSize: 12, visible: true })
}) }
function inspectClusters(): void { run(view => { const groups = view.getMarkerClusters('clusters'); message.value = groups.map(group => `${group.id}:${group.count}项 ${group.memberIds.join(',')},${group.coordinate.latitude},${group.coordinate.longitude}`).join('\n') || '当前视口内没有聚合点' }) }
function changeVisibility(): void { run(view => { view.setAdvancedLayerVisible({ kind: 'cluster', id: 'clusters' }, !visible); visible = !visible }) }
function removeCluster(): void { run(view => view.removeAdvancedLayer({ kind: 'cluster', id: 'clusters' })) }
function movePoint(): void { run(view => { moveId.value = view.startPointMove({ points: [{ latitude: 39.9042, longitude: 116.4074 }, { latitude: 39.906, longitude: 116.409 }], durationSeconds: 20, timeoutMs: 50000 }) }) }
function stopMove(): void { run(view => { view.stopPointMove(moveId.value); moveId.value = ''; readState() }) }
function snapshotMap(): void { run(view => { snapshotId.value = view.takeMapSnapshot({ timeoutMs: 30000 }) }) }
function cancelSnapshot(): void { run(view => { view.cancelMapSnapshot(snapshotId.value); snapshotId.value = ''; readState() }) }
function removeImage(): void { run(view => { view.removeMapSnapshot(savedImageId.value); savedImageId.value = '' }) }
function readState(): void { run(view => { const state = view.getAdvancedState(); message.value = JSON.stringify({ platform: state.platform, instanceId: state.instanceId, active: state.active, ready: state.ready, layers: state.layers, move: state.move, snapshot: state.snapshot, snapshots: state.snapshots, retiredMoves: state.retiredMoves, errCode: state.errCode, nativeErrorCode: state.nativeErrorCode, reason: state.reason }) }) }
function clearAdvanced(): void { run(view => { view.clearAdvancedLayers(); moveId.value = ''; snapshotId.value = ''; savedImageId.value = ''; readState() }) }
function onAdvancedEvent(event: MapAdvancedEvent): void {
  if (leaving) return
  console.log(event.type, event.instanceId, event.requestId, event.layerKind, event.layerId, event.layerGeneration, event.sequence, event.timestamp, event.state)
  if (event.type === 'cluster-click' && event.cluster !== null) console.log(event.cluster.coordinate, event.cluster.memberIds, event.cluster.count)
  if (event.type === 'multipoint-click' && event.point !== null) console.log(event.point.id, event.point.coordinate)
  if (event.move !== null) console.log(event.move.phase, event.move.busy, event.move.pending, event.move.releaseState, event.move.markerPresent, event.move.durationSeconds, event.move.remainingDistanceMeters, event.move.elapsedSeconds, event.move.passedPointCount, event.move.position, event.move.positionSource)
  if (event.type === 'move-complete' || event.type === 'move-error') moveId.value = ''
  if (event.type === 'snapshot-ready' && event.snapshot !== null) {
    savedImageId.value = event.snapshot.id
    const image = event.snapshot
    message.value = `${image.width}×${image.height}物理像素,完整度:${image.complete === null ? 'SDK未确认' : image.complete ? '完整' : '未完整'},原状态${image.renderStatus ?? '无'},时间${image.timestamp},临时路径${image.path}`
  }
  if (event.type === 'snapshot-ready' || event.type === 'snapshot-error') snapshotId.value = ''
  if (event.errCode !== 0) message.value = `错误${event.errCode},原码${event.nativeErrorCode ?? '无'},${event.reason};占用以event.state为准`
}
onShow(() => { if (!leaving) active.value = true })
onHide(() => { if (!leaving) active.value = false })
onUnload(() => { leaving = true }) // 组件卸载释放自己的资源,不在onUnload重置响应式挂载条件
</script>

takeMapSnapshot() 也允许省略整个参数。同步返回的 ID 只表示本请求已受理;移动活动、完成或截图由 advanced-event 通知。取消会立即停止向用户交付该请求,但 SDK 没有取消能力时仍保留 busy/pending。截图成功可以是未完整渲染的 PNG,不能把状态 0 或 complete=null 当成完整;临时图需要长期保存时,应在组件销毁前由宿主自行复制。

前台围栏完整调用

先完成隐私与SDK初始化,并由用户主动取得精确定位授权、开启系统定位服务。围栏启动不会弹授权框;ready只表示本地通道准备完成。以下页面手动输入GCJ-02中心,不自动提交预设城市。完整示例包含三标签、真实记录、按需地图、参数、状态和有界日志。

<template>
  <view>
    <input v-model="businessId" placeholder="业务ID,1至64字符" />
    <input v-model="latitude" placeholder="GCJ-02纬度" />
    <input v-model="longitude" placeholder="GCJ-02经度" />
    <button @click="start">准备会话</button>
    <button :disabled="!ready" @click="add">注册圆形围栏</button>
    <button :disabled="sessionId.length === 0" @click="remove">移除输入ID</button>
    <button @click="refresh">读取自有记录与管理状态</button>
    <button @click="stop">结束本会话</button>
    <text>{{ message }}</text>
    <text v-for="item in records" :key="item.requestId">{{ item.id }} · {{ item.phase }} · {{ item.lastRelation ?? '尚无关系回执' }}</text>
  </view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { onHide, onUnload } from '@dcloudio/uni-app'
import { startMapGeofenceSession, addMapCircleGeofence, removeMapGeofence, stopMapGeofenceSession,
  getMapGeofences, getMapGeofenceState, getMapGeofenceCapabilities } from '@/uni_modules/lizhao-map'
import type { MapGeofenceEvent, MapGeofenceInfo } from '@/uni_modules/lizhao-map'
const businessId = ref(''), latitude = ref(''), longitude = ref(''), sessionId = ref('')
const ready = ref(false), message = ref('等待操作'), records = ref<MapGeofenceInfo[]>([])
let exited = false
function report(error: unknown) { const value = error as { errCode?: number }; message.value = `操作失败:${value.errCode ?? 9101029}` }
function receive(event: MapGeofenceEvent) {
  if (exited || event.sessionId !== sessionId.value) return
  if (event.type === 'ready') ready.value = true
  else if (event.type === 'registered') message.value = `SDK已确认注册;请求 ${event.requestId}`
  else if (event.type === 'status') message.value = `${event.fence?.lastRelation ?? '未知'};${event.firstObservation === true ? '首次关系观察,可能是初态' : '后续SDK关系观察'}`
  else if (event.type === 'removed') message.value = 'SDK名单已观察不到该自有圆;这不证明OS定位线程停止'
  else message.value = `围栏错误 ${event.errCode};原生码 ${event.nativeErrorCode ?? '未提供'}`
  if (event.state === null) message.value += ';管理状态未知,请重新读取'
  refresh()
}
function start() {
  try {
    const cap = getMapGeofenceCapabilities()
    if (!cap.supported) { message.value = cap.note; return }
    sessionId.value = startMapGeofenceSession({ startupTimeoutMs: 30000, onEvent: receive })
    ready.value = false; message.value = '会话已受理,等待本地ready'
  } catch (error) { report(error) }
}
function add() {
  if (latitude.value.trim().length === 0 || longitude.value.trim().length === 0) { message.value = '请完整填写中心坐标'; return }
  try {
    const requestId = addMapCircleGeofence({ sessionId: sessionId.value, id: businessId.value,
      center: { latitude: Number(latitude.value), longitude: Number(longitude.value) }, radiusMeters: 1000, timeoutMs: 30000 })
    message.value = `注册已受理:${requestId},等待真实SDK回执`
  } catch (error) { report(error) }
}
function remove() { try { removeMapGeofence({ sessionId: sessionId.value, id: businessId.value }); refresh() } catch (error) { report(error) } }
function refresh() {
  try {
    const state = getMapGeofenceState()
    ready.value = ready.value && state.sessionId === sessionId.value && state.phase === 'ready' && state.deliveryMode === 'open'
    if (sessionId.value.length > 0) records.value = getMapGeofences(sessionId.value)
  } catch (error) { report(error) }
}
function stop() {
  try { stopMapGeofenceSession(sessionId.value); ready.value = false; refresh() } catch (error) { report(error) }
}
onHide(() => { if (!exited) stop() })
onUnload(() => { exited = true; try { stopMapGeofenceSession(sessionId.value) } catch (_) {} })
</script>

业务ID在同一会话内不可覆盖,正常移除并确认名单缺失后才可重用。remove立即静默该项尚未交付的注册/关系数据;未决SDK注册仍保留占用,迟到结果只用于清理。stop先静默整会话,不交付后续关闭成功事件,调用方主动读状态。再次启动需真实busy=false,后台返回不自动续启。

搜索到模拟导航的完整串联

宿主注册完整示例路由后可直接打开:

uni.navigateTo({ url: '/uni_modules/lizhao-map/example/uniappx/journey' })
步骤 公开能力 实际行为
选择地点 searchMapPois、cancelMapSearchRequest 主动检索并分别选择两个真实地点;无坐标项不能成为端点,0坐标合法,改条件使旧选择与预览失效
预览路线 planMapRoute、cancelMapRouteRequest、地图标准组件 Search驾车推荐策略32,显示真实方案、来源、单位与分段轨迹;不同step不拼接成假连线,缺失几何不补端点直线
进入模拟 getMapNaviCapabilities、getMapNaviState、导航标准组件 核对隐私/初始化、前台授权与服务、能力及真实占用,以Navi推荐策略10重新算路;到达导航页后仍需用户核对并点击启动模拟

Search策略32与Navi策略10分别属于不同引擎,不互转数值。当前Search方案只用于预览,不将其path.id、结果DTO或轨迹点组当成Navi路径凭据;新算路结果可能不同。模拟也可能使用SDK内部定位,不能绕过现有授权或资源门禁。

页面交接复用示例内navigation-demo-state.ts。它深拷贝起终点、可用POI标识和模拟设置,只保存在当前进程;URL只带不透明handoff关联ID,不携坐标、地点名、搜索正文或载荷。展示页只按准确ID消费一次,来源只信本地交接记录。旧页的迟到失败或卸载只能清自己的ID,不能清后来准备的行程;进入子页引发父页隐藏时不提前清掉待消费数据。

从串联页进入后,“退出”返回原串联页;空态/恢复入口也保留可信来源。直接重开旧URL或刷新使进程内交接缺失时,不会自动恢复旧坐标、创建导航或启动模拟,需重新准备。关键词、坐标、地点标识与交接ID不进入示例日志。完整独立搜索、五方式路线、四方式/GPS/货车参数仍在各自页面。

模块化示例

模块 前置条件 完整演示位置 对应操作
隐私 宿主完成政策展示 example/uniappx/setup.uvue 编辑三项隐私并应用配置
初始化 同意隐私,填写 Key example/uniappx/setup.uvue 初始化与重复调用
错误处理 支持的平台 example/uniappx/setup.uvue 空 Key 与隐私拒绝演示
状态 已导入插件 example/uniappx/setup.uvue 查询能力、状态、复制日志
相机与区域 初始化并等待地图就绪 example/uniappx/map.uvue 五项相机输入、实际读数与可视边界
图层与手势 地图就绪 example/uniappx/map.uvue 地图类型、路况、控件和手势
多实例与事件 初始化 example/uniappx/map.uvue 独立参数、点击/长按、销毁和重建
前台权限与定位 隐私已同意;定位还需初始化 example/uniappx/location.uvue 只读权限、系统申请、单次、取消、设置与地图联动
标记与气泡 初始化并等待地图就绪 example/uniappx/overlays.uvue 两标记、图片、样式、拖动、实际位置与气泡能力
线面与管理 地图就绪 example/uniappx/overlays.uvue 折线/圆/面绘制与更新、ID清单、移除、清空、范围适配与事件
持续与后台定位 隐私、初始化、前台定位授权;后台另需系统条件 example/uniappx/tracking.uvue 启停、条件与通知、原生轨迹及地图联动
输入提示 隐私与初始化 example/uniappx/search.uvue 主动获取、无ID/无坐标分支、按词搜索和真实点联动
POI与详情 隐私与初始化 example/uniappx/search.uvue 四种模式、成功条件翻页、五组扩展、三请求隔离和60条日志
地址与行政区 隐私与初始化 example/uniappx/geocoding.uvue 编码/逆编码、完整字段、树与边界、取消和真实地图
SDK测量与转换 隐私与初始化;投影另需地图ready example/uniappx/tools.uvue 距离/两类面积、八来源转换、实例投影、距离矩阵与逐项失败
路线与方案选择 隐私与初始化;绘图另需地图ready example/uniappx/routes.uvue 五种方式、参数、途经/避让、多方案、公交备选与真实分段地图
驾车导航 隐私、初始化、前台定位与系统服务;GPS另需精确位置 example/uniappx/navigation.uvue、navigation-view.uvue 参数与模式、真实Navi方案、导航图面、实时/日志、停止/退出/重建
巡航与语音 巡航同GPS定位条件;独立语音只需隐私、前台和中文系统资源 example/uniappx/cruise.uvue 巡航准备/启动/真实数据、初始与运行播报开关、中文文本/等待期限/停止及回收读数
离线底图 隐私、初始化、前台和高阶离线授权 example/uniappx/offline.uvue 目录筛选与分页、下载/暂停/恢复/确认删除、任务状态、手动地图和日志
地图进阶 隐私、初始化、前台与本地图ready example/uniappx/advanced-map/advanced-map.uvue 三种数据层、显隐/移除/读取、点移动、地图截图、临时图回收与状态
前台圆形围栏 隐私、初始化、精确授权与系统定位服务 example/uniappx/geofence.uvue 显式会话、真实注册和关系、名单/状态、自有移除与退出清理
完整业务串联 真实地点选择、Search方案及导航接入条件 example/uniappx/journey.uvue 独立端点搜索、真实分段预览、一次性交接、Navi重新算路与主动模拟

可将初始化封装为以下业务函数,页面直接传入 Key 与真实隐私状态。

import { setMapPrivacy, initializeMap } from '@/uni_modules/lizhao-map'
import type { MapPrivacyOptions } from '@/uni_modules/lizhao-map'

export function startMap(apiKey: string, privacy: MapPrivacyOptions) {
  setMapPrivacy(privacy)
  return initializeMap({ apiKey: apiKey })
}

多个 LizhaoMap 组件会生成独立实例。每个实例使用各自的 ref、camera、options;通过 event.instanceId 记录事件,不把一个实例的相机目标回写到另一个实例。

API 用途速查

模块 适用业务 常用方法 使用结果
隐私 同意和撤回 setMapPrivacy(options) 成功返回 void,失败抛出 MapFail
配置 绑定当前平台 Key initializeMap(options) MapInitResult,失败抛出 MapFail
状态 页面恢复与提示 getMapStatus() MapStatus
能力 展示功能入口 getMapCapabilities() MapCapabilities
组件 原生地图视图 LizhaoMap 通过 ref 暴露 MapViewContext
相机 移动与查询 setCamera、getCamera、getBounds 实际相机及可视包围盒
图层 类型、路况和手势 setOptions 当前实例立即应用或排队至加载完成
生命周期 暂停、恢复、销毁 setActive、destroy 销毁幂等,重建需要新组件
标记 新增或完整替换 upsertMarkers 按业务 ID 管理,支持真实拖动事件
图形 绘制或替换线、圆、面 upsertPolylines、upsertCircles、upsertPolygons 当前实例的几何、样式、显隐与层级
气泡与读数 显示文字、读取实际坐标与能力 setMarkerCallout、getMarkerPosition、getOverlayCapabilities 不支持多个默认气泡时明确返回能力限制
对象管理 清单、移除与清空 getOverlaySummary、removeOverlays、clearOverlays 清单包含隐藏对象,移除幂等且按实例/类型隔离
范围 将多个坐标适配到视口 fitCoordinates 使用实际视口和逻辑像素 padding,不支持极区/跨日期线输入
权限 查询与申请前台定位 getMapLocationPermission、requestMapLocationPermission 系统权限、精度授权及服务开关
定位 获取一次真实位置 getMapLocation 可取消 ID,结果通过回调返回
持续会话 用户主动启停及读状态 startMapLocationSession、stopMapLocationSession、getMapLocationSessionState 开始同步返回会话ID,事件异步;与单次定位互斥
后台接入 检查条件、主动申请通知 getMapLocationBackgroundStatus、requestMapLocationNotificationPermission 纯查询不申请权限、不创建频道;通知等待用既有取消API
轨迹 读取或清空原生缓冲 getMapLocationSessionTrack、clearMapLocationSessionTrack 最近受理会话快照;清空不停止、不重置累计序号
定位请求 结束等待、恢复授权 cancelMapLocationRequest、openMapLocationSettings 取消幂等,设置返回后重查权限
输入提示 查询候选词或地点 getMapInputTips(options) 返回请求ID,success交付真实提示数组
POI列表 按词、周边或几何范围检索 searchMapPois(options) 返回请求ID,规范化query、本页items和原始count
地点详情 用实际POI ID读取字段 getMapPoiDetail(options) 返回请求ID,requestedId及完整poi结构
搜索取消 结束指定ID的等待 cancelMapSearchRequest(requestId) 幂等void,只处理本插件搜索请求
搜索能力 按端展示可用功能 getMapSearchCapabilities() 纯查询MapSearchCapabilities,不建SDK请求
搜索状态 查看自有请求记录 getMapSearchState() 纯查询MapSearchState,不表示网络连接数量
地址匹配 结构化地址转坐标 geocodeMapAddress(options) 请求ID,候选地址/匹配级别和真实坐标
逆编码 坐标转结构化地址与附近信息 reverseGeocodeMapCoordinate(options) 请求ID,地址组件/道路/路口/POI/AOI
行政区 查询层级与边界 searchMapDistricts(options) 请求ID,原始count、树及多段边界
距离矩阵 多起点到单终点 getMapDistanceMatrix(options) 请求ID,实际SDK行、输入编号及逐项状态
地理请求管理 只取消自己持有的ID cancelMapGeoRequest、getMapGeoState、getMapGeoCapabilities 独立地理查询记录与能力,不混入地点搜索
路线规划 五种出行方式的方案预览 planMapRoute ID、查询快照、多方案、路段、交通与公交换乘
路线管理 取消自己持有的ID及纯状态查询 cancelMapRouteRequest、getMapRouteCapabilities、getMapRouteState 独立四条自有记录、策略与平台差异
SDK计算 距离/面积/来源坐标转换 calculateMapDistance、calculateMapArea、convertMapCoordinate 同步SDK结果或抛MapFail,不占地理请求槽
地图投影 当前实例坐标与像素互转 coordinateToScreen、screenToCoordinate 同步MapScreenPoint或MapCoordinate,须ready
导航与巡航 原生视图、真实Navi算路或无目的地检测 lizhao-map-navi、startCruise 本实例状态、路线或巡航数据与结束重建
内置播报 当前导航/巡航的语音配置 setVoiceEnabled 成功后从本实例voiceEnabled读取配置,非物理声音确认
系统语音 中文文本异步播报 speakMapText、stopMapSpeech 返回请求ID,事件表明开始/终态;主动停止后读getMapSpeechState
离线底图 会话目录与单城管理 startMapOfflineSession、getMapOfflineCatalog、downloadMapOfflineCity、pauseMapOfflineCity、resumeMapOfflineCity、removeMapOfflineCity、stopMapOfflineSession、getMapOfflineState、getMapOfflineCapabilities 会话/操作ID关联真实目录和事件;SDK授权、解压暂停与回收强度有平台边界
语音能力与占用 按端检查资源与回收 getMapSpeechCapabilities、getMapSpeechState 纯快照,不创建系统引擎、不触发定位
高级地图能力 判断平台与插件容量 getMapAdvancedCapabilities 纯能力声明,Web为unsupported;不保证设备负载表现
围栏会话 准备或结束自有前台会话 startMapGeofenceSession、stopMapGeofenceSession ready只为本地准备;stop先静默,未决SDK回执仍可能保占用
圆形围栏 注册或精确移除自有圆 addMapCircleGeofence、removeMapGeofence 真实registered与SDK关系事件;同ID不upsert,名单缺失不证明OS停止
围栏读取 自有名单、管理状态与能力 getMapGeofences、getMapGeofenceState、getMapGeofenceCapabilities 纯查询不创建SDK/定位;未知失败不伪造空名单
高级数据层 安装、显隐与读取聚合 setMarkerClusters、getMarkerClusters、setHeatmap、setMultiPoints、setAdvancedLayerVisible 三类各一层,真实SDK对象与网格投影缓存
高级资源管理 独立清理与读取状态 removeAdvancedLayer、clearAdvancedLayers、getAdvancedState 按实例和种类隔离,不操作普通覆盖物
点移动 输入路径启动与取消 startPointMove、stopPointMove 唯一请求ID与真实SDK回执,无统一暂停/百分比
地图区域截图 临时PNG及自己文件的回收 takeMapSnapshot、cancelMapSnapshot、removeMapSnapshot 请求ID、完整度三态、真实物理像素;不自动保存相册

配置、状态/能力读取、SDK本地工具和组件ref方法为同步接口;地点搜索和四类地理查询返回ID后异步交付结果。地图加载及变化通过 map-event 通知。相机/边界读取与投影需要等待ready,组件卸载释放原生地图与监听。

参数 类型 必填 说明 默认值 可选参数
MapInitOptions.apiKey string 是 当前平台 Key,首尾空格会清除 无 非空字符串
MapPrivacyOptions.shown boolean 是 已向用户展示政策 初始状态 false true / false
MapPrivacyOptions.contains boolean 是 政策中包含高德说明 初始状态 false true / false
MapPrivacyOptions.agreed boolean 是 用户同意隐私政策 初始状态 false true / false
字段 类型 说明
errMsg string 初始化成功为 initializeMap:ok
platform string android / ios / harmony / unsupported
sdkVersion string 本插件固定依赖的导航 SDK 版本
initialized boolean 本地 SDK 配置就绪,撤回隐私后为 false
keyConfigured boolean 本进程已绑定 Key,部分配置失败也可能为 true
authVerified boolean 当前仅配置 SDK,返回 false
privacy MapPrivacyOptions 最近提交的三项隐私状态
supported boolean 当前平台是否提供这些原生接口
availableFeatures string[] App按已实现能力返回配置、地图、覆盖物、定位、地点/地理查询、SDK工具、route-planning/route-state和driving-navigation/navigation-state;按实际返回数组判断
minimumOSVersion string 当前宿主最低系统要求
coordinateType string gcj02

字段读取代码见高级示例,errMsg 与初始化结果见简单示例。

地图组件与方法参数

camera、options 均传完整对象;省略整个属性时使用组件默认值。传入 false 或 0 会保留该值。

参数 类型 必填 说明 默认值 可选参数
camera / setCamera(camera) MapCamera 属性否,方法是 相机目标,GCJ-02 经纬度 北京中心、zoom=12、tilt=0、bearing=0 完整对象
camera.latitude number 是 纬度,度 39.9042 −90 至 90,有限数
camera.longitude number 是 经度,度 116.4074 −180 至 180,有限数
camera.zoom number 是 缩放级别,SDK 可能进一步限制 12 3 至 20
camera.tilt number 是 俯仰角,度,SDK 可能进一步限制 0 0 至 60
camera.bearing number 是 旋转角,度;360 等效于 0 0 0 至 360
options / setOptions(options) MapViewOptions 属性否,方法是 图层、控件与手势配置 下列默认组合 完整对象
options.mapType MapType 是 标准、卫星、夜间 normal normal / satellite / night
options.traffic boolean 是 显示实时路况 false true / false
options.compass boolean 是 启用 SDK 指南针,显隐也受地图旋转状态影响 true true / false
options.scale boolean 是 显示比例尺 true true / false
options.gestures.scroll boolean 是 拖动手势 true true / false
options.gestures.zoom boolean 是 缩放手势,与组件缩放按钮独立 true true / false
options.gestures.rotate boolean 是 旋转手势 true true / false
options.gestures.tilt boolean 是 俯仰手势 true true / false
active / setActive(active) boolean 属性否,方法是 请求暂停或恢复当前地图渲染 true true / false
zoom-controls boolean 否 组件右下方统一缩放按钮 true true / false

属性传递、ref 方法与页面显示/隐藏代码见完整示例。destroy() 无参数,重复调用安全;销毁后 getter 或更新方法返回 9101008。重建时先 v-if=false,等待 nextTick 后创建新的组件,不能向已绑定的同一个 native-view 再绑定另一原生地图。

字段 类型 说明
getCamera().latitude / longitude number 实际中心,GCJ-02,度
getCamera().zoom / tilt / bearing number 实际缩放级别、俯仰角与旋转角,可能不同于目标值
getBounds().southwest.latitude / longitude number 可视区域包围盒西南角,度
getBounds().northeast.latitude / longitude number 可视区域包围盒东北角,度

边界跨越日期变更线时,西南经度可能大于东北经度。读取四项边界和实际相机的代码见完整示例 inspectView。

地图事件

组件统一通过 @map-event 返回 MapEventDetail。

字段 类型 说明
instanceId string 独立地图 ID;创建前参数错误等情况下可能为空
type MapEventType ready / camera-change / map-click / map-long-press / error / destroyed;标记事件见下文
latitude / longitude number 当前实例实际中心或最后可用相机,度
zoom / tilt / bearing number 当前实例实际缩放和角度,错误/销毁事件可能使用最后缓存
pointLatitude / pointLongitude number 点击/长按点位或标记事件时的实际标记坐标,度
overlayType MapOverlayType 或空字符串,可选 标记事件为 marker,普通地图事件不使用此字段
overlayId string,可选 当前实例的业务标记 ID,普通地图事件为空或省略
errCode number 成功为 0,error 事件为统一错误码
errMsg string 成功为空,错误为可读说明,不含 Key

ready 表示加载就绪,恢复渲染时可能再次返回;camera-change 在相机变化结束时返回。组件等待约 25 秒未就绪会通知 9101010,随后原生加载成功仍可返回 ready。处理各类型、读取全部字段见完整示例和地图页的“实例与事件”标签。

标记事件为 marker-click、marker-callout-click、marker-drag-start、marker-drag、marker-drag-end。拖动读数来自原生对象,替换/移除后的旧对象事件会丢弃;高频拖动事件请自行按业务需要节流。onOverlayEvent 演示全部分支。当前不提供线/圆/多边形点击事件。

标准组件适配器

MapViewController 是标准组件使用的 App 原生容器适配器。普通页面使用上述组件和 ref 即可;需要自行封装标准组件时,必须在 native-view 的 init 事件中创建,每个元素只绑定一次。

参数 类型 必填 说明 默认值 可选参数
new MapViewController(element, camera, options) 的 element UniNativeViewElement 是 init 事件返回的原生元素 无 当前组件自己的元素
camera MapCamera 是 初始完整相机目标 无 范围见相机参数表
options MapViewOptions 是 初始完整地图配置 无 组合见地图参数表
// 仅限 App 标准组件脚本;camera/options 参数来自组件属性。
import { MapViewController } from '@/uni_modules/lizhao-map'
import type { MapCamera, MapViewOptions } from '@/uni_modules/lizhao-map'

function bindMap(element: UniNativeViewElement, camera: MapCamera, options: MapViewOptions) {
  const controller = new MapViewController(element, camera, options)
  controller.setActive(true)
  return controller
}

function releaseMap(controller: MapViewController): void {
  controller.release()
}

适配器提供同样的 MapViewContext 方法,另有 release() 供组件卸载时调用;iOS 会清理 SDK 监听与 JS 交付路由,失去引用的原生代理由运行时回收。适配器通过元素的 mapstate 事件传递上述字段,标准组件转发为 map-event。完整事件接线、卸载和错误处理见 components/lizhao-map/lizhao-map.uvue。

前台权限与单次定位参数

权限只读检查无参数、不弹系统框、不读取位置、不创建高德定位对象。申请权限要求三项隐私均同意,但不要求 SDK 初始化;单次定位另要求初始化完成、前台定位权限与系统定位服务可用,不隐式请求权限。

参数 类型 必填 说明 默认值 可选参数
requestMapLocationPermission(options) MapLocationPermissionOptions 是 系统前台权限请求 无 {} 或以下字段
options.timeoutMs(权限) number 否 结束等待的毫秒数,不能自动关闭 OS 弹窗 60000 整数 1000–120000
getMapLocation(options) MapLocationOptions 是 单次定位请求 无 {} 或以下字段
options.accuracy MapLocationAccuracy 否 期望高精度或均衡策略,不覆盖系统授权 high high / balanced
options.timeoutMs(定位) number 否 整体请求毫秒数,包括请求地址时的等待 10000 整数 1000–60000
options.needAddress boolean 否 请求 SDK 返回地址,可能增加等待 false true / false
options.success function 否 权限 / 定位 / 设置的对应结果 无 见完整示例
options.fail (error: MapFail) => void 否 统一失败,data 含请求 ID 与可用数字错误 无 见完整示例
options.complete () => void 否 成功或失败后交付一次 无 不带参数
openMapLocationSettings(options) MapLocationSettingsOptions 是 打开本应用授权管理页 无 success / fail / complete
cancelMapLocationRequest(requestId) string 是 取消当前等待/定位,未知或结束的 ID 无操作 无 本插件返回的请求 ID

0 超时是无效参数,不会替换成默认值;false 地址配置会保留。定位成功只交付一次,超时/取消/结束后注销监听并丢弃迟到结果。取消权限等待不会关闭系统权限框;取消已打开的设置请求也不会关闭系统页面。

权限与定位输出

字段 类型 说明
permission.requestId string 异步请求 ID;只读检查为空
permission.platform MapPlatform 当前平台
permission.state MapLocationPermissionState not-determined / granted / denied / restricted / unsupported
permission.accuracy MapLocationAccuracyAuthorization full / reduced / none / unknown;与定位策略独立
permission.serviceEnabled boolean 系统定位服务是否开启,与应用授权独立
permission.canAskAgain boolean 当前未授权状态下能否再次发起系统申请
location.requestId / platform string / MapPlatform 本次定位请求与平台
location.coordinateType string gcj02,已按 SDK 实际转换流程处理
location.latitude / longitude number 经纬度,度;合法 0 会保留
location.accuracy number SDK 实际水平精度,米
location.altitude number / null SDK 可用高度,米;未提供为 null
location.speed number / null 速度,米/秒,0 为静止
location.bearing number / null 方位角,度,0 为朝北
location.timestamp number / null SDK 定位时间的 Unix 毫秒,未返回为 null,不用请求时刻补造
location.provider string SDK 返回的来源名称,未返回为空
location.isMock boolean / null SDK/OS 模拟标记,false 与未提供 null 不同
location.address MapLocationAddress / null 未请求或未返回为 null
address.formattedAddress / country / province / city / district string 格式化地址与行政区,缺分量为空
address.street / streetNumber / adCode / cityCode / poiName string 街道/门牌/区码/城市码/POI,缺分量为空
settings.requestId / platform / opened string / MapPlatform / boolean 设置跳转成功为 opened=true,不代表已授权
error.data.requestId / nativeErrorCode string / number / null 纯数字诊断,不透传 SDK 错误原文或 Key

字段读取、拒绝分支和 null/0/false 判断见完整示例。页面隐藏或退出应取消自己保存的请求 ID,并设置非响应式退出标记来丢弃旧页面回调;响应式数据在 onUnmounted 清理,避免退出过程重新渲染。

覆盖物方法与参数

以下方法均通过地图组件 ref 调用。变更、summary、实际标记位置和范围适配需等待 ready;能力可在实例已创建时读取。每批不超过 500 项。ID 在每个地图、每种覆盖物内独立;一批重复同类 ID 不合法,不同类型可用相同 ID。参数错误整批不会调用原生变更,图片格式/实际尺寸由原生进一步检查。

参数 类型 必填 说明 默认值 可选参数
upsertMarkers(markers) MapMarker[] 是 新增或完整替换同 ID 标记 无 空数组无变更
upsertPolylines(polylines) MapPolyline[] 是 新增或替换折线 无 空数组无变更
upsertCircles(circles) MapCircle[] 是 新增或替换圆 无 空数组无变更
upsertPolygons(polygons) MapPolygon[] 是 新增或替换多边形 无 空数组无变更
removeOverlays(references) MapOverlayReference[] 是 按类型/业务 ID 移除;不存在为空操作 无 type 为 marker / polyline / circle / polygon
references[].type MapOverlayType 是 需要移除的类型 无 四种类型
references[].id string 是 对应类型的业务 ID 无 与创建时一致
setMarkerCallout(id,visible,exclusive) 的 id string 是 已存在且有标题或说明的标记 无 业务 ID
visible boolean 是 显示或关闭气泡;显示时标记也须可见 无 true / false
exclusive boolean 否 显示前关闭其他气泡;false 需要多气泡能力 true true / false
getMarkerPosition(id) 的 id string 是 读取原生实际位置,包含拖动结果 无 业务 ID
fitCoordinates(points,padding) 的 points MapCoordinate[] 是 至少两个不同点,最多 5000;纬度绝对值≤85,经度最大最小跨度≤180 无 不支持极区或跨日期线集合
padding number 否 四边留白,逻辑像素;不能侵占全部视口 32 0–128

clearOverlays()、getOverlaySummary()、getOverlayCapabilities() 无参数。clear 只移除本插件当前地图创建的四类对象,不清除 SDK 自有图层;销毁或撤回隐私会同时释放覆盖物、图片和监听。SDK 执行中发生异常可能部分变更,使用 summary 检查当前对象后重试/clear,不将同步批次视为数据库事务。

标记字段:

参数 类型 必填 说明 默认值 可选参数
id string 是 1–64 字符,无首尾空白或控制字符 无 同类型业务唯一
position MapCoordinate 是 GCJ-02 经纬度 无 latitude −90至90,longitude −180至180,有限数
title string 否 气泡标题,最多200字符 空字符串 普通文字
snippet string 否 气泡说明,最多200字符 空字符串 普通文字
visible boolean 否 标记显隐,隐藏时关闭气泡 true true / false
draggable boolean 否 允许拖动,事件读实际坐标 false true / false
rotation number 否 从正北顺时针,度 0 0–360,360等效0
opacity number 否 图片整体透明度 1 0–1
zIndex number 否 标记层内绘制层级 0 −10000至10000的整数
anchorX / anchorY number 否 图片锚点归一位置,0左/上,1右/下 0.5 / 1 0–1
icon MapMarkerIcon或null 否 自定义本地图片,null恢复默认标记 null 不传时使用SDK默认图标
icon.imageBase64 string icon非null时是 PNG/JPEG原始base64;也接受对应data前缀 无 去掉前缀后≤262144字符,实际图片每边≤512像素
icon.width / icon.height number icon非null时是 显示宽高,逻辑像素 无 1–128

不请求网络图片,不接受 SVG 或任意文件路径。示例 PNG 与界面 SVG 使用同组图形;接入者可以使用自身本地图片内容。title/snippet 都为空或标记隐藏时,显示气泡返回参数错误;关闭气泡不要求有文字。SDK 默认气泡布局由平台提供,多气泡须读取实际能力,不能将多次调用自动当作多开成功。

当前三端固定 SDK 的默认气泡均只支持单个选中标记,本插件 multipleCallouts=false;customMarkerImage 与 markerDrag 为 true,仍需在匹配的原生集成环境验收。自定义多个同时可见气泡不属于默认气泡接口,当前没有模拟该能力。

iOS 程序化显示屏幕外标记的默认气泡时,SDK 可能调整地图中心;需要保持视口时先将标记放入当前范围,再显示气泡。iOS 拖动过程按屏幕刷新读取原生标记的实际坐标,只有坐标变化才发事件,隐藏、移除和销毁均停止读取。

图形的共同样式与几何:

参数 类型 必填 说明 默认值 可选参数
id string 是 同标记ID规则,按类型隔离 无 1–64字符
MapPolyline.points MapCoordinate[] 是 至少两个不同点,最多5000点 无 GCJ-02
MapPolygon.points MapCoordinate[] 是 至少三个不同点,最多5000点;首尾相同会去掉重复末点,由SDK闭合 无 不额外检测自相交
MapCircle.center MapCoordinate 是 GCJ-02圆心 无 合法经纬度
MapCircle.radius number 是 半径,米;0为合法退化图形 无 0–1000000
strokeColor string 否 描边颜色,透明度另设 #14878f 精确格式 #RRGGBB,大小写均可
strokeWidth number 否 描边宽度,逻辑像素 折线4,圆/面2 0–40
strokeOpacity number 否 描边透明度 1 0–1
MapPolyline.dashed boolean 否 虚线,具体点划形态由SDK提供 false true / false
fillColor string 圆/面否 填充颜色 #14878f 精确 #RRGGBB
fillOpacity number 圆/面否 填充透明度 0.18 0–1
visible boolean 否 隐藏后仍保留在清单中 true true / false
zIndex number 否 图形层内绘制层级 0 −10000至10000整数

所有数值须为有限数,0 与 false 不被默认值覆盖。尺寸为公开逻辑像素:Android 按 density、鸿蒙按 vp2px 转换到 SDK 像素,iOS 使用点。zIndex 仅用于同一渲染层,标记层与线面层不承诺相互穿插。

字段 类型 说明
getOverlaySummary().markerIds string[] 当前已成功创建的标记业务ID,包含隐藏对象
polylineIds / circleIds / polygonIds string[] 对应类型的已存在业务ID;不承诺顺序
getMarkerPosition().latitude / longitude number 原生实际位置,GCJ-02,度
getOverlayCapabilities().multipleCallouts boolean 当前固定SDK/实现是否可同时显示多个默认气泡
customMarkerImage boolean 是否支持本地PNG/JPEG base64标记
markerDrag boolean 是否提供原生拖动及实际位置事件

完整赋值、读取、能力分支、事件、替换和清理代码见 drawOverlays、onOverlayEvent、updateAndRemoveOverlays,逐项操作见覆盖物演示页。参数错误与原生错误均抛统一 MapFail,页面应捕获并保留原来成功的状态,不提前显示操作成功。

持续会话参数与输出

startMapLocationSession(options)受理后返回新会话ID;前置或参数失败同步抛MapFail。stopMapLocationSession(sessionId)、getMapLocationSessionTrack(sessionId)、clearMapLocationSessionTrack(sessionId)的参数如下;停止旧ID为空操作,读取/清空旧ID为9101019。getMapLocationSessionState()与getMapLocationBackgroundStatus()无参数。

参数 类型 必填 说明 默认值 可选参数
options MapLocationSessionOptions 是 启动配置对象 无 下列字段
mode string 否 前台或后台持续;均须从前台启动 foreground foreground、background
accuracy string 否 精度偏好;不提升用户已授予的精度 high high、balanced
intervalMs number 否 整数毫秒;首点不受间隔限制,后续交付节流 2000 1000–60000
distanceFilter number 否 米;后续点须同时满足间隔和距离门槛 0 0–1000
needAddress boolean 否 需要可用地址时启用;无地址为null false true、false
startupTimeoutMs number 否 后台准备至首个可用点的总期限,整数毫秒 10000 1000–60000
maxPoints number 否 原生环形缓冲容量,超限移除最旧点 500 整数32–2000
androidNotification MapAndroidLocationNotification 否 仅Android后台通知外观 见下列字段 id、title、text
androidNotification.id number 否 本插件定位通知ID,避免与宿主通知冲突 2611706 整数1–2147483647
androidNotification.title string 否 通知标题,非空 位置记录进行中 最多60字符
androidNotification.text string 否 通知正文,非空 正在使用位置信息,点击返回应用 最多120字符
onEvent function 否 读取type/state/point/error,后台不发送高频location 无 state、location、error
sessionId string 是 start返回的ID;最多保留最近已受理会话 无 stop、getTrack、clearTrack参数

requestMapLocationNotificationPermission(options)返回可取消请求ID,success/fail/complete在返回后交付。拒绝进入success且state=denied;取消等待不关闭系统弹窗。

参数 类型 必填 说明 默认值 可选参数
options MapLocationNotificationOptions 是 通知许可请求配置 无 下列字段
timeoutMs number 否 整数毫秒 60000 1000–60000
success function 否 读取requestId、platform、state、channelEnabled、canAskAgain 无 state为granted/denied/not-required/unsupported;channelEnabled为boolean或null
fail function 否 统一MapFail;错误data仅requestId和数字nativeErrorCode/null 无 取消为9101014
complete function 否 每次请求结束一次 无 无
字段 类型 说明
state.sessionId / platform string 最近会话ID及实际平台;未开始为空ID、idle
state.phase string idle / starting / running / stopping / stopped / failed;running不表示已取得首点
state.mode / appInForeground string / boolean 运行模式和真实App前台状态
state.receivedPointCount number 通过过滤的累计接收点数
state.storedPointCount / discardedPointCount number 当前保留 / 未保留点数;未保留包含环形淘汰和手动清空
state.startedAt / stoppedAt / lastFixReceivedAt number或null 会话开始、结束、最近点接收的Unix毫秒;与SDK位置时间分开
state.lastErrorCode / stopReason number或null / string 最近错误与固定停止原因,错误15可能恢复;隐私、权限、服务、首点超时等会终止
track.sessionId / points string / MapLocationSessionPoint[] 当前/最近终止会话的深复制快照,最多maxPoints
track.receivedPointCount / discardedPointCount number 满足累计=points.length+未保留;清空后累计及序号不重置
point.sequence / receivedAt / location number / number / MapLocationResult 从1递增序号、接收Unix毫秒、与单次定位相同的真实位置结构;location.requestId为会话ID
event.type / state / point / error string / State / Point或null / MapFail或null location含point;error含错误;state事件其余均null
background.platform / supported string / boolean 该端与系统版本是否提供后台模式;鸿蒙API20为false
background.foregroundPermission string not-determined / granted / denied / restricted / unsupported
background.backgroundPermission / notificationPermission string granted / denied / not-required / unsupported;不隐式弹出申请
background.notificationChannelEnabled boolean或null Android实际频道;未创建、旧系统或其他端为null,不假装已开启
background.configurationState string ready / missing / unknown;鸿蒙Stage未能核实配置时unknown
background.appInForeground / canStart / requiresSettings / reason boolean / boolean / boolean / string 已知条件允许尝试、是否需用户设置及可读原因;canStart不代替系统最终校验
notification.requestId / platform string 通知请求ID及实际平台
notification.state string granted / denied / not-required / unsupported;拒绝仍属于成功返回的状态
notification.channelEnabled / canAskAgain boolean或null / boolean 频道状态(不适用或未创建为null)及是否可再次申请

清空不删除宿主已导出的文件;隐私撤回停止会话并清空原生位置缓冲,此后读取轨迹返回9101002。后续成功受理新会话才替换旧轨迹,失败启动不覆盖上次结果。位置timestamp保留SDK原始值,0和false均有效,不可用为null。lastFixReceivedAt在合法点被间隔/距离过滤时仍刷新,用于识别最近采样;计数只计算通过过滤的点。iOS的intervalMs用于交付过滤,不承诺降低系统采样频率。

地点搜索参数

getMapInputTips(options)、searchMapPois(options)、getMapPoiDetail(options)受理后返回请求ID,回调在函数返回后交付;参数和前置失败也通过fail/complete结束。success与fail互斥,complete至多一次。能力/状态读取为同步纯查询;cancelMapSearchRequest(requestId)传入自己持有的请求ID,对已结束或非本插件ID为空操作。

参数 类型 必填 说明 默认值 可选参数
MapInputTipsOptions.keyword string 是 trim后1–80字符 无 非空关键词
MapInputTipsOptions.city string 否 城市名称/代码,trim后最多80字符 空字符串 原厂支持的城市文本
MapInputTipsOptions.cityLimit boolean 否 true时city须非空 false true / false
MapInputTipsOptions.types string 否 类型名称或代码,多项用竖线分隔,最多200字符 空字符串 SDK支持的类型
MapInputTipsOptions.center MapCoordinate 否 真实输入偏好中心,GCJ-02;不是定位 不传 有限经纬度,0合法
MapPoiSearchOptions.mode MapPoiSearchMode 否 V2检索范围 keyword keyword / nearby / rectangle / polygon
MapPoiSearchOptions.keyword string 否 trim后最多80字符;除周边外与types至少一项非空 空字符串 关键词或空
MapPoiSearchOptions.types string 否 trim后最多200字符;周边可与keyword同时为空 空字符串 类型名称/代码,多项用竖线分隔
MapPoiSearchOptions.city string 否 keyword/nearby可传;几何范围须为空 空字符串 城市文本,最多80字符
MapPoiSearchOptions.cityLimit boolean 否 仅keyword可true且须有city false true / false
MapPoiSearchOptions.center MapCoordinate 条件必填 nearby必须;keyword距离排序必须;几何范围不传 不传 纬度−90–90、经度−180–180,均为有限数字
MapPoiSearchOptions.radius number 否 周边半径,单位米;0原样保留,其他模式不使用 3000 0–50000整数
MapPoiSearchOptions.sort MapPoiSort 否 距离排序需center;几何范围仅综合 nearby为distance,其他为comprehensive comprehensive / distance
MapPoiSearchOptions.rectangle MapSearchRectangle 矩形必填 southWest/northEast,西南两值严格小于东北、经差小于180度 不传 只在rectangle传入
MapPoiSearchOptions.polygon MapCoordinate[] 多边形必填 3–16唯一顶点,简单非零面积,不重复首尾、不跨日期线 空数组 只在polygon传入
MapPoiSearchOptions.page number 否 三端统一从1开始 1 1–100整数
MapPoiSearchOptions.pageSize number 否 三端共同上限25 20 1–25整数
MapPoiSearchOptions.includeFields MapPoiOptionalField[] 否 请求扩展字段,重复值归并;未选不补造数据 空数组 children / business / indoor / navi / photos
MapPoiDetailOptions.id string 是 trim后1–128字符,单个真实POI ID,不含竖线 无 从实际搜索结果选择
MapPoiDetailOptions.includeFields MapPoiOptionalField[] 否 与列表相同五组;详情默认也只取基础字段 空数组 children / business / indoor / navi / photos
上述三种Options.timeoutMs number 否 从受理至结果被原生接受的上限,含准备和原生编码;回调还受宿主线程调度影响 10000 1000–60000整数
上述三种Options.success function 否 分别返回MapInputTipsResult/MapPoiSearchResult/MapPoiDetailResult 不设置 result回调
上述三种Options.fail function 否 MapFail,SDK诊断只保留数字nativeErrorCode 不设置 error回调
上述三种Options.complete function 否 成功、失败、取消、超时后结束等待 不设置 无参回调
cancelMapSearchRequest.requestId string 是 当前插件搜索API返回的ID;只取消自己页面持有的ID 无 非空字符串
getMapSearchCapabilities / getMapSearchState 无 — 均无参数,不初始化SDK、不申请权限、不发送搜索 — —

矩形/多边形不能同时传city、cityLimit=true、center或其他几何对象,排序为comprehensive。坐标顺序在公开类型中始终是 { latitude, longitude },不要直接复制原厂经度在前的字符串。示例代码已覆盖关键词+城市限制+距离排序、无过滤周边+半径0、矩形、多边形、仅类型搜索、基础/五组字段和单ID详情。

搜索输出与平台差异

字段 类型 说明
三类Result.requestId / platform / coordinateType string / MapPlatform / string 请求关联ID、实际平台、固定gcj02
MapInputTipsResult.keyword / city / cityLimit / types / center string / string / boolean / string / MapCoordinate或null 本次规范化输入快照,center未传为null
MapInputTipsResult.tips MapInputTip[] SDK真实提示,空数组为成功空结果
MapInputTip.id / name / district / adCode / address / typeCode string 真实提示字段,缺失文本为空;id可能不是可查详情的POI
MapInputTip.position MapCoordinate或null 无坐标提示为null,不按名称制造坐标
MapPoiSearchResult.query MapPoiSearchQuery 规范化输入:mode、keyword、types、city、cityLimit、center、radius、sort、rectangle、polygon、page、pageSize、includeFields;未传几何为null/空数组
MapPoiSearchResult.count number或null 原始SDK计数;不是计算后的总页数,不保证下一页有数据
MapPoiSearchResult.items MapPoi[] 本页真实结果,最多请求pageSize条
MapPoiSearchResult.suggestions MapPoiSuggestions或null iOS公开字段可提供;Android/鸿蒙V2无对应公开结果,返回null
MapPoiSuggestions.keywords string[] 原厂关键词建议,可为空
MapPoiSuggestions.cities MapPoiCitySuggestion[] 每项name、cityCode、adCode为string;count为number或null
MapPoiDetailResult.requestedId / includeFields / poi string / MapPoiOptionalField[] / MapPoi 实际请求ID、请求字段、真实详情;poi.id可能是别名,不用于强制相等判断
MapPoi.id / name / type / typeCode / address string POI基础文本,缺失为原样空值
MapPoi.province / provinceCode / city / cityCode / district / adCode string 行政区文本与代码
MapPoi.position MapCoordinate或null 真实GCJ-02坐标,缺失为null
MapPoi.distanceToCenterMeters number或null 仅在列表有center及真实position时,由插件以6371008.8米球半径计算的大圆估算;不是SDK测距或路线长度;无中心/详情为null
MapPoi.business / indoor / navi 对应结构或null 未请求/SDK未提供为null;请求不保证服务一定有该数据
MapPoi.children / photos MapPoiChild[] / MapPoiPhoto[] 未请求或未提供为空数组;不据空数组推断地点不存在
MapPoiBusiness.businessArea / openingHoursToday / openingHoursWeek string或null 商圈与今日/本周营业时间
MapPoiBusiness.telephone / tags / rating / averageCost string或null 电话、标签、评分、人均消费,保留SDK文本而非猜测数值
MapPoiBusiness.parkingType / alias / cpId string或null 停车类型、别名、CP ID;iOS未提供cpId,返回null
MapPoiIndoor.hasIndoorMap / poiId / floor / floorName boolean / string / number或null / string 室内图标记、室内POI、楼层及名称;false和0保留,鸿蒙缺少floor时为null
MapPoiNavi.poiId / entry / exit / gridCode string / MapCoordinate或null / MapCoordinate或null / string 导航POI、入口/出口及网格码;坐标缺失不补POI中心
MapPoiChild.id / name / address / type / typeCode / position string / string / string / string / string / MapCoordinate或null 子POI完整公开字段
MapPoiPhoto.title / url string / string 原厂照片名称与URL;加载照片应处理失败并按宿主隐私策略使用
MapSearchCapabilities.platform / supported / inputTips / poiModes / poiDetail / optionalFields / poiSuggestions 平台、boolean、boolean、模式数组、boolean、字段数组、boolean 静态原生能力;Web为false/空数组,不生成示例地点
MapSearchCapabilities.cancellation string iOS为sdk-request,Android/鸿蒙为callback-only;未支持端为unsupported
MapSearchCapabilities.maxPage / maxPageSize / maxPolygonVertices / maxPendingRequests / note number / number / number / number / string 原生端分别100/25/16/4及限制说明;未支持端上限为0
MapSearchState.platform / pendingRequestIds / retiredRequestCount / maxPendingRequests 平台 / string[] / number / number 本插件原生自有记录,pending与retired共占最多4槽;不是远端请求或系统网络连接统计

单请求提示上限100条,POI列表上限为pageSize,单POI子项最多1000条、照片100条、单值文本4096字符、序列化结果2MiB。超界或字段无效返回9101020,不静默裁剪后声称完整。取消仅终止本插件等待;Android/鸿蒙SDK没有对应公开取消入口,已发请求保留内部回执记录至SDK返回,届时释放槽。iOS按该请求独占的SDK实例调用真实取消方法,不影响其他调用者。上述行为均不承诺撤销已经发送至远端的数据。

地理信息和SDK工具参数

四类地理异步API先返回ID,参数/前置失败也在返回后通过fail/complete交付;回调至多一次,隐藏/退出按页面保存的ID取消。地理查询自有四槽(含retired),与地点搜索通道分别管理。本地工具为同步API,非法输入、环境或SDK异常抛MapFail。下表中点均为 { latitude, longitude }、GCJ-02;转换来源点依fromType解释。

参数 类型 必填 说明 默认值 可选参数
MapGeocodeOptions.address string 是 trim后1–500字符的结构化地址 无 非空地址
MapGeocodeOptions.city / country string 否 分别trim后最多80字符 空字符串 原厂支持的城市/国家文本
MapReverseGeocodeOptions.position MapCoordinate 是 原厂逆编码输入,不触发定位 无 有限纬度−90–90、经度−180–180
MapReverseGeocodeOptions.radius number 否 半径米,0原样保留 1000 0–3000整数
MapReverseGeocodeOptions.includeNearby boolean 否 请求附近道路/路口/POI/AOI扩展 false true / false
MapReverseGeocodeOptions.poiTypes string 否 最多200字符,多类型竖线分隔;仅扩展时传 空字符串 原厂类型代码
MapReverseGeocodeOptions.overseaSort string 否 原厂仅海外生效;非扩展保持默认 distance distance / score
MapDistrictOptions.keywords string 是 单关键字trim后1–80字符,不含竖线 无 行政区名称或原厂支持代码
MapDistrictOptions.subDistrict number 否 返回下级深度,0不含下级 1 0 / 1 / 2 / 3
MapDistrictOptions.showBoundary boolean 否 请求真实多段边界 false true / false
MapDistrictOptions.page / pageSize number 否 分别为一基页码和每页条数,均整数 1 / 20 page 1–100;pageSize 1–50
MapDistanceMatrixOptions.origins MapCoordinate[] 是 多起点,保留顺序和重复起点;SDK ID一基对应 无 1–100点
MapDistanceMatrixOptions.destination MapCoordinate 是 单个终点 无 有限合法GCJ-02点
MapDistanceMatrixOptions.mode MapDistanceMatrixMode 否 本接口只返回距离/时长,不返回路线 driving straight / driving / walking
MapDistanceMatrixOptions.strategy number 否 驾车原厂策略子集;其他mode保持4且不发送策略 4 0–9整数
MapDistanceMatrixOptions.includeExtensions boolean 否 原厂扩展选项,不保证所有字段均有值 false true / false
上述四类Options.timeoutMs number 否 从受理到原生接受完成的单调截止,包含编码检查 10000 1000–60000整数
上述四类Options.success function 否 分别返回对应Geocode/ReverseGeocode/District/DistanceMatrix Result 不设置 result回调
上述四类Options.fail / complete function 否 MapFail回调 / 无参结束回调,互斥成功失败后完成一次 不设置 error回调 / 无参回调
cancelMapGeoRequest.requestId string 是 本页持有的地理请求ID,旧/未知ID空操作 无 本插件地理查询接口返回值
getMapGeoCapabilities / getMapGeoState 无 — 无参数、纯查询,不申请权限/发SDK请求 — —
MapDistanceOptions.from / to MapCoordinate 是 SDK本地两点距离,单位米 无 两个合法点,可相同
MapAreaOptions.mode MapAreaMode 是 原厂估算面积,平方米 无 rectangle / polygon
MapAreaOptions.rectangle MapSearchRectangle 矩形必填 southWest/northEast严格递增、经差小于180;另一形状不传 无 两角纬度绝对值≤85
MapAreaOptions.polygon MapCoordinate[] 多边形必填 3–500唯一、简单非零面积顶点,不重复首尾/跨日期线 无 纬度绝对值≤85,另一形状不传
MapCoordinateConversionOptions.position MapCoordinate 是 依fromType解释来源坐标 无 有限合法经纬度
MapCoordinateConversionOptions.fromType MapCoordinateSource 是 目标固定gcj02;gcj02来源为identity复制 无 gcj02 / wgs84 / bd09 / mapbar / mapabc / soso / aliyun / google
MapViewContext.coordinateToScreen.coordinate MapCoordinate 是 当前地图GCJ-02点,返回本地逻辑px,可落视口外 无 地图ready后调用
MapViewContext.screenToCoordinate.point MapScreenPoint 是 {x,y}均为有限数,绝对值≤10000000,返回GCJ-02 无 本地逻辑px,0合法,可为视口外点

行政区没有有效level过滤参数,按查询结果的level读取,不从已废弃setter推断支持。逆编码仅处理给定坐标;若输入来自WGS-84/百度等,请先按真实来源转换。矩阵的整体请求成功仍可含失败行,不以success回调替代每个item.success判断。

地理信息和工具输出

字段 类型 说明
四类Result.requestId / platform / coordinateType string / MapPlatform / string 关联ID、实际平台、gcj02
MapGeocodeResult.query / count / items MapGeocodeQuery / number或null / MapGeocodeAddress[] address/city/country规范化快照、SDK原始计数或null、实际候选;Android/HM没有count getter则null
MapGeocodeAddress.formattedAddress / province / city / cityCode / district / adCode string 格式化地址与行政文字;正编码cityCode仅iOS公开,其他端为空,不猜码
MapGeocodeAddress.township / neighborhood / building / country / postCode / level / position string(前六项)/ MapCoordinate或null 匹配地址补充、级别及真实位置;缺文本为空,缺坐标null
MapReverseGeocodeResult.query / address MapReverseGeocodeQuery / MapReverseGeocodeAddress或null 输入position/radius/includeNearby/poiTypes/overseaSort;成功未提供地址时null
MapReverseGeocodeAddress.formattedAddress / addressComponent string / MapGeoAddressComponent或null 格式化地址及实际组件,不伪造缺失对象
MapGeoAddressComponent.country / countryCode / province / city / cityCode / district / adCode / township / townCode / neighborhood / building string 原厂各级地址/代码,缺值为空
MapGeoAddressComponent.streetNumber / businessAreas MapGeoStreetNumber或null / MapGeoBusinessArea[] 街道门牌及商圈;空数组不代表查询失败
MapGeoStreetNumber.street / number / position / direction / distanceMeters string / string / MapCoordinate或null / string / number或null 门牌“0”和距离0均保留,距离单位米
MapGeoBusinessArea.name / position string / MapCoordinate或null 真实商圈名称和中心
MapReverseGeocodeAddress.roads / intersections / pois / aois 对应结构数组 原厂扩展集合,未提供为空,均可独立展示和选择
MapGeoRoad.id / name / position / direction / distanceMeters string / string / MapCoordinate或null / string / number或null 附近道路,SDK距离米
MapGeoRoadIntersection.position / distanceMeters / direction / firstRoadId / firstRoadName / secondRoadId / secondRoadName 坐标或null / number或null / 五个string 实际交叉路口与两条道路
MapGeoPoi.id / name / type / typeCode / address / province / provinceCode / city / cityCode / district / adCode / telephone / direction / businessArea string Legacy逆编码POI基础字段,不混用地点搜索V2扩展
MapGeoPoi.position / distanceMeters MapCoordinate或null / number或null SDK实际位置与距离,后者不是客户端按查询中心计算的大圆估算
MapGeoAoi.id / name / adCode / position / areaSquareMeters / distanceMeters / type string / string / string / 坐标或null / number或null / number或null / string 兴趣区域,平方米及米,合法0不变null
MapDistrictResult.query / count / items MapDistrictQuery / number或null / MapDistrictNode[] keywords/subDistrict/showBoundary/page/pageSize快照;原始count不是总页数
MapDistrictNode.name / level / cityCode / adCode / center string / string / string / string / MapCoordinate或null 实际节点标识、级别、代码与中心
MapDistrictNode.boundaries / children MapCoordinate[][] / MapDistrictNode[] 每项一段真实边界,保留点序/首尾;递归孩子不暴露SDK可变对象
MapDistanceMatrixResult.query / items MapDistanceMatrixQuery / MapDistanceMatrixItem[] origins/destination/mode/strategy/includeExtensions快照与原厂实际行;不补造缺行
MapDistanceMatrixItem.originId / destinationId / originIndex / destinationIndex number 保留SDK一基ID;索引减一,对应输入数组和单终点
MapDistanceMatrixItem.success / errorCode / reason boolean / number或null / string 成功code为null/0;失败1无道路、2距道路远、3覆盖外,其他含负码为sdk-error,不转发原厂异常原文
MapDistanceMatrixItem.distanceMeters / durationSeconds number或null 成功保留0米/0秒;失败两项均null,不能用SDK默认0冒充成功
MapDistanceCalculationResult.platform / coordinateType / distanceMeters / method MapPlatform / string / number / string SDK本地距离米,method为sdk
MapAreaCalculationResult.platform / coordinateType / mode / areaSquareMeters / method MapPlatform / string / MapAreaMode / number / string SDK原厂估算,method为sdk
MapCoordinateConversionResult.platform / inputPosition / fromType / toType / position 平台 / 来源点 / MapCoordinateSource / string / 目标点 保留来源和实际输出,目标固定gcj02
MapCoordinateConversionResult.changed / dataAvailable / method boolean / boolean或null / string 数值是否变化、SDK对输出GCJ-02坐标的数据覆盖判断(无API则null)、identity或sdk;均不是转换/鉴权验证
MapScreenPoint.x / y number 地图左上角为原点的本地逻辑px;反向返回MapCoordinate经纬度
MapGeoCapabilities.platform / supported / geocode / reverseGeocode / district / distance / mapProjection 平台和boolean 本地实现能力;Web均未支持,纯查询不构造请求
MapGeoCapabilities.areaModes / coordinateSources / distanceMatrixModes / cancellation 模式数组 / 来源数组 / 模式数组 / string 两种面积、八种来源、三种矩阵;iOS sdk-request,Android/HM callback-only
MapGeoCapabilities.maxPendingRequests / maxMatrixOrigins / maxDistrictDepth / maxDistrictPage / maxDistrictPageSize / maxAreaVertices / maxDistrictNodes / maxBoundaryPoints / note number(前八项)/ string 原生端4/100/3/100/50/500/5000/200000及限制说明;Web上限0
MapGeoState.platform / pendingRequestIds / retiredRequestCount / maxPendingRequests 平台 / string[] / number / number 仅地理查询原生自有记录,不含地点搜索或同步工具,不表示网络连接数

正向候选和每类逆向集合最多1000,行政区总节点5000/深度8/边界总点200000,面积500顶点;基础文本4096字符、最终UTF-8结果16MiB。达到客户端防御上限或坏字段返回9101022,不静默裁剪。例页对大结果按层级/分组浏览,地图单图形超过5000点时以真实点分段或明确显示限制,查询数据保持完整。

投影需要当前实例可用、ready和有效视口。Android/Harmony原生物理像素经密度转换,iOS使用本地UIKit points;整数像素量化、相机旋转/倾斜会影响往返,不能要求坐标严格相等。屏幕点属于当前地图,不是全屏/页面坐标,不复用其他地图实例的投影结果。

路线规划参数

参数 类型 必填 说明 默认值 可选参数
mode MapRouteMode 是 一次请求选一种方式 — driving / walking / riding / transit / truck
from / to MapRouteEndpoint 是 起终点对象 — —
from.position / to.position MapCoordinate 是 GCJ-02,latitude±90、longitude±180,有限数值,0合法 — —
from.poiId / to.poiId string 否 trim后≤256字符;步行/骑行要求空,公交策略6要求两端非空 空 —
driving / walking / riding / transit / truck 对应Options或null 对应方式 只传当前组,其他组缺省或null 当前组按下表 —
timeoutMs number 否 1000–60000整数,结束本插件等待 10000 —
success / fail / complete function 否 结果/统一错误/等待结束;ID返回后异步至多一次 无 —
driving.strategy number 否 固定客户端驾车策略整数 32 32–45
driving.waypoints / truck.waypoints MapCoordinate[] 否 按顺序途经,最多16点,深快照 [] —
driving.avoidPolygons MapRouteAvoidPolygon[] 否 最多32区,每区points为3–16个非重复/非闭合/简单非退化点;纬度绝对值≤85、经差<180 [] 与avoidRoad互斥
driving.avoidRoad string 否 一条道路,trim后≤200字符 空 与avoidPolygons互斥
driving.plate string 否 ≤16字符,转大写 空 —
driving.carType number 否 原厂车辆类型 0 0燃油 / 1纯电 / 2插混
driving.useFerry boolean 否 轮渡开关,false保留 true true / false
driving.includeTraffic / includeCities boolean 否 路况/城市扩展 true / false true / false
walking.alternativeRoute / riding.alternativeRoute number 否 备选数量请求,不保证返回同数 1 1 / 2 / 3
walking.indoor boolean 否 室内步行;鸿蒙true返回9101006 false 以indoorWalking能力为准
transit.originCityCode / destinationCityCode string 是 数字城市码≤16字符,保留010前导零 — —
transit.strategy number 否 公交策略;6要求两端POI 0 0–8
transit.includeNightBuses boolean 否 夜班车请求开关 false true / false
transit.alternativeRoute number 否 公交备选数量请求 5 1–10
transit.maxTransfers number 否 最大换乘次数,0合法 4 0–4
transit.includeAllSubwayExits boolean 否 全部地铁出入口 false true / false
transit.originAdCode / destinationAdCode string 否 空或6位数字行政编码 空 —
transit.date / time string 否 有效YYYY-MM-DD / HH:mm,可分别留空;SDK时分分隔符由原生转换 空 —
truck.strategy number 否 固定客户端货车策略 1 1–9
truck.size number 否 原厂货车尺寸类型 2 1微型 / 2轻型 / 3中型 / 4重型
truck.heightMeters / widthMeters number 否 0–25.5米,保留0 1.6 / 2.5 —
truck.grossWeightTons / ratedLoadTons number 否 0–6553.5吨,分别映射SDK load / weight 0.9 / 10 —
truck.axles number 否 轴数整数,0合法 2 0–255
truck.plateProvince / plateNumber string 否 省份简称≤8 / 车牌部分≤16字符,后者转大写 空 —
truck.includeTraffic / includeCities boolean 否 仅鸿蒙支持true;Android/iOS true返回9101006 false / false 以trafficModes/cityModes为准
cancelMapRouteRequest(requestId) string 是 只取消自己持有的路线等待 — —
getMapRouteCapabilities / getMapRouteState 无 — 纯查询,不申请定位权限/发算路请求 — —

字符串统一trim且拒绝控制字符。不接受其他方式组参数,不静默丢弃未支持开关。途经上限依据固定客户端校验和iOS搜索更新说明;部分旧Android/鸿蒙注释仍写6,服务能否返回16点方案须以实际账号/地区验证。

策略表示SDK规划偏好,不保证实际方案的耗时、收费或通行结果。示例页可在请求前查看当前值含义并展开选择。以下数值已与固定SDK常量核对;语义依据官方驾车策略、公交策略、货车策略。公交0是新版推荐模式,不能套用旧版“最快捷”的说明。

方式 值 规划偏好
驾车 32 高德推荐
驾车 33 躲避拥堵
驾车 34 高速优先
驾车 35 不走高速
驾车 36 减少收费
驾车 37 大路优先
驾车 38 速度优先
驾车 39 躲避拥堵、高速优先
驾车 40 躲避拥堵、不走高速
驾车 41 躲避拥堵、减少收费
驾车 42 减少收费、不走高速
驾车 43 躲避拥堵、减少收费、不走高速
驾车 44 躲避拥堵、大路优先
驾车 45 躲避拥堵、速度优先
公交 0 综合推荐
公交 1 经济优先
公交 2 减少换乘
公交 3 减少步行
公交 4 舒适优先
公交 5 不乘地铁
公交 6 地铁图,双端地铁站POI必填
公交 7 地铁优先
公交 8 总时间优先
货车 1 躲避拥堵
货车 2 不走高速
货车 3 减少收费
货车 4 躲避拥堵、不走高速
货车 5 减少收费、不走高速
货车 6 躲避拥堵、减少收费
货车 7 躲避拥堵、减少收费、不走高速
货车 8 高速优先
货车 9 躲避拥堵、高速优先

路线输出与平台差异

字段 类型 说明
MapRouteResult.requestId / platform / coordinateType / mode / provider string / MapPlatform / gcj02 / MapRouteMode / search 请求、平台和来源
navigationReusable / scalarPresenceKnown boolean 当前均false;Search方案ID不是导航token,原始标量presence不能恢复
query MapRouteQuery 归一化深快照,端点poiId始终为string,五组仅当前组非null,不含回调/Key
origin / destination / taxiCostYuan / routes 点或null / 点或null / number或null / MapRoutePath[] SDK实际端点、整体打车费用、方案;不以输入补造结果点;taxiCost可用性随SDK模型,不表示原始响应presence或报价保证
MapRoutePath.id / index string / number requestId加/零基序号及原返回顺序,仅本次预览使用
distanceMeters / durationSeconds / durationSource number或null / number或null / string 米、秒;sdk-model / steps-sum / unavailable
strategyDescription / restrictionCode string / number或null 原厂说明和限行码,不表示通行保证
tollsYuan / tollDistanceMeters / trafficLights number或null 元、米、灯数;父对象缺失/方式不可用为null
steps / transit MapRouteStep[]或null / MapRouteTransit或null 非公交steps非null/transit为null;公交相反
MapRouteStep.instruction / orientation / road / action / assistantAction / tollRoad string 导航文字、方向、道路、动作和收费路文本
distanceMeters / durationSeconds / roadType / tollsYuan / tollDistanceMeters / trafficLights number或null 米/秒/原厂类型/元/米/灯数,按端与方式读取
polyline / cities / traffic MapCoordinate[] / MapRouteCity[]或null / MapRouteTraffic[]或null 真实分段,不补缺口;未请求/不支持扩展为null
MapRouteCity.name / cityCode / adCode / districts string(前三项)/ MapRouteDistrict[] District含name/adCode
MapRouteTraffic.rawStatus / distanceMeters / polyline string / number或null / MapCoordinate[] 原始交通文本、米、轨迹,未知状态不当作畅通
MapRouteTransit.costYuan / nightBus / walkingDistanceMeters / busDistanceMeters / segments number或null / boolean或null / number或null / number或null / MapRouteTransitSegment[] 元、夜班、步行/公交米、换乘分段
MapRouteTransitSegment.walking / busLines / taxi / railway / entrance / exit 步行对象或null / 备选线路数组 / 出租对象或null / 铁路对象或null / 入口或null / 出口或null busLines是同段备选,不是顺次乘坐;出入口含name/position
MapRouteWalkingPart.origin / destination / distanceMeters / durationSeconds / steps 点或null / 点或null / number或null / number或null / MapRouteStep[] 换乘步行真实端点/米/秒/步骤
MapRouteBusLine.id / name / type / cityCode string 线路身份、名称、类型、城市码
distanceMeters / durationSeconds / departureStop / arrivalStop / viaStopCount / viaStops number或null / number或null / 站点或null / 站点或null / number或null / MapRouteStop[] 站点含id/name/position,保留计数与实际列表
firstTimeText / lastTimeText / polyline string / string / MapCoordinate[] SDK首末班时分和真实轨迹;Date按本地HH:mm,不补日期、不转UTC
MapRouteTaxi.origin / destination / originName / destinationName 点或null / 点或null / string / string 出租车子段端点和名称
distanceMeters / durationSeconds / priceText / priceYuan / polyline number或null / number或null / string / number或null / MapCoordinate[] 米/秒/原价格文本/严格解析元/轨迹;Android/鸿蒙V2无价格,固定空/null
MapRouteRailway.id / name / trip / type / distanceMeters / durationSeconds string(前四项)/ number或null 身份、车次、类型、米、秒,不添加原厂没有的轨道polyline
departureStation / arrivalStation / viaStops / spaces / alternatives 车站或null / 车站或null / MapRouteRailwayStation[] / MapRouteRailwaySpace[] / MapRouteRailwayAlternative[] 上下车/途经、仓位费用、备选车次
MapRouteRailwayStation.id / name / adCode / position / timeText / waitMinutes / isStart / isEnd string(前三项)/ 点或null / string / number或null / boolean或null / boolean或null 时刻可跨日;停靠分钟;false合法
MapRouteRailwaySpace.code / costYuan string / number或null 仓位原编码和人民币元
MapRouteRailwayAlternative.id / name string 共同可用的备选身份/名称,不补完整车次
MapRouteCapabilities.platform / supported / modes MapPlatform / boolean / MapRouteMode[] 当前实现能力;Web不支持
drivingStrategyValues / transitStrategyValues / truckStrategyValues / alternativeCounts / maxTransitAlternatives / truckSizeValues number[](除第五项为number) 32–45 / 0–8 / 1–9 / [1,2,3] / 10 / [1,2,3,4]
trafficModes / cityModes / indoorWalking MapRouteMode[] / MapRouteMode[] / boolean 驾车三端;货车交通/城市仅鸿蒙;室内步行仅Android/iOS
navigationReusable / scalarPresenceKnown / cancellation boolean / boolean / string false / false;iOS sdk-request,Android/鸿蒙callback-only,其他unsupported
maxPendingRequests / maxWaypoints / maxAvoidPolygons / maxAvoidVertices number 原生端4 / 16 / 32 / 16;Web上限0
maxRoutes / maxSteps / maxTransitSegments / maxAuxiliaryItems / maxGeometryPoints / note number(前五项)/ string 20 / 20000 / 1000 / 20000 / 200000及说明
MapRouteState.platform / pendingRequestIds / retiredRequestCount / maxPendingRequests MapPlatform / string[] / number / number 仅路线通道;retired占槽,不表示网络连接数

SDK模型没有可靠数值presence:已请求且该端可用的合法0/false保留;未请求/不适用/不支持/父对象缺失为null。0不能证明远端确实给了该字段。Android/鸿蒙驾车总时长读取Cost,iOS读取原厂扁平映射。鸿蒙骑行只有各步时长全可用时求和并标steps-sum,缺项为null/unavailable;步行/骑行有错键的roadType为null。

驾车restrictionCode 0为无/已规避、1无法规避;货车0未知、1已规避、2起点/3途经/4区域/5终点限行。铁路waitMinutes保留SDK原数值:鸿蒙固定版本注释写秒,但真实parser原样读取wait,官方铁路换乘字段写分钟,因此按分钟解释;此注释冲突仍须真实服务验证。

客户端防御上限按整个结果累计:20方案、20000步骤、1000公交段、20000辅助项、200000几何点,文本4096字符、最终UTF-8 16MiB。坏字段/超界返回9101023,不截断成功数据。没有轨迹的部分保持缺失并在预览提示。每请求独占SDK对象,Android/鸿蒙取消/超时仍保留retired记录到实际回执,无回执可能持续占四槽;iOS只取消自身搜索实例。重新同意隐私不会恢复旧结果。

导航组件、方法与参数

getMapNaviCapabilities() 返回固定能力,getMapNaviState() 返回插件全局占用缓存;均无需初始化,也不会为查询而创建 SDK。普通页面使用 lizhao-map-navi。App 自定义适配器可用 new MapNaviController(element, traffic, transport, voiceEnabled);其接口与组件实例相同。直接适配器须监听 native-view 的 navistate 并在卸载调用 destroy();建议使用标准组件处理 ref/ready 与 UI 解绑。

参数 类型 必填 说明 默认值 可选参数
组件 transport MapNaviTransport 否 本实例固定出行方式;切换须结束并重建组件 driving driving / walking / riding / truck
组件 active boolean 否 false 终止本实例;再次true不会恢复已终止会话 true true / false
组件 traffic boolean 否 真实地图交通图层;iOS步行/骑行仅false,不是算路策略 false true / false
组件 voice-enabled boolean 否 初始内置播报配置;运行中通过实例setVoiceEnabled更改并读回 true true / false
MapNaviController.element UniNativeViewElement 是 App 标准 native-view 的init元素 无 Android / iOS / HarmonyOS
MapNaviController.traffic boolean 否 初始交通图层,限制同组件traffic false true / false
MapNaviController.transport MapNaviTransport 否 可选第三参,固定本实例出行方式 driving driving / walking / riding / truck
MapNaviController.voiceEnabled boolean 否 可选第四参,false在创建和后续启动中保留 true true / false
calculate.options.start MapNaviPoint或null 是 手动起点;null使用SDK当前定位,仍可能等待或失败 无 坐标点 / null
calculate.options.end MapNaviPoint 是 真实目的地,不能由Search方案ID代替 无 见点参数
MapNaviPoint.position MapCoordinate 是 高德坐标,国内GCJ-02/度,0合法 无 latitude±90、longitude±180
MapNaviPoint.name string 否 trim后≤128字符,无控制字符 空字符串 实际点名称
MapNaviPoint.poiId string 否 trim后≤256;非空时SDK优先按POI,坐标仍须提供 空字符串 实际POI ID
calculate.options.waypoints MapNaviPoint[] 否 驾车/货车最多16个,步行/骑行的插件共同合同为空;超界拒绝 [] 驾车/货车0–16点;步骑0点
calculate.options.strategy number 否 Navi策略,不是Search策略;1001不保证服务有多条结果 驾车/货车10,步骑1000 驾车/货车下表10项;步骑1000单路线 / 1001多路线
calculate.options.vehicle MapNaviVehicle 否 仅driving可传;新请求完整替换旧值 0/空车牌/false 见车辆参数
vehicle.vehicleType number 否 燃油/纯电/插混客车;货车使用独立truck配置 0 0 / 2 / 4
vehicle.plateNumber string 否 trim后≤32;只由接入者输入,不写示例密钥或真实车牌 空字符串 本次实际车牌
vehicle.avoidRestrictions boolean 否 true必须有非空车牌;false真实应用,不取代现实通行规则 false true / false
calculate.options.truck MapNaviTruck 否 仅truck可传;本次完整货车配置,不与vehicle并传 见下表 见货车参数
calculate.options.timeoutMs number 否 插件等待期限,超时不表示远端请求已撤回 30000 整数1000–60000ms
selectRoute.routeId string 是 从本实例、本代真实结果取得的不透明凭据 无 当前routes[].routeId
start.options.mode MapNaviMode 是 GPS真实导航或室内模拟 无 gps / emulator
start.options.emulatorSpeedKmh number 否 仅模拟可填写;GPS填写会报参数错误 步20、骑35、驾/货60 步10–30、骑10–50、驾/货10–120整数km/h
setTraffic.visible boolean 是 图层真实开关;iOS步行/骑行返回9101006且不更改会话 无 true / false
startCruise.options.mode number 否 1电子眼、2特殊道路、3同时检测;仅未算路的驾车实例 3 整数1 / 2 / 3
startCruise.options.startupTimeoutMs number 否 等待真实巡航专属数据的期限,不以位置回执代替确认 60000 整数1000–120000ms
setVoiceEnabled.enabled boolean 是 本实例内置播报开关,成功后更新配置;不控制独立TTS 无 true / false
setActive.active boolean 是 false安全结束;true不自动启动或复活 无 true / false

货车参数仅在 transport="truck" 使用。固定SDK对尺寸字段明确注明type1生效,本插件当前只开放燃油货车1;其他燃料货车暂不开放,避免参数被静默忽略。货车路线服务的开通、费用及配额请向高德确认;不保证结果完全避开现实通行限制。高德车辆说明

参数 类型 必填 说明 默认值 可选参数
truck.vehicleType number 否 燃油货车 1 1
truck.plateNumber string 否 trim后≤32字符,无控制字符 空字符串 实际车牌
truck.avoidRestrictions boolean 否 true必须提供车牌,false保留 false true / false
truck.size number 否 微型/轻型或小型/中型/重型 2 整数1 / 2 / 3 / 4
truck.heightMeters number 否 车高,米 1.6 有限0–25.5
truck.widthMeters number 否 车宽,米 2.5 有限0–25.5
truck.lengthMeters number 否 车长,米 6 有限0–25
truck.grossWeightTons number 否 总重(车重与核定载重),吨 10 有限0–6553.5
truck.ratedLoadTons number 否 核定载重,吨 2 有限0–6553.5
truck.axles number 否 轴数,0合法,不由缺省覆盖 2 整数0–255
truck.includeWeight boolean 否 重量是否参与算路;三端明确应用同一语义 true true / false
策略 含义
10 综合推荐:速度、拥堵与距离
12 躲避拥堵
13 不走高速
14 少收费
15 不走高速+躲避拥堵
16 不走高速+少收费
17 少收费+躲避拥堵
18 不走高速+少收费+躲避拥堵
19 高速优先
20 高速优先+躲避拥堵
方法 返回 适用条件与行为
calculate(options) string请求ID ready后行前算路;至多一条未回执请求,结果见事件/getRoutes
cancelCalculation() void 取消自己等待;旧SDK回执前可能继续占用,不能假解锁
selectRoute(routeId) void prepared阶段选择真实当前路径;更新预览/所选摘要
getRoutes() MapNaviRouteResult 取得真实Navi结果的独立深快照;无结果/失效报25,正常可在导航中读取
start(options) void prepared后仅启动一次;调用返回不等于navigation-start回执
startCruise(options) void 仅driving、ready、active且无任何算路代次/结果;一次启动,结束后重建
stop() void 结束本实例并接受回收,不等于OS资源已强确认停止
setTraffic(visible) void 实际交通图层;按本方式profile.trafficLayer检查,iOS步骑不提供
setVoiceEnabled(enabled) void 设置当前引擎内置播报配置;成功不等于实际出声或物理音频停止
showOverview() void 行前全览实际所选几何;导航中调用SDK全览
followVehicle() void 导航中恢复锁车,其他状态报25
setActive(active) void false终止,回到前台后由用户重建;不后台自动恢复
getState() MapNaviState 只读本实例缓存,终止后仍可核对状态
destroy() void 幂等终止/回收;不影响别的地图和定位会话

MapNaviCapabilities:

字段 类型 说明
platform / supported MapPlatform / boolean 固定SDK及本插件合同;Web/小程序supported=false
modes / drivingStrategyValues / vehicleTypeValues MapNaviMode[] / number[] / number[] GPS/模拟、驾车与货车10种策略、0/2/4客车
transports / transportProfiles MapNaviTransport[] / MapNaviTransportProfile[] 四种方式及各方式实际速度、途经点与交通图层合同
travelStrategyValues / truckVehicleTypeValues / maxTravelWaypoints number[] / number[] / number [1000,1001] / [1] / 0;Web均空或0
transportProfiles[].transport / trafficLayer MapNaviTransport / boolean 对应方式;iOS步骑trafficLayer=false,其余App组合true
transportProfiles[].maxWaypoints number 驾车/货车16,步骑0,表示插件共同合同
transportProfiles[].emulatorSpeedMinKmh / emulatorSpeedMaxKmh / emulatorSpeedDefaultKmh number 步10/30/20、骑10/50/35、驾/货10/120/60,km/h
maxInstances / maxWaypoints / maxRoutes / maxGeometryPoints number 插件上限1 / 16 / 20 / 200000,后两者是防御预算而非保证服务返回数量
emulatorSpeedMinKmh / emulatorSpeedMaxKmh / emulatorSpeedDefaultKmh number 旧字段为驾车10 / 120 / 60;其他方式读取transportProfiles
viewRequiresLocationPermission boolean App为true,手动起点模拟也要在引擎创建前授权
gpsRequiresFullAccuracy boolean GPS start精确位置政策;模拟允许reduced但SDK仍可拒绝
foregroundOnly / restartRequiresRebuild boolean 当前均true;退后台终止,一实例只start一次
builtInVoice / voiceControl boolean 原厂导航语音与实例配置开关能力;实际资源/音频播放由集成环境验证
cruiseTransports / cruiseModeValues MapNaviTransport[] / number[] App为[driving]及[1,2,3];Web为空
cancellation string App为callback-only:取消等待并丢弃旧交付,远端请求不保证撤回
preview string Android/鸿蒙same-navi-map,iOS dedicated-map;都是实际SDK几何
locationSessionExclusive boolean 鸿蒙true:导航与插件单次/持续定位双向互斥,避免共享SDK全局后台开关相互覆盖
note string 当前端限制说明,不包含输入/Key

MapNaviState 与全局 MapNaviGlobalState:

字段 类型 说明
transport MapNaviTransport或null 本实例固定方式;全局无owner为null
activity MapNaviActivity或null navigation / cruise;尚未受理活动或全局无owner为null
platform / instanceId MapPlatform / string 当前端与实例ID;全局无owner时instanceId为空
phase MapNaviPhase / MapNaviGlobalPhase creating / ready / calculating / prepared / starting / navigating / cruise-starting / cruising / stopping / stopped / finished / error / destroyed;全局还可none
active boolean 本实例前台激活状态,仅实例状态有此字段
generation / requestId number / string 当前准备代次与独立请求,仅实例状态有此字段
pendingCalculation boolean 仍有未实际回执请求,可能已经取消用户等待;不是远端连接数
selectedRouteId / routeCount string / number 本代实际所选凭据与方案数,仅实例状态有此字段
mode MapNaviMode或null 实际启动模式;未启动/不适用null,仅实例状态有此字段
releaseState string owned自有资源;releasing在回收;released为SDK层已回收;uncertain不能确认,不能新建
traffic boolean 实际/排队应用的交通图层开关,仅实例状态有此字段
voiceEnabled boolean 本实例内置播报配置;false是有效值,不表示物理音频强验
cruiseMode / cruiseConfirmed / locationConfirmed number或null / boolean / boolean 本实例巡航配置、真实专属数据确认与真实位置确认;后两者分别记录
errCode number 0或统一错误;不含原始异常文本
nativeErrorCode number或null 本实例安全原码,全局状态不提供
busy boolean 仅全局有;回收/retired/uncertain期间仍true

MapNaviRouteResult 与 MapNaviRoute:

字段 类型 说明
transport MapNaviTransport 真实结果所属方式,必须与组件和state一致
instanceId / requestId / generation string / string / number 本次真实路径组合的拥有者和代次
coordinateType string amap,保留SDK高德坐标,不二次纠偏
selectedRouteId / routes string / MapNaviRoute[] 当前所选及本次真实候选,不保证一定多于一条
routes[].routeId string 插件不透明凭据,绑定实例/引擎/代次;不可跨组件保存
routes[].sdkRouteId string 真实SDK选路键;独立路径组按原厂映射,鸿蒙步骑使用本引擎实际路线Map键
routes[].nativePathId string或null 原厂64位路径ID的十进制文本,不经过Double/Number
routes[].distanceMeters / durationSeconds / tollCostYuan number或null 米/秒/元;步骑收费不适用为null,有效模型0保留;不证明远端原字段presence
routes[].trafficLightCount number或null 实际可用红绿灯数;未提供null
routes[].labels / polyline string[] / MapCoordinate[] 实际标签与真实几何;缺失为空,不画猜测线或跨缺口伪线

MapNaviEvent(组件事件名为navi-event):

字段 类型 说明
type MapNaviEventType ready、calculate-start/success/cancel、route-selected、navigation-start、cruise-start/update、progress、location、gps-signal、waypoint、off-route、traffic-reroute、route-updated、arrive、emulator-end、stop、close-request、error、destroyed
instanceId / requestId string 归属与本次请求,初始化失败还未取得实例时可能为空
sequence / timestamp number 本组件单调事件序号与插件epoch毫秒;不是原厂事件总数/定位时间
state MapNaviState 当前状态快照;操作返回与真实回执分别看
routes MapNaviRouteResult或null 算路成功、选路、可用重算结果;其余null
info / location MapNaviInfo或null / MapNaviLocation或null 分别仅progress / location带本次数据;不在普通日志记录原始位置
cruise MapCruiseUpdate或null 仅cruise-start/update携带本次巡航数据;按kind读取,不能拿旧槽填新回执
waypointIndex number或null 原厂途经点索引,保留平台原值,不统一加1
gpsSignalLevel number或null 原厂数值等级;只有bool弱信号时为null,看reason weak/normal
reason string 安全原因标识,如weak/normal/hidden;无原生异常文案
errCode / errMsg / nativeErrorCode number / string / number或null 统一错误/安全说明/可用原码;成功为0/空/null

MapNaviInfo 与 MapNaviLocation:

字段 类型 说明
info.currentRoad / nextRoad string 当前/下一道路;未提供为空
info.remainingDistanceMeters / remainingDurationSeconds number或null 路线剩余米/秒
info.stepRemainingDistanceMeters / stepRemainingDurationSeconds number或null 当前路段剩余米/秒
info.maneuverCode number或null 平台原始转向编号,未承诺所有值跨端统一
location.coordinateType / latitude / longitude string / number / number amap/度,不从系统WGS坐标自行套转换
location.speedKmh number或null 已核实SDK单位km/h;模型0保留,不推断设备一定静止

高德原厂说明中国大陆及港澳台输出高德坐标,海外输出WGS84,因此导航结果使用amap标签;国内高德坐标为GCJ-02,示例输入采用国内高德坐标。坐标范围说明,高德坐标说明。

每条路线最多128标签,全部结果合计最多20路线/200000坐标,单文本4096 UTF16、最终UTF-8 16MiB,超界报24而非截断。核心高频进度/位置在同一次交付批次合并为最新值;结束/错误等保留顺序。界面展示本次实际字段,日志建议仅保留类型、实例/请求ID和错误码,并限制容量。

导航引擎是进程单例,宿主不得再并行直接管理同一导航SDK。getMapNaviState只读取本插件的导航缓存;空闲不代表其他代码未持有SDK或定位资源,创建时仍会检查实际占用。退出只清理本插件自己的视图、监听、路径和导航定位;Android先销毁自己的NaviView再销毁引擎,鸿蒙先解绑Builder再回收Factory,iOS移除自身representatives与强引用后检查destroy结果。SDK层released不等于已经实测OS全部采样/线程停止;撤权、服务关闭或异常不能确认时保留uncertain/busy。无回执时可能持续回收,需匹配环境核查或重启进程,不按定时器假解锁。重新同意隐私不复活旧路线/车辆/位置。

巡航结果与系统语音

字段 类型 说明
cruise.kind string statistics / facilities / cameras / congestion,其他槽为null
cruise.statistics MapCruiseStatistics或null 实际未提供为null,不补假零对象
statistics.distanceMeters / elapsedSeconds number或null 米/秒;有效0与小数保留,鸿蒙没有时间字段故为null
cruise.facilities MapCruiseFacility[]或null 实际nil为null,实际空数组为[],至多256项,超界拒绝而非截断
facilities[].nativeType number或null SDK原始整数类型,未承诺跨端枚举相同
facilities[].position MapCoordinate或null 实际高德坐标/度;无坐标不补当前定位
facilities[].distanceMeters / limitSpeedKmh number或null 米 / km/h,按实际SDK提供
cruise.congestion MapCruiseCongestion或null 本次null表示SDK清除拥堵
congestion.roadName / lengthMeters / durationSeconds / statusCode string / number或null / number或null / number或null 道路、米、秒、原始整数状态
参数 类型 必填 说明 默认值 可选参数
speakMapText.text string 是 原文送系统;trim后非空,合法代理对,允许换行/回车/tab,拒绝其他控制字符 无 ≤2000 UTF16且≤8000 UTF8字节
speakMapText.language string 否 当前共同合同仅普通话中文 zh-CN zh-CN
speakMapText.timeoutMs number 否 含初始化和播放的单调等待期限 60000 整数1000–120000ms
speakMapText.onEvent (event:MapSpeechEvent) => void 否 返回ID之后异步交付,回调异常不影响原生清理 无 state / start / complete / stop / error
stopMapSpeech.requestId string 是 只停止匹配的自己请求;旧/未知ID不影响新请求 无 本次返回ID

speakMapText 同步返回请求ID,同步门禁失败抛统一错误;受理后OS失败走事件。stopMapSpeech 返回void并立即抑制该请求用户交付;停止后用 getMapSpeechState 读取清理。getMapSpeechState 与 getMapSpeechCapabilities 只读缓存,不创建系统引擎,不申请麦克风或定位。

字段 类型 说明
MapSpeechState.platform / requestId MapPlatform / string 当前端/自有请求;空态ID为空
phase MapSpeechPhase idle / initializing / queued / speaking / stopping / completed / stopped / failed
busy / releaseState boolean / MapNaviReleaseState 占用与回收;终态仍可能busy,不能只按phase解锁
language / actualLanguage string / string或null 请求语言zh-CN / 实际系统Voice语言;未选定为null
textLength number 文字UTF16长度,不返回正文
startedAt / finishedAt number或null 插件epoch毫秒,未发生为null,不代表声卡时间
errCode / nativeErrorCode / reason number / number或null / string 统一错误、安全系统整数与固定原因,无原生异常/正文
MapSpeechEvent.type / requestId / sequence / timestamp string / string / number / number 请求关联、单调序号与插件epoch毫秒;start/complete仅真实系统回执
MapSpeechEvent.state / errCode / nativeErrorCode MapSpeechState / number / number或null 事件事实与状态快照;complete的errCode=0可与清理失败的state.errCode不同
MapSpeechCapabilities.platform / supported / languages MapPlatform / boolean / string[] App固定支持zh-CN;系统资源缺失真实失败;Web不支持、语言为空
maxTextLength / maxUtf8Bytes number App为2000 / 8000,Web为0
foregroundOnly / naviExclusive boolean App均true;隐藏停止,只与任意Navi owner双向互斥,不占用Navi全局诊断
offlineOnly boolean Android/Harmony可强制离线选择/模式为true;iOS无公开资产/联网探测为false
note string 当前系统与集成边界说明

Android仅选已安装、中文中国且无需联网的Voice;鸿蒙使用系统离线模式,资源缺失真实失败,不下载或改在线。iOS只调用系统AVSpeechSynthesizer,不接云服务,但没有公开接口保证设备离线资产和系统网络行为。无需地图Key或SDK初始化;隐私三项和前台仍须满足。系统引擎关闭及本地解绑只证明自身对象回收,不等于已在设备上验证物理声音或所有OS线程停止;初始化Promise未结束或清理无法确认时保持占用。

离线会话参数与输出

参数 类型 必填 说明 默认值 可选参数
start.options.timeoutMs number 否 目录等待期限,整数毫秒 30000 1000–120000
start.options.onEvent (event: MapOfflineEvent) => void 否 本会话所有任务事件,调用返回后交付 无 —
stop/getCatalog.sessionId string 是 当前会话 ID,最长 128;stop 的空/旧/未知 ID 无操作 无 start 返回值
download/pause/resume/remove.options.sessionId string 是 当前就绪会话 无 start 返回值
options.cityId string 是 当前目录城市 id,最长 256 无 catalog.cities[].id
options.timeoutMs number 否 单项等待期限,整数毫秒;超时不证明 SDK 已停止 下载/恢复900000;暂停/删除60000 1000–3600000

getMapOfflineState() 和 getMapOfflineCapabilities() 无参数,不构造 SDK、不弹权限。四项城市操作返回唯一 operationId。getMapOfflineCatalog() 未就绪报 9101010、失效会话报 9101008;停止会话立即清除本会话排队的用户回调,后台释放仍须读取真实状态。

字段 类型 说明
catalog.platform/sessionId/generation MapPlatform/string/number 平台、会话与目录代次;目录最多5000条,不静默截断
catalog.version/timestamp/cities string|null/number/MapOfflineCity[] SDK目录版本、读取毫秒时刻和真实城市;真实空数组保留
city.id/name/cityCode/adCode/provinceName string/string/string|null/string|null/string|null 不透明ID及SDK名称/区号/行政区码/省名,保留前导0
city.version/packageBytes string|null/number|null 真实逐城版本和包大小字节;iOS无逐城版本
city.downloadedBytes/expectedDownloadBytes number|null 实际可用字节;Android/鸿蒙均null,iOS也只在SDK明确提供时有值
city.status MapOfflineCityStatus not-downloaded、queued、downloading、unpacking、paused、downloaded、update-available、error或unknown
city.nativeStatus/nativeDownloadStatus/progressPercent number|null SDK缓存状态、下载阶段原码与实际阶段百分比0–100;0合法,缺失null
city.actions MapOfflineAction[] 当前可请求动作download/pause/resume/remove;实际调用仍重新门禁
state.phase/busy/releaseState MapOfflinePhase/boolean/MapNaviReleaseState none/loading/ready/closing/closed/error、owner占用与owned/releasing/released/uncertain
state.platform/sessionId/catalogReady/cityCount/generation MapPlatform/string/boolean/number/number 当前真实会话、目录就绪与条数/代次
state.operationId/operation/cityId/pending string/MapOfflineAction|null/string/boolean 最后或当前操作及未决管线;终态可保留操作ID
state.errCode/nativeErrorCode/reason number/number|null/string 统一错误、可用SDK原码和安全原因,不返回路径/Key/异常原文
event.type MapOfflineEventType state/ready/progress/download-complete/paused/removed/error/closed
event.sessionId/operationId/cityId/sequence/timestamp string/string/string/number/number 身份与会话递增序号、插件毫秒时间
event.state/city/catalog MapOfflineState/MapOfflineCity|null/MapOfflineCatalog|null 状态快照;city须真实对应项;只有ready携带catalog
event.errCode/nativeErrorCode/reason number/number|null/string 事件事实;可与后续清理的state错误不同
capabilities.platform/supported/maxSessions/maxConcurrentDownloads/maxCities MapPlatform/boolean/number/number/number App接口范围1/1/5000;Web不支持且上限0
capabilities.foregroundOnly/requiresAdvancedService/pauseDuringUnzip boolean App仅前台、需要高阶离线授权、解压暂停不保证
capabilities.downloadedBytesReported/deleteConfirmation/note boolean/MapOfflineDeleteConfirmation/string 字节仅iOS条件可用;Android/鸿蒙callback-and-sdk-cache,iOS sdk-cache;详细集成前提

宿主不得并行直接创建或操作其他离线 manager:SDK 内部是共享单例,插件只能约束自己的 owner。默认使用 SDK 应用专属存储,不新增广泛存储权限,不改全局网络或缓存目录。下载/删除必须由用户主动触发;只管理所选城市,不全盘清理,不删除文件系统目录。停止会话保留已安装数据。

Android/鸿蒙删除需匹配删除回执并读取 SDK 缓存确认;iOS 无删除回调,只确认该项 SDK 可见缓存缺失,不能据此声称物理文件擦除或线程已退出。目录构造、排队启动、解压或删除未决时,退出/超时后可能继续占用,需等待原 SDK 管线结算,不能用倒计时假释。三端均无城市中心字段,示例地图用明确的独立手动坐标。默认优先本地缓存不等于强制断网,断网底图须在已授权真机验收。

高级地图参数与输出

以下均为 lizhao-map 组件 ref 方法。层/项 ID 保留原值,1–64 字符、合法 UTF-16、无控制字符/首尾空白,同层项 ID 唯一,字符串 '0' 有效。坐标为 GCJ-02,尺寸和容量属于插件共同合同。

参数 类型 必填 说明 默认值 可选参数
setMarkerClusters.options.id / setHeatmap.options.id / setMultiPoints.options.id string 是 同类完整替换同ID;同类已有其他ID时返回16 无 合法层ID
MapAdvancedPoint.id / coordinate string / MapCoordinate 是 聚合/海量点每项业务ID和坐标 无 经度[-180,180]、纬度[-90,90]
setMarkerClusters.options.points MapAdvancedPoint[] 是 当前视口投影后划网格,单点也成组 无 1–5000项
setMarkerClusters.options.gridSize number 否 整数逻辑px 60 20–200
setHeatmap.options.points MapHeatmapPoint[] 是 每项含coordinate、weight 无 1–5000项
MapHeatmapPoint.coordinate MapCoordinate 是 共同合同限制纬度严格(-85,85),不称为iOS SDK原始限制 无 合法GCJ-02
MapHeatmapPoint.weight number 是 有限权重,0为零贡献;全部0不构造空provider 无 0–1000000
setHeatmap.options.radius number 否 原值送SDK;Android/鸿蒙瓦片px,iOS屏幕point 12 整数10–50
setHeatmap.options.opacity number 否 0保持完全透明 0.6 0–1
setMultiPoints.options.points MapAdvancedPoint[] 是 真SDK海量点层,所有项共享同一青绿圆点 无 1–20000项
setMultiPoints.options.iconSize number 否 圆点逻辑px,anchor固定0.5,0.5 12 整数4–64
三种options.visible boolean 否 真实显隐,false保留 true true / false
getMarkerClusters.layerId string 是 读取该层当前聚合缓存;未知层返回8 无 本实例cluster层ID
visibility/remove.reference.kind / id MapAdvancedLayerKind / string 是 setAdvancedLayerVisible/removeAdvancedLayer指定自有层 无 cluster / heatmap / multipoint
setAdvancedLayerVisible.visible boolean 是 设置指定层显隐,未知ref返回8 无 true / false
startPointMove.options.points MapCoordinate[] 是 原路径逐项送SDK,不能全部重复;独立专属点 无 2–2000项
startPointMove.options.durationSeconds number 否 整数秒,不提供统一SDK百分比 20 1–3600
startPointMove.options.timeoutMs number 否 整次原始截止含准备、回执、编码与交付,不在首帧重置 durationSeconds×1000+30000 整数1000–3720000
takeMapSnapshot.options / options.timeoutMs MapSnapshotOptions / number 否 整次等待预算,截图范围仅为原生地图视图 {} / 30000 整数1000–120000
stopPointMove.requestId / cancelMapSnapshot.requestId string 是 仅处理自己保存的匹配请求,空/旧/未知ID无操作 无 本实例相应请求ID
removeMapSnapshot.snapshotId string 是 只删除本实例已注册自有临时图;不接受路径 无 snapshot.id,空/未知无操作
clearAdvancedLayers / getAdvancedState / getMapAdvancedCapabilities 无 否 分别清理高级资源、读取实例状态、读取纯能力 无 无
字段 类型 说明
MapCluster.id / coordinate / memberIds / count string / MapCoordinate / string[] / number generation内不透明组ID、SDK反投影中心、实际业务成员和数量;相机变化会重新分组
MapAdvancedLayerInfo.kind / id / generation MapAdvancedLayerKind / string / number 图层身份、替换/重算代次;group ID不能用作长期POI ID
pointCount / effectivePointCount / nativeObjectCount / visible number / number / number / boolean 输入、有效、管理的SDK句柄数量与显隐;不是已渲染帧数量
gridSize / radius / opacity / iconSize number|null 对应种类参数;不适用字段为null
MapAdvancedState.platform / instanceId / active / ready MapPlatform / string / boolean / boolean 当前地图管理快照,纯查询不新建SDK对象
layers / move / snapshot / snapshots / retiredMoves MapAdvancedLayerInfo[] / MapPointMoveState / MapSnapshotState / MapSnapshot[] / number 三种层、移动/截图状态、最多4张自有图、进程保活的retired移动数量
errCode / nativeErrorCode / reason number / number|null / string 统一错误、安全原始数值、固定诊断;Native异常原文不会返回
MapPointMoveState.requestId / phase / busy / pending / releaseState string / MapPointMovePhase / boolean / boolean / MapNaviReleaseState idle/starting/moving/completed/closing/closed/error;busy为占用,pending为未确认原生工作;不能用超时推断已释放
markerPresent / durationSeconds boolean / number|null 管理的专属点是否仍存在、本次时长
remainingDistanceMeters / elapsedSeconds / passedPointCount number|null Android/鸿蒙返回SDK剩余米数,后两项null;iOS返回真实elapsed/passed,剩余米数null;0有效
position / positionSource MapCoordinate|null / 'sdk'|'input-endpoint'|'none' 真实SDK点;Android终点setter晚于回执时可用输入末点,并明确来源
MapSnapshotState.requestId / phase / busy / pending / releaseState string / MapSnapshotPhase / boolean / boolean / MapNaviReleaseState idle/pending/closing/closed/ready/error;无SDK取消时取消仅停止交付,槽继续保留
MapSnapshot.id / path / width / height string / string / number / number id等于请求ID,真实App缓存PNG路径、实际物理像素;不是宿主屏幕截图
renderStatus / complete / timestamp number|null / boolean|null / number 0→false、1→true、未知原码→null,无status→null/null;时间为epoch毫秒
MapAdvancedEvent.type MapAdvancedEventType clusters-changed、cluster-click、multipoint-click、move-start/update/complete/error、snapshot-ready/error、error
instanceId / requestId / layerKind / layerId / layerGeneration string / string / MapAdvancedLayerKind|null / string / number 层事件requestId空;请求事件无层;按所属实例和代次消费
sequence / timestamp / state number / number / MapAdvancedState 原生事件顺序、时间与该事件的管理快照;用户事件在方法返回后交付
cluster / point / move / snapshot MapCluster|null / MapAdvancedPoint|null / MapPointMoveState|null / MapSnapshot|null 只携带对应点击/移动/截图数据,其他为null;通用error全为null
MapAdvancedCapabilities.platform / supported / clusterAlgorithm MapPlatform / boolean / 'plugin-screen-grid'|'unsupported' 聚合为插件屏幕网格算法加真实SDK Marker,未声称SDK内建聚合
maxLayersPerKind / maxClusterPoints / maxHeatmapPoints / maxMultiPoints / maxMovePoints number App为1/5000/5000/20000/2000,Web全0;是插件预算,不承诺流畅性能
maxSnapshots / maxPendingMoves / maxPendingSnapshots number App为4/1/1;未决包括retired。进程同时live/retired移动合计最多4,启动前预占
maxSnapshotPixels / maxSnapshotBytes number App为16777216物理像素/67108864字节,超预算失败而非静默缩图
heatmapRadiusMin / heatmapRadiusMax / heatmapRadiusDefault / heatmapRadiusUnit number / number / number / string App为10/50/12;单位Android/鸿蒙sdk-pixel,iOSscreen-point,Webunsupported且数值0
foregroundOnly / note boolean / string 当前为true,note说明平台、预算及SDK原生取消边界;Web不建原生对象

clearAdvancedLayers() 清三种高级层、取消自有移动/截图并回收已注册临时图;clearOverlays() 仍只清普通覆盖物。隐藏取消移动与截图交付,静态层保留,返回前台不会自动续播。releaseState=uncertain 必须保留占用,不能按计时假释;SDK真终态与清理失败以实际状态为准。协议失败后重建地图再使用高级方法;invalid-result-last-known 是最后可信快照,不能当作当前释放确认。

前台围栏参数与输出

参数 类型 必填 说明 默认值 可选参数
options.startupTimeoutMs number 否 本地准备至首次公开交付的完整原始预算,整数毫秒 30000 1000..120000
options.onEvent (MapGeofenceEvent) => void 否 方法返回后异步交付;ready不等于围栏注册或定位成功 无 五种type见下表
options.sessionId string 注册/移除必填 start返回的会话标识,不用地图实例ID 无 当前自有会话
options.id string 注册/移除必填 业务ID,合法UTF-16、无控制符和首尾空白,'0'有效 无 1..64字符
options.center MapCoordinate 注册必填 GCJ-02,latitude -90..90、longitude -180..180,0合法 无 有限数值
options.radiusMeters number 否 圆半径米,允许小数;这是插件预算 1000 1..100000
options.timeoutMs number 否 SDK注册至首次公开成功交付的完整原始预算,整数毫秒 30000 1000..120000
stop/getMapGeofences的sessionId string 是 stop空/旧/未知ID幂等;读取未知ID报9101008,不伪造空记录 无 start返回值;stop另允许空
字段 类型 说明
capabilities.platform / supported / shapes MapPlatform / boolean / MapGeofenceShape[] 三App支持circle,Web unsupported/false/[];声明不证明Key已授权或设备行为
maxSessions / maxFences / maxPendingAdds number 插件1会话/4圈/1未决注册;四圈预算包含未决预留与移除中记录,Web均0
radiusMinMeters / radiusMaxMeters / radiusDefaultMeters number 1/100000/1000米,Web均0
timeoutMinMs / timeoutMaxMs / timeoutDefaultMs number 1000/120000/30000毫秒,Web均0
foregroundOnly / requiresFullAccuracy boolean 均true,为使用约束;创建前检查真实前台与现有精确授权,不自动提权
locationExclusive / locationFeed boolean / string 鸿蒙true/sdk-host-feed,独立真实定位送SDK doCheckFence,与旧定位/导航双向互斥;Android/iOS false/sdk-internal;Web false/unsupported
backgroundSupported / processRecoverySupported / reportsPosition boolean 均false;不返回当前位置,不保证后台/进程重启恢复
removalConfirmation / note string sdk-request-and-list-observation及实际边界说明,Web unsupported
state.platform / sessionId / phase MapPlatform / string / string none、preparing、ready、closing、closed、error;标识当前/最近自有会话
state.active / deliveryMode boolean / string 前台资格和open/terminal-only/closed;关闭后不因返回前台重开,terminal-only只交付安全错误
state.busy boolean 插件owner/未决/未知自有资源,false不证明OS/GPS/线程强停止
pendingRequestId / pendingFenceId / pendingRetired string / string / boolean 尚未结算SDK add的身份;空代表无未决;取消后retired仍占用直到真正回执
registeredCount / removingCount number 已确认与移除中自有记录数;不把未知名单补成0
sourceState string none/sdk-managed/starting/subscribed/stopping/unsubscribed/unknown;sdk-managed不等于已定位
cleanupLevel / sdkListObservation string none/requested/list-observed/uncertain;not-read/owned-present/owned-absent-observed/unknown。区分提交清理、名单观测和未知
state.errCode / nativeErrorCode / reason number / number或null / string 统一码、安全原生int32与安全原因;不输出异常原文或私有nonce
info.id / requestId / generation / nativeId string / string / number / string 业务ID、实际注册请求、代次、SDK不透明标识;不可互换或转数字
info.center / radiusMeters / requestedRadiusMeters MapCoordinate / number / number SDK确认的GCJ-02中心、实际半径、请求半径;保留float舍入差异
info.phase / deliveryEnabled / registeredAt string / boolean / number registered/removing/removed、当前本地交付资格、插件epoch毫秒;removed只出现在事件
lastRelation / nativeStatus / lastObservedAt string或null / number或null / number或null 三者null表示未观察;SDK 0/1/2/3映射unknown/inside/outside/stayed,时间为插件epoch毫秒
lastPresence / presenceObservedAt string / number或null present/absent-observed/unknown及最后名单观察时间,不是OS注册表强确认
event.type / origin string / string ready(plugin)、registered(sdk-registration)、status(sdk-status)、removed(sdk-list-observation)、error(plugin/SDK/location-source)
event.platform / sessionId / requestId / fenceId / generation 平台及标识/数值 与真实自有请求关联;管理级错误无圈时保持空ID/0,不强归到选中圈
event.sequence / timestamp number 自有会话事件顺序及插件epoch毫秒,不是SDK boot-time
event.state / fence MapGeofenceState或null / MapGeofenceInfo或null 状态快照与关联圆;仅无可信快照的plugin/error29允许state=null,不伪造已释放零状态
event.firstObservation boolean或null 仅status有值;true是插件首次接受关系,可能是初始内外状态,不能计算物理跨界次数
event.errCode / nativeErrorCode / reason number / number或null / string 非error统一码0,error非0;firstObservation=false、nativeStatus=0和空值均保留

三端只启用进入/离开激活,SDK可能返回unknown或stayed;没有自定义停留时长承诺。Android/iOS注册后由专用SDK内部定位,鸿蒙由独立真实定位回调驱动SDK判断;两者均不在插件中计算距离伪造关系。围栏不依赖地图创建,示例按需画出的圆只是输入/确认几何,不能证明监控已经运行。Web只预览界面,不生成成功或定位事件。

围栏API调用顺序

能力与管理状态纯读;startMapGeofenceSession → 等本地ready → addMapCircleGeofence → 等真实registered/status → getMapGeofences。removeMapGeofence按sessionId+业务ID精确移除,stopMapGeofenceSession结束自己的会话。页面隐藏/退出和撤隐私均关闭交付;SDK无删除terminal,正常名单缺失可释放逻辑记录,未决注册/部分启动不明则保留真实busy。

错误码说明

错误码 原因 处理
9101001 Key 为空 填写当前平台 Key
9101002 隐私条件未满足 实际展示政策并取得同意后再提交配置
9101003 应用上下文不可用 应用启动后重试
9101004 SDK 或原生操作失败 检查应用上下文、依赖与原生环境
9101005 进程已绑定其他 Key 重启应用后更换
9101006 当前平台或固定 SDK 没有对应能力 查看能力查询,按实际支持使用
9101007 原生 SDK 尚未初始化 完成隐私与初始化后重试,地图按需重建
9101008 原生实例或会话已失效 重建自己的实例或会话,重新获取目录凭据
9101009 输入参数不合法 检查有限数、坐标、几何、ID、图片、样式、查询组合与时间范围
9101010 当前模块尚未加载就绪 等待对应ready,检查网络、Key与匹配基座;离线目录未就绪时不发城市操作
9101011 未取得前台定位权限 申请权限或查看本应用授权设置
9101012 系统定位服务关闭 到系统设置开启定位服务后重查
9101013 权限、定位或查询等待超时 检查运行条件与网络,按需调整有效超时;查询仍可能等待底层回执
9101014 主动取消或页面结束等待 不把取消当作成功,重试时使用新请求 ID
9101015 SDK 定位失败或结果不合法 查看纯数字 nativeErrorCode 并核对 Key、网络与环境
9101016 导航/定位/系统语音资源互斥或查询记录达到上限 查询各模块实际状态,等待SDK回执/自有资源释放;回收未确认时不创建新实例
9101017 指定覆盖物不存在 检查类型、业务ID、地图实例及是否已被清除
9101018 持续定位运行条件不满足 从前台开始,检查后台授权、通知、服务及宿主原生配置
9101019 会话不存在或已被新会话替换 使用最近成功受理的会话ID读取/清空轨迹
9101020 搜索失败或结果超界/不合法 检查Key、网络、参数及纯数字nativeErrorCode;不记录原厂异常原文
9101021 指定POI未找到 核对实际POI ID,重新搜索;无详情不是空POI成功
9101022 地理信息/工具失败、结果超界或无效 检查输入、Key、网络、SDK环境和纯数字nativeErrorCode;矩阵先区分整体失败与逐项失败
9101023 路线失败、结果超界或无效 检查方式/策略、真实服务、Key和有限数字nativeErrorCode;空方案不等于该错误
9101024 导航操作失败、原生结果无效或超界 核对权限/精度、应用Key与身份、网络和SDK集成;nativeErrorCode仅提供安全原码
9101025 导航状态或路线凭据失效 等ready后算路、从本实例结果选路;终止后重建,不能传Search方案或旧routeId
9101026 系统语音初始化、播报或回收失败 确认中文系统语音资源与前台条件,读取busy/releaseState;不自动下载/切在线
9101027 离线地图加载、任务、协议或回收失败 先确认高阶离线授权与前台;读取pending/busy/releaseState,等待SDK回执,未知占用不强制重建
9101028 高级图层、点移动、地图截图或协议/回收失败 检查本地图ready、原生SDK与输入预算,读取真实state;受控失败可能已安装新层或留下清理债,不能假定回滚成功
9101029 围栏SDK、协议或清理失败 检查已有精确授权/服务/前台与SDK配置;读取真实state/busy,名单缺失不代表系统定位停止,不强制重建未知占用

示例与平台接入

平台 最低系统 当前接入状态
Android Android 6 / API 23 上述公开能力已提供原生实现,UTS/原生编译及完整示例资源生成通过;匹配自定义基座、真实服务与设备运行待验证
iOS iOS 15 已提供Swift原生桥接与JS校验实现并核对固定SDK声明;Apple工具链类型检查、链接、App构建及设备运行待验证
HarmonyOS NEXT HarmonyOS 6 / API 20 UTS/ArkTS原生编译及未签名打包通过;后台定位需API21+,签名、真实服务及设备运行待验证
Web、小程序 无 原生地图与初始化不可用;Web 仅提供诚实占位及界面预览

示例首页为宿主 pages/index/index.uvue,宿主 pages.json 注册17条真实路由。完整演示位于插件 example/uniappx/,覆盖接入、地图、定位、覆盖物、查询、工具、路线、导航、巡航语音、离线、地图进阶、围栏与业务串联。结果按实际字段、空值和失败展示;Web提供界面预览与本地校验。

iOS 使用 HBuilderX 5.34 及以上版本,通过插件根入口导入。请完整保留 utssdk/app-ios/interceptor.js、bridge-core.uts 与 facade/:同步校验和统一错误在 JS 层处理,SDK 调用通过原生桥接完成。插件根 index.d.ts 提供公开类型声明,导入时应保留整个插件目录。

路线页包含五种方式、完整参数、公交备选与真实分段;导航配置/展示两页包含四种方式、Navi独立算路、选路、GPS/模拟、实时信息和释放状态。串联页把明确选择的端点与模拟设置一次性交接给Navi重新算路,Search方案ID不能作为导航凭据。地图进阶提供三种数据层、点移动和临时截图;前台围栏提供真实注册、关系和自有清理。Android Key绑定宿主包名与签名,iOS Key绑定Bundle ID,鸿蒙Key绑定高德要求的应用身份。

后台定位需要宿主原生集成配置,导入源码后应重新制作匹配基座或运行包:

  • Android插件Manifest含FOREGROUND_SERVICE、FOREGROUND_SERVICE_LOCATION、POST_NOTIFICATIONS及location类型的私有服务。采用从前台启动定位前台服务路径,不自动申请ACCESS_BACKGROUND_LOCATION。Android13+主动申请通知,旧系统仍读取真实通知开关。通知支持点击回App及停止本会话。
  • iOS插件Info.plist含UIBackgroundModes.location及WhenInUse用途说明;确认最终Bundle保留能力并签名后使用。只请求使用期间授权,从前台开始的连续后台定位不请求Always,也不提供进程重启恢复。使用原生后台位置指示。
  • 鸿蒙前台持续最低API20,后台最低API21。插件声明LOCATION_IN_BACKGROUND、KEEP_BACKGROUND_RUNNING及定位用途;后台位置授权需用户进入设置,通知单独申请。宿主EntryAbility的backgroundModes须含location:将自己的生成entry/src/main/module.json5复制到项目harmony-configs/entry/src/main/module.json5,在原Ability上添加该字段并保留宿主配置。本项目已提供该真实覆盖文件。详见DCloud鸿蒙配置覆盖说明;最终检查生成HAP的合并结果。

Android 固定导航地图定位搜索合包 11.3.100_3dmap11.3.100_loc11.3.000_sea9.8.1。iOS 固定 NO-IDFA Navi 11.2.100、Location 2.12.2、Search 9.8.1、Foundation 1.9.1。鸿蒙固定 navi/common/location/search 11.2.1,地图使用导航包内实现,无需再添加另一地图 SDK。

注意事项

  • 三项隐私必须全部为 true 才允许初始化,宿主负责政策内容与用户选择。
  • 仅将 Key 保存在当前进程中,示例不会持久化 Key,运行日志不包含 Key。
  • 同 Key 可以重复初始化,进程开始配置后更换 Key 需要重启。
  • 错误演示会改变当前隐私状态,测试后需重新同意并初始化。
  • 隐私撤回会关闭所有地图;恢复同意并初始化后,须创建新组件。页面隐藏传 active=false,退出移除组件以释放 SDK 监听和地图资源。
  • 地图浏览、覆盖物及按手动条件搜索不主动申请定位权限,不显示当前位置蓝点。定位由用户主动触发;示例地图中心联动真实结果。路线规划使用独立Search结果;驾车导航使用Navi自身真实路径组,两者ID不能互换。
  • 搜索数据通过各端原生高德SDK发送,宿主需向用户说明关键词、城市、输入中心/范围及POI ID的用途。搜索页不自动逐字请求,隐私撤回会结束搜索等待并清除页面地点与地图缓存;已发送的数据不能由插件追溯撤回。
  • 搜索取消与定位取消分别使用各自API。页面隐藏/退出仅取消自己保存的搜索ID,迟到回调不能覆盖新条件的列表。新提示成功后清除旧提示的地图关联,需重新选择本次提示;分页使用成功query快照,不将输入修改与旧页码混用。
  • 地理信息/矩阵使用cancelMapGeoRequest,原生四槽与地点搜索分别管理。Android/鸿蒙取消后仍等SDK回执释放retired记录;iOS只取消各请求自己的API实例。超时不修改SDK全局网络设置,也不承诺已经撤销远端请求。
  • 地址、起终点、行政区和转换来源均是用户输入条件。坐标转换可原样返回,changed/dataAvailable不是鉴权或转换正确性证明;矩阵整体成功时仍要逐项判断success,失败项不能用0代替null。工具和投影不申请定位,SDK行为仍须隐私披露。
  • 行政区边界保留原厂多段及顶点;省市大边界可能超过单地图图形5000点限制。示例通过分段或选择边界展示,并明确说明未绘制部分;不要为显示方便静默改写查询结果。矩形/多边形面积为SDK估算,输入限制、极区与日期线边界见参数表。
  • 覆盖物按地图实例/类型/ID隔离,upsert完整替换;移除/隐藏标记关闭气泡,退出释放监听。实际拖动后重新读取位置,避免用旧表单坐标覆盖拖动结果。
  • 高级图层和点移动使用宿主主动提供的点与路径;移动路径不是实际定位轨迹。地图截图只含当前地图区域,写入应用临时PNG,由本实例管理回收;插件不主动上传截图,宿主导出或分享应另行说明用途。
  • 前台围栏由SDK处理用户输入的圆形区域和定位关系,不提供后台或进程恢复;隐藏/退出清理自己的会话。首条inside/outside可能是初态,SDK名单缺席不能证明系统定位线程已经停止。
  • 定位用途文案请按宿主实际业务检查。Android/iOS持续后台沿用前台/使用期间授权与各端后台机制;鸿蒙后台位置权限由用户在系统设置开启。系统授权、通知、服务和SDK初始化为独立条件。
  • 会话与单次定位互斥,停止/异步清理期间保留互斥。后台模式由用户主动开始;返回前台读取原生轨迹,页面真正退出时停止自己的ID,不在App退后台时误停后台会话。系统杀进程、撤权、省电或厂商限制可结束运行,插件不绕过系统限制。
  • 鸿蒙定位会暂时关闭高德 SDK 的自动长任务策略,由插件管理自己的系统任务,全部清理后恢复原值。同一进程在本插件定位运行期间应避免通过其他入口改写该 SDK 全局开关。
  • 固定鸿蒙 SDK 11.2.1 的停止方法会检查定位授权。插件先关闭该管理器的后台选项,再确认自身监听已停止;前台授权全部撤回或系统注销失败时仍保留 stopping,恢复前台授权/服务后自动重试。若 SDK 部分启动且从未确认 isStarted,无法证明已回收时需结束应用进程后重新进入;仅返回页面不能解除这类占用,期间新定位仍返回9101016。此时自有系统后台任务仍会独立回收,不全量停止宿主任务。
  • Android 关闭公开定位缓存开关并排除明确的缓存结果;iOS/鸿蒙使用新管理器和真实单次 API,SDK 没有相同缓存开关时不伪造该能力,返回原始位置时间。鸿蒙 SDK 的在途系统单次请求无法强行中止时,取消后清理 SDK/回调并丢弃迟到结果。
  • 地图、定位、查询及Search路线按各自返回的coordinateType使用GCJ-02,角度单位为度、缩放为级别。导航结果标记为amap,保留SDK原厂坐标:国内GCJ-02、海外WGS84,不二次纠偏;不要把原始WGS-84输入直接当作GCJ-02。
  • 原生指南针可见性受旋转状态影响。统一缩放按钮与四类地图手势分别配置,保留原厂 Logo。
  • 示例图标随插件位于 static/icons/,统一为 24 × 24、2px 线宽的线性 SVG;请保留资源路径。
  • 原生 SDK 运行需要匹配依赖的集成环境,iOS 需要可用的原生构建环境和签名。
  • 高德SDK的数据处理、固定依赖和使用条件见第三方说明及原厂政策;宿主须按实际启用的能力披露并取得授权。

作者系列 UTS 插件

以下为作者已上架的 UTS 插件,详情见各市场页面或作者主页。作者主页

插件 能力方向 插件市场
lizhao-app-keepalive 应用保活、唤醒、自愈与报告 查看插件
lizhao-bg-audio 背景音频播放、队列、倍速与事件 查看插件
lizhao-ble BLE 扫描、连接、读写、通知与自动重连 查看插件
lizhao-notify-pro 本地通知、点击动作、进度与定时提醒 查看插件
lizhao-smart-tts 系统 TTS、云端合成、听书方案 查看插件

隐私、权限声明

1. 本插件需要申请的系统权限列表:

定位由用户主动触发。导航两模式创建前均需前台定位与系统服务,GPS另需精确位置;当前导航仅前台,隐藏终止。前台围栏需精确定位与系统服务,隐藏停止本会话交付并清理,不提供后台或进程恢复;鸿蒙与本插件持续定位/导航互斥。独立后台定位:Android使用定位前台服务与通知,iOS使用期间授权及location后台能力,鸿蒙另需后台位置、通知与长时任务配置。截图写应用缓存,不额外申请相册或广泛存储许可。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件仅在当前进程保存Key与配置。用户主动查询/算路的关键词、地址、范围、起终点与途经坐标、POI ID、策略、公交时刻及车辆参数会由原生SDK提交高德服务。导航引擎创建即定位,导航/巡航按SDK处理位置、路径与内置语音。前台围栏把用户输入的中心/半径交给SDK注册,由SDK使用位置观察关系。高级图层和点移动处理宿主主动提供的点与路径;地图截图写入应用临时PNG,由本实例管理回收,插件不主动上传截图。业务串联仅在进程内存一次性交接端点和设置,URL只含不透明关联ID。独立播报文本仅传系统合成API,诊断不返回正文;Android/鸿蒙强制离线,iOS系统网络行为无公开保证。离线SDK可能按自身策略更新目录,用户主动选城下载或删除;插件不改变全局网络策略。取消等待不能撤回已发送请求,宿主须按实际用途披露与授权。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。