欢迎加入开源鸿蒙跨平台社区 :https://openharmonycrossplatform.csdn.net

📋 前言
地图功能已经成为许多应用的核心特性。无论是出行导航、位置分享、还是周边服务搜索,地图都扮演着重要角色。react-native-maps 是 React Native 生态中最流行的地图组件库,提供了丰富的地图渲染和交互功能,让开发者能够快速集成地图能力。
🎯 库简介
基本信息
- 库名称 :
react-native-maps - 版本信息 :
1.10.4+@react-native-ohos/react-native-maps: 支持 RN 0.72 版本1.24.4+@react-native-ohos/react-native-maps: 支持 RN 0.77 版本
- 官方仓库: https://github.com/react-native-oh-library/react-native-maps
- 主要功能 :
- 🗺️ 地图显示与交互
- 📍 标记点(Marker)支持
- 🔵 圆形、多边形、折线覆盖物
- 🎯 地图相机控制
- 📱 支持 HarmonyOS 华为地图服务
为什么选择 react-native-maps?
| 特性 | 原生地图开发 | react-native-maps |
|---|---|---|
| 跨平台一致性 | ❌ 需分别开发 | ✅ 统一 API |
| 开发效率 | ⚠️ 较低 | ✅ 快速集成 |
| 维护成本 | ⚠️ 较高 | ✅ 社区维护 |
| HarmonyOS 支持 | ❌ 需自行适配 | ✅ 官方适配版本 |
| TypeScript 支持 | ⚠️ 需自行定义 | ✅ 完整类型定义 |
支持的组件
| 组件 | 说明 | HarmonyOS 支持 |
|---|---|---|
MapView |
地图容器组件 | ✅ |
Marker |
标记点 | ✅ |
Circle |
圆形覆盖物 | ✅ |
Polygon |
多边形覆盖物 | ✅ |
Polyline |
折线覆盖物 | ✅ |
Callout |
信息弹窗 | ✅ |
UrlTile |
瓦片图层 | ✅ |
WMSTile |
WMS 瓦片图层 | ✅ |
Overlay |
图片覆盖物 | ✅ |
Geojson |
GeoJSON 支持 | ✅ |
Cluster |
标记聚合 | ✅ |
兼容性验证
在以下环境验证通过:
- RNOH : 0.72.90; SDK : HarmonyOS 6.0.0 Release SDK; IDE : DevEco Studio 6.0.2; ROM: 6.0.0
⚠️ 重要提示:华为地图服务申请
🔴 注意 :使用
react-native-maps的 HarmonyOS 版本需要先开通华为地图服务(Map Kit)。未开通地图服务将导致地图无法正常显示!
为什么需要开通地图服务?
华为地图服务(Map Kit)是云端服务,需要通过华为服务器进行鉴权:
应用 → 请求地图数据 → 华为服务器 → 验证身份 → 返回地图数据
这与 Google Maps 需要 Google Cloud Console 配置 API Key 是类似的原理。
版本差异说明
根据您的开发环境版本,配置流程有所不同:
| 环境版本 | 配置复杂度 | 是否需要 Client ID | 是否需要公钥指纹 |
|---|---|---|---|
| HarmonyOS 5.0.2+ 且 DevEco Studio 6.0.0+ | ✅ 简单 | ❌ 不需要 | ❌ 不需要 |
| HarmonyOS 5.0.2 以下 或 DevEco Studio 6.0.0 以下 | ⚠️ 复杂 | ✅ 需要 | ✅ 需要 |
🚀 方案一:HarmonyOS 5.0.2+ 且 DevEco Studio 6.0.0+(推荐使用,我用的也是这个)
适用条件:HarmonyOS SDK 5.0.2(14) 及以上版本,且 DevEco Studio 6.0.0 Beta5 及以上版本
第一步:注册华为开发者账号
- 访问 华为开发者联盟
- 点击"注册"按钮,完成账号注册
- 完成实名认证(个人或企业)
第二步:通过 DevEco Studio 自动开通地图服务
🎉 优势:DevEco Studio 6.0.0+ 支持一键开通地图服务,无需手动配置 Client ID 和公钥指纹!
1. 配置签名
- 打开 DevEco Studio
- 选择 File → Project Structure
- 进入 Project → Signing Configs 页面
- 勾选 Automatically generate signature
- 登录华为开发者账号
- 点击 OK 完成签名配置
2. 开通地图服务
如果bundle name不能申请,说名称已经存在了,就换一个不存在的。我改完以后,app.json5自动同步了bundle名称。
- 在 Signing Configs 页面
- 点击 Enable open capabilities 按钮
- 在弹出的服务列表中,勾选 Map Kit
- 点击 OK 完成配置

✅ DevEco Studio 会自动完成以下操作:
- 在 AppGallery Connect 创建/关联项目和应用
- 开通地图服务权限
- 配置签名信息
- 生成并下载 Profile 文件
第三步:安装依赖
在项目根目录执行以下命令:

bash
# RN 0.72 版本
npm install @react-native-ohos/react-native-maps@1.10.4-rc.1
# RN 0.77 版本
npm install @react-native-ohos/react-native-maps@1.24.4-rc.1
第四步:配置权限
1. 在 module.json5 中添加权限
打开 harmony/entry/src/main/module.json5,在 requestPermissions 中添加:
json
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
"reason": "$string:internet_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "$string:location_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.LOCATION",
"reason": "$string:location_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
}
2. 添加权限说明字符串
打开 harmony/entry/src/main/resources/base/element/string.json,添加:
json
{
"string": [
{
"name": "internet_reason",
"value": "用于加载地图数据"
},
{
"name": "location_reason",
"value": "用于显示您的位置和导航"
}
]
}
第五步:原生代码配置
1. 添加依赖
打开 harmony/entry/oh-package.json5,添加依赖:
json5
{
"dependencies": {
"@rnoh/react-native-openharmony": "0.72.90",
"@react-native-ohos/react-native-maps": "file:../../node_modules/@react-native-ohos/react-native-maps/harmony/maps.har"
}
}
2. 同步依赖
点击 DevEco Studio 右上角的 Sync Now 按钮,或执行:
bash
cd harmony/entry
ohpm install
3. 配置 CMakeLists.txt
打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加 Maps 模块:
c
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1)
add_compile_definitions(WITH_HITRACE_SYSTRACE)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
# 添加 Maps 模块
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-maps/src/main/cpp" ./maps)
file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
add_library(rnoh_app SHARED
${GENERATED_CPP_FILES}
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
# 链接 Maps 库
+ target_link_libraries(rnoh_app PUBLIC rnoh_maps)
4. 修改 PackageProvider.cpp
打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:
cpp
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "MapsPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
+ std::make_shared<MapsPackage>(ctx),
};
}
5. 在 ArkTS 侧引入组件
打开 harmony/entry/src/main/ets/pages/Index.ets(或 LoadBundle.ets),添加:
typescript
import {
AIRMap,
AIR_MAP_TYPE,
AIRMapMarker,
AIR_MAP_MARKER_TYPE,
AIRMapPolyline,
AIR_MAP_POLYLINE_TYPE,
AIRMapPolygon,
AIR_MAP_POLYGON_TYPE,
AIRMapCircle,
AIR_MAP_CIRCLE_TYPE,
AIRMapCallout,
AIR_MAP_CALLOUT_TYPE,
AIRMapCalloutSubview,
AIR_MAP_CALLOUT_SUBVIEW_TYPE,
Geojson,
AIR_GEOJSON_TYPE,
AIRMapUrlTile,
AIR_URLTILE_TYPE,
AIRMapWMSTile,
AIR_WMSTILE_TYPE,
AIRMapOverlay,
AIR_OVERLAY_TYPE,
AIRMapCluster,
AIR_MAP_CLUSTER_TYPE,
} from "@react-native-ohos/react-native-maps"
@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {
if (ctx.componentName === AIR_MAP_TYPE) {
AIRMap({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_MARKER_TYPE) {
AIRMapMarker({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_POLYLINE_TYPE) {
AIRMapPolyline({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_POLYGON_TYPE) {
AIRMapPolygon({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CIRCLE_TYPE) {
AIRMapCircle({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CALLOUT_TYPE) {
AIRMapCallout({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CALLOUT_SUBVIEW_TYPE) {
AIRMapCalloutSubview({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_GEOJSON_TYPE) {
Geojson({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_URLTILE_TYPE) {
AIRMapUrlTile({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_WMSTILE_TYPE) {
AIRMapWMSTile({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_OVERLAY_TYPE) {
AIRMapOverlay({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CLUSTER_TYPE) {
AIRMapCluster({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
}
}
const arkTsComponentNames: Array<string> = [
AIR_MAP_TYPE,
AIR_MAP_MARKER_TYPE,
AIR_MAP_POLYLINE_TYPE,
AIR_MAP_POLYGON_TYPE,
AIR_MAP_CIRCLE_TYPE,
AIR_MAP_CALLOUT_TYPE,
AIR_MAP_CALLOUT_SUBVIEW_TYPE,
AIR_GEOJSON_TYPE,
AIR_URLTILE_TYPE,
AIR_WMSTILE_TYPE,
AIR_OVERLAY_TYPE,
AIR_MAP_CLUSTER_TYPE,
]
6. 引入 MapsPackage
打开 harmony/entry/src/main/ets/RNPackagesFactory.ts,添加:
typescript
import type { RNPackageContext, RNPackage } from 'rnoh/ts';
import { MapsPackage } from '@react-native-ohos/react-native-maps/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new MapsPackage(ctx),
];
}
第六步:运行项目
- 连接 HarmonyOS 设备或启动模拟器
- 点击 DevEco Studio 的运行按钮
- 地图应该正常显示
⚠️ 方案二:HarmonyOS 5.0.2 以下 或 DevEco Studio 6.0.0 以下(不推荐,要适配RN0.7x,还是用最新版)
适用条件:HarmonyOS SDK 5.0.2(14) 以下版本,或 DevEco Studio 6.0.0 Beta5 以下版本
⚠️ 注意:此方案需要手动配置 Client ID 和公钥指纹,流程较为复杂。建议升级到新版本以简化配置。
第一步:注册华为开发者账号
- 访问 华为开发者联盟
- 点击"注册"按钮,完成账号注册
- 完成实名认证(个人或企业)
第二步:在 AppGallery Connect 创建项目和应用
1. 登录 AppGallery Connect
访问 AppGallery Connect 并登录
2. 创建项目
- 点击"我的项目"
- 点击"创建项目"
- 填写项目名称,选择项目类型
- 点击"确定"完成创建
3. 创建应用
- 在项目详情页,点击"添加应用"
- 选择应用平台:HarmonyOS
- 填写应用信息:
- 应用名称:您的应用名称
- 应用包名 :必须与项目
app.json5中的bundleName一致 - 应用类型:选择"APP"
- 点击"确定"完成创建
⚠️ 重要 :应用包名必须与 HarmonyOS 项目中的
bundleName完全一致!
第三步:开通地图服务
- 登录 AppGallery Connect
- 进入项目详情页
- 选择 开发与服务 → API 管理
- 找到 地图服务 开关,打开开关
- 确认已开启"地图服务"
第四步:配置签名证书
🔴 关键步骤:开通地图服务后,必须重新申请 Profile 文件!
1. 生成签名证书
在 DevEco Studio 中:
- 选择 Build → Generate Key and CSR
- 填写证书信息:
- Key Alias: 密钥别名(如:key0)
- Password: 密钥密码
- Validity: 有效期(建议 25 年)
- First and Last Name: 姓名
- Organization: 组织名称
- 选择保存路径,生成
.p12文件和.csr文件
2. 申请调试证书
- 登录 AppGallery Connect
- 进入 用户与访问 → 证书管理
- 点击"新增证书"
- 选择证书类型:调试证书
- 上传
.csr文件 - 点击"提交",下载
.cer证书文件
3. 申请 Profile 文件
- 进入 应用信息 → HAP Provision Profile 管理
- 点击"添加"
- 选择类型:调试 Profile
- 选择已申请的调试证书
- 点击"提交",下载
.p7bProfile 文件
⚠️ 重要:开通地图服务后,必须重新申请 Profile 文件,否则地图无法正常显示!
第五步:获取并配置 Client ID
1. 获取 Client ID
- 在 AppGallery Connect 项目详情页
- 进入 项目设置 → 常规
- 找到应用的 Client ID(客户端 ID)
- 复制此 ID
2. 配置 Client ID
打开 harmony/entry/src/main/module.json5,在 metadata 中添加 Client ID:
json5
{
"module": {
"name": "entry",
"type": "entry",
"metadata": [
{
"name": "client_id",
"value": "110168601" // 替换为您在 AGC 获取的 Client ID
}
]
}
}
第六步:配置应用包名
打开 harmony/AppScope/app.json5,确保 bundleName 与 AppGallery Connect 中创建的应用包名一致:
json5
{
"app": {
"bundleName": "com.example.yourapp", // 必须与 AGC 中的应用包名一致
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name"
}
}
第七步:配置签名
打开 harmony/build-profile.json5,配置签名信息:
json5
{
"app": {
"signingConfigs": [
{
"name": "default",
"type": "HarmonyOS",
"material": {
"certpath": "E:/certs/yourapp.cer", // 调试证书路径
"storePassword": "0000001F46D5FEE28...", // 密钥库密码
"keyAlias": "key0", // 密钥别名
"keyPassword": "0000001F2B30EA30...", // 密钥密码
"profile": "E:/certs/yourappDebug.p7b", // Profile 文件路径
"signAlg": "SHA256withECDSA",
"storeFile": "E:/certs/yourapp.p12" // 密钥库文件路径
}
}
]
}
}
第八步:安装依赖
在项目根目录执行以下命令:
bash
# RN 0.72 版本
npm install @react-native-ohos/react-native-maps@1.10.4-rc.1
# RN 0.77 版本
npm install @react-native-ohos/react-native-maps@1.24.4-rc.1
第九步:配置权限
1. 在 module.json5 中添加权限
打开 harmony/entry/src/main/module.json5,在 requestPermissions 中添加:
json5
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
"reason": "$string:internet_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "$string:location_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.LOCATION",
"reason": "$string:location_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
}
2. 添加权限说明字符串
打开 harmony/entry/src/main/resources/base/element/string.json,添加:
json
{
"string": [
{
"name": "internet_reason",
"value": "用于加载地图数据"
},
{
"name": "location_reason",
"value": "用于显示您的位置和导航"
}
]
}
第十步:原生代码配置
1. 添加依赖
打开 harmony/entry/oh-package.json5,添加依赖:
json5
{
"dependencies": {
"@rnoh/react-native-openharmony": "0.72.90",
"@react-native-ohos/react-native-maps": "file:../../node_modules/@react-native-ohos/react-native-maps/harmony/maps.har"
}
}
2. 同步依赖
点击 DevEco Studio 右上角的 Sync Now 按钮,或执行:
bash
cd harmony/entry
ohpm install
3. 配置 CMakeLists.txt
打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加 Maps 模块:
cmake
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1)
add_compile_definitions(WITH_HITRACE_SYSTRACE)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
# 添加 Maps 模块
add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-maps/src/main/cpp" ./maps)
file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
add_library(rnoh_app SHARED
${GENERATED_CPP_FILES}
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
# 链接 Maps 库
target_link_libraries(rnoh_app PUBLIC rnoh_maps)
4. 修改 PackageProvider.cpp
打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:
cpp
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
#include "MapsPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
std::make_shared<MapsPackage>(ctx),
};
}
5. 在 ArkTS 侧引入组件
打开 harmony/entry/src/main/ets/pages/Index.ets(或 LoadBundle.ets),添加:
typescript
import {
AIRMap,
AIR_MAP_TYPE,
AIRMapMarker,
AIR_MAP_MARKER_TYPE,
AIRMapPolyline,
AIR_MAP_POLYLINE_TYPE,
AIRMapPolygon,
AIR_MAP_POLYGON_TYPE,
AIRMapCircle,
AIR_MAP_CIRCLE_TYPE,
AIRMapCallout,
AIR_MAP_CALLOUT_TYPE,
AIRMapCalloutSubview,
AIR_MAP_CALLOUT_SUBVIEW_TYPE,
Geojson,
AIR_GEOJSON_TYPE,
AIRMapUrlTile,
AIR_URLTILE_TYPE,
AIRMapWMSTile,
AIR_WMSTILE_TYPE,
AIRMapOverlay,
AIR_OVERLAY_TYPE,
AIRMapCluster,
AIR_MAP_CLUSTER_TYPE,
} from "@react-native-ohos/react-native-maps"
@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {
if (ctx.componentName === AIR_MAP_TYPE) {
AIRMap({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_MARKER_TYPE) {
AIRMapMarker({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_POLYLINE_TYPE) {
AIRMapPolyline({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_POLYGON_TYPE) {
AIRMapPolygon({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CIRCLE_TYPE) {
AIRMapCircle({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CALLOUT_TYPE) {
AIRMapCallout({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CALLOUT_SUBVIEW_TYPE) {
AIRMapCalloutSubview({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_GEOJSON_TYPE) {
Geojson({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_URLTILE_TYPE) {
AIRMapUrlTile({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_WMSTILE_TYPE) {
AIRMapWMSTile({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_OVERLAY_TYPE) {
AIRMapOverlay({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
} else if (ctx.componentName === AIR_MAP_CLUSTER_TYPE) {
AIRMapCluster({
ctx: ctx.rnComponentContext,
tag: ctx.tag,
})
}
}
const arkTsComponentNames: Array<string> = [
AIR_MAP_TYPE,
AIR_MAP_MARKER_TYPE,
AIR_MAP_POLYLINE_TYPE,
AIR_MAP_POLYGON_TYPE,
AIR_MAP_CIRCLE_TYPE,
AIR_MAP_CALLOUT_TYPE,
AIR_MAP_CALLOUT_SUBVIEW_TYPE,
AIR_GEOJSON_TYPE,
AIR_URLTILE_TYPE,
AIR_WMSTILE_TYPE,
AIR_OVERLAY_TYPE,
AIR_MAP_CLUSTER_TYPE,
]
6. 引入 MapsPackage
打开 harmony/entry/src/main/ets/RNPackagesFactory.ts,添加:
typescript
import type { RNPackageContext, RNPackage } from 'rnoh/ts';
import { MapsPackage } from '@react-native-ohos/react-native-maps/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new MapsPackage(ctx),
];
}
第十一步:运行项目
- 连接 HarmonyOS 设备或启动模拟器
- 点击 DevEco Studio 的运行按钮
- 地图应该正常显示
📖 API 详解
🔷 MapView - 地图容器
MapView 是地图的核心容器组件,用于显示地图和控制地图状态。
typescript
import MapView from 'react-native-maps';
<MapView
style={{ flex: 1 }}
initialRegion={{
latitude: 39.9042,
longitude: 116.4074,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
/>
主要属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
initialRegion |
Region | ❌ | 初始显示区域 | ✅ |
region |
Region | ❌ | 当前显示区域(受控) | ✅ |
camera |
Camera | ❌ | 相机配置 | ✅ |
showsUserLocation |
boolean | ❌ | 显示用户位置 | ✅ |
showsCompass |
boolean | ❌ | 显示指南针 | ✅ |
showsScale |
boolean | ❌ | 显示比例尺 | ✅ |
zoomEnabled |
boolean | ❌ | 启用缩放 | ✅ |
scrollEnabled |
boolean | ❌ | 启用滚动 | ✅ |
rotateEnabled |
boolean | ❌ | 启用旋转 | ✅ |
mapType |
string | ❌ | 地图类型 | ✅ |
Region 类型
typescript
interface Region {
latitude: number; // 纬度
longitude: number; // 经度
latitudeDelta: number; // 纬度跨度
longitudeDelta: number; // 经度跨度
}
事件回调
| 事件 | 说明 | HarmonyOS 支持 |
|---|---|---|
onRegionChange |
区域变化时触发 | ✅ |
onRegionChangeComplete |
区域变化完成时触发 | ✅ |
onPress |
点击地图时触发 | ✅ |
onLongPress |
长按地图时触发 | ✅ |
onMarkerPress |
点击标记时触发 | ✅ |
🔷 Marker - 标记点
Marker 用于在地图上标注位置。
typescript
import MapView, { Marker } from 'react-native-maps';
<MapView style={{ flex: 1 }}>
<Marker
coordinate={{
latitude: 39.9042,
longitude: 116.4074,
}}
title="北京"
description="中国首都"
/>
</MapView>
主要属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
coordinate |
LatLng | ✅ | 标记坐标 | ✅ |
title |
string | ❌ | 标题 | ✅ |
description |
string | ❌ | 描述 | ✅ |
image |
ImageSource | ❌ | 自定义图标 | ✅ |
opacity |
number | ❌ | 透明度 | ✅ |
draggable |
boolean | ❌ | 可拖拽 | ✅ |
anchor |
Point | ❌ | 锚点 | ✅ |
自定义标记图标
typescript
<Marker
coordinate={{ latitude: 39.9042, longitude: 116.4074 }}
image={require('./assets/marker.png')}
/>
🔷 Circle - 圆形覆盖物
Circle 用于在地图上绘制圆形区域。
typescript
import MapView, { Circle } from 'react-native-maps';
<MapView style={{ flex: 1 }}>
<Circle
center={{
latitude: 39.9042,
longitude: 116.4074,
}}
radius={1000}
fillColor="rgba(255, 0, 0, 0.3)"
strokeColor="rgba(255, 0, 0, 1)"
strokeWidth={2}
/>
</MapView>
主要属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
center |
LatLng | ✅ | 圆心坐标 | ✅ |
radius |
number | ✅ | 半径(米) | ✅ |
fillColor |
string | ❌ | 填充颜色 | ✅ |
strokeColor |
string | ❌ | 边框颜色 | ✅ |
strokeWidth |
number | ❌ | 边框宽度 | ✅ |
🔷 Polygon - 多边形覆盖物
Polygon 用于在地图上绘制多边形区域。
typescript
import MapView, { Polygon } from 'react-native-maps';
<MapView style={{ flex: 1 }}>
<Polygon
coordinates={[
{ latitude: 39.91, longitude: 116.40 },
{ latitude: 39.90, longitude: 116.41 },
{ latitude: 39.89, longitude: 116.40 },
{ latitude: 39.90, longitude: 116.39 },
]}
fillColor="rgba(0, 200, 0, 0.5)"
strokeColor="rgba(0, 200, 0, 1)"
strokeWidth={2}
/>
</MapView>
主要属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
coordinates |
LatLng[] | ✅ | 顶点坐标数组 | ✅ |
fillColor |
string | ❌ | 填充颜色 | ✅ |
strokeColor |
string | ❌ | 边框颜色 | ✅ |
strokeWidth |
number | ❌ | 边框宽度 | ✅ |
holes |
LatLng[][] | ❌ | 空洞区域 | ✅ |
🔷 Polyline - 折线覆盖物
Polyline 用于在地图上绘制路线或路径。
typescript
import MapView, { Polyline } from 'react-native-maps';
<MapView style={{ flex: 1 }}>
<Polyline
coordinates={[
{ latitude: 39.91, longitude: 116.40 },
{ latitude: 39.90, longitude: 116.41 },
{ latitude: 39.89, longitude: 116.42 },
]}
strokeColor="#FF0000"
strokeWidth={3}
lineDashPattern={[5, 2, 3, 2]}
/>
</MapView>
主要属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
coordinates |
LatLng[] | ✅ | 端点坐标数组 | ✅ |
strokeColor |
string | ❌ | 线条颜色 | ✅ |
strokeWidth |
number | ❌ | 线条宽度 | ✅ |
lineDashPattern |
number[] | ❌ | 虚线模式 | ✅ |
geodesic |
boolean | ❌ | 测地线 | ✅ |
📱 完整示例

typescript
import React, { useState, useRef } from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
Alert,
} from 'react-native';
import MapView, {
Marker,
PROVIDER_DEFAULT,
} from '@react-native-ohos/react-native-maps';
const LATITUDE_DELTA = 0.01;
const LONGITUDE_DELTA = 0.01;
const DEFAULT_LOCATION = {
latitude: 39.9042,
longitude: 116.4074,
};
interface Coordinate {
latitude: number;
longitude: number;
}
const MapDemo = () => {
const mapRef = useRef<MapView>(null);
const [region, setRegion] = useState<Coordinate>(DEFAULT_LOCATION);
const [markers, setMarkers] = useState<Coordinate[]>([]);
const handleMapPress = (e: any) => {
const coordinate = e.nativeEvent?.coordinate;
if (coordinate) {
setMarkers([...markers, coordinate]);
}
};
const handleMarkerPress = (index: number) => {
const marker = markers[index];
if (marker) {
Alert.alert(
'标记点',
`位置 ${index + 1}\n纬度: ${marker.latitude.toFixed(4)}\n经度: ${marker.longitude.toFixed(4)}`
);
}
};
const handleRegionChangeComplete = (newRegion: any) => {
if (newRegion && typeof newRegion.latitude === 'number' && typeof newRegion.longitude === 'number') {
setRegion({
latitude: newRegion.latitude,
longitude: newRegion.longitude,
});
}
};
const clearMarkers = () => {
setMarkers([]);
};
return (
<View style={styles.container}>
<MapView
ref={mapRef}
style={styles.map}
provider={PROVIDER_DEFAULT}
initialRegion={{
...DEFAULT_LOCATION,
latitudeDelta: 0.1,
longitudeDelta: 0.1,
}}
onRegionChangeComplete={handleRegionChangeComplete}
onPress={handleMapPress}
showsUserLocation
showsCompass
showsScale
showsMyLocationButton
zoomEnabled
scrollEnabled
rotateEnabled
>
{markers.map((marker, index) => (
<Marker
key={index}
coordinate={marker}
title={`标记 ${index + 1}`}
description="点击查看详情"
onPress={() => handleMarkerPress(index)}
/>
))}
</MapView>
<View style={styles.topPanel}>
<View style={styles.infoBox}>
<Text style={styles.infoText}>点击地图添加标记点</Text>
<Text style={styles.infoText}>当前标记数: {markers.length}</Text>
</View>
<TouchableOpacity style={styles.clearButton} onPress={clearMarkers}>
<Text style={styles.clearButtonText}>清除标记</Text>
</TouchableOpacity>
</View>
<View style={styles.coordinateBox}>
<Text style={styles.coordinateText}>
纬度: {region?.latitude?.toFixed(4) ?? 'N/A'}
</Text>
<Text style={styles.coordinateText}>
经度: {region?.longitude?.toFixed(4) ?? 'N/A'}
</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
map: {
flex: 1,
},
topPanel: {
position: 'absolute',
top: 20,
left: 20,
right: 20,
backgroundColor: 'rgba(255, 255, 255, 0.95)',
borderRadius: 12,
padding: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
infoBox: {
marginBottom: 8,
},
infoText: {
fontSize: 14,
color: '#333',
marginBottom: 2,
},
clearButton: {
backgroundColor: '#2196F3',
paddingVertical: 10,
borderRadius: 8,
alignItems: 'center',
},
clearButtonText: {
color: '#fff',
fontSize: 14,
fontWeight: '600',
},
coordinateBox: {
position: 'absolute',
bottom: 120,
left: 20,
backgroundColor: 'rgba(0, 0, 0, 0.7)',
borderRadius: 8,
padding: 12,
},
coordinateText: {
color: '#fff',
fontSize: 12,
fontFamily: 'monospace',
},
});
export default MapDemo;
❓ 常见问题
1. 地图无法显示(白屏)
问题:运行应用后地图显示为空白。
解决方案:
- ✅ 确认已在 AppGallery Connect 开通地图服务
- ✅ 确认 Client ID 配置正确(仅旧版本需要)
- ✅ 确认应用包名与 AGC 中一致
- ✅ 确认签名配置正确(使用开通地图服务后重新申请的 Profile)
- ✅ 确认网络连接正常
2. 地图显示"鉴权失败"
问题:地图显示鉴权失败错误。
解决方案:
- 检查 Client ID 是否正确配置在
module.json5中(仅旧版本需要) - 确认签名证书指纹已在 AGC 中配置(仅旧版本需要)
- 确认 Profile 文件是在开通地图服务后重新申请的
3. 定位权限申请失败
问题:申请定位权限时失败。
解决方案:
- 确认
module.json5中已声明LOCATION和APPROXIMATELY_LOCATION权限 - 确认
string.json中已添加权限说明 - 检查设备是否开启了定位服务
4. 标记点不显示
问题:添加的 Marker 不显示。
解决方案:
- 检查坐标是否在可视区域内
- 检查 Marker 的
coordinate属性是否正确 - 确认 MapView 组件已正确渲染
📚 参考资料
✅ 总结
react-native-maps 是一个功能强大的地图组件库,在 HarmonyOS 平台上需要配合华为地图服务(Map Kit)使用。
版本选择建议
| 您的环境 | 推荐方案 |
|---|---|
| HarmonyOS 5.0.2+ 且 DevEco Studio 6.0.0+ | ✅ 方案一:自动配置,简单快捷 |
| 其他版本 | ⚠️ 方案二:手动配置,流程较多 |
关键步骤总结
方案一(新版本):
- DevEco Studio 自动签名
- Enable open capabilities → 勾选 Map Kit
- 完成!
方案二(旧版本):
- AppGallery Connect 创建项目和应用
- 开通地图服务
- 生成签名证书
- 申请调试证书和 Profile
- 获取并配置 Client ID
- 配置签名信息
关键提醒:使用地图功能前,务必先开通地图服务!