HarmonyOS - 鸿蒙开发百度地图案例
开发环境为:
开发工具:DevEco Studio 5.0.5 Release
API版本是:API17
本文所有代码都已使用模拟器测试成功!
1. 准备工作
我们在纯血鸿蒙系统中,如果需要调用百度SDK做一些功能的话,我们需要先做如下准备工作:
- 百度地图开放平台中,创建应用后,获取AK,没有这个AK,APP是无法使用百度地图的
- 一部纯血鸿蒙系统手机,5.0以上系统(模拟器无法调试,只能真机测试)
- 必须到AppGallery上申请证书等相关文件(.cer、.p12、.p7b文件,签名需要用到)
- DevEco Studio开发工具(SDK需要5.0以上)
以上信息准备好之后,开始进入【百度地图开放平台】官网看API进行开发,官网地址:
https://lbsyun.baidu.com/faq/api?title=harmonynextsdk/guide/create-project/engineering
参照官网一步一步配置即可
2. 实战案例编码
1. 添加SDK依赖
在【oh-package.json5】文件中添加如下依赖:
json
"@bdmap/base": "1.2.6",
"@bdmap/search": "1.2.6",
"@bdmap/map": "1.2.6",
"@bdmap/locsdk": "1.1.4"
如下图所示:

2. 初始化
在绘制地图前初始化SDK,我这里是在【EntryAbility.ets】文件中进行初始化的,如下图所示:

图中的MAP_KEY就是百度开发平台中创建的应用的AK,上图中新增代码如下:
js
//检查百度地图秘钥的合法性
LocationClient.checkAuthKey(MAP_KEY, (result: string) => {
Logger.debug("百度地图秘钥合法性检测 result = " + result);
});
//初始化秘钥
Initializer.getInstance().initialize(MAP_KEY)
LocationClient.setAgreePrivacy(true) // 设置是否同意隐私政策
3. 案例实战
1. 地图打点
需求说明:
每隔1秒就在地图上标识出一个点,点的数据存在JSON文件中
效果如下所示:
地图打点演示视频
页面代码如下:
js
interface JsonData {
miaoshu: string;
location: string;
}
/**
* 地图打点
*/
@Entry
@Component
struct MapSetMarker {
// 定位位置(维度,经度)
startLoc = new LatLng(0, 0)
// 控制器
mapController: MapController | null = null;
// 设置地图控件参数
@State mapOpt: MapOptions = new MapOptions({
// 默认基础地图,可通过改变satelliteMap的值加载不同的底图
shows: { satelliteMap: SysEnum.ESatelliteLayerType.NONE },
gestures: {
zoom: true,
move: true,
rotate: true,
overlooking: true,
}
});
@State dataArray: Array<RadiationData> = []
marker: Marker | null = null;
//读取JSON文件经纬度数据
readJsonData() {
//开始读取工程目录 rawfile 中的JSON文件
try {
let context = getContext() as common.UIAbilityContext;
let rawFile = context.resourceManager.getRawFileContentSync("jingdian.json");
let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true });
let jsonResult: string = textDecoder.decodeToString(rawFile, { stream: false })
// Logger.debug('jsonContent=' + jsonResult)
this.dataArray = this.parseRadiationData(jsonResult);
} catch (error) {
let code = (error as BusinessError).code;
let message = (error as BusinessError).message;
Logger.error(`getRawFileContentSync failed, error code: ${code}, message: ${message}.`);
}
}
parseRadiationData(jsonString: string): RadiationData[] {
try {
const rawData: Array<JsonData> = JSON.parse(jsonString);
let dataArray: Array<RadiationData> = []
rawData.map((item: JsonData) => {
// 提取剂量率数值(去掉单位)
const miaoshu = item.miaoshu.trim();
// 解析经纬度
const locationParts = item.location.split(' ');
if (locationParts.length !== 2) {
throw new Error('Invalid location format');
}
// 提取纬度(去掉°N)
const lat = locationParts[0].replace('°N', '').trim();
// 提取经度(去掉°E)
const lng = locationParts[1].replace('°E', '').trim();
dataArray.push({
miaoshu: miaoshu,
lat: Number(lat),
lng: Number(lng)
});
});
return dataArray;
} catch (error) {
myTools.alertMsg('JSON数据解析失败:' + JSON.stringify(error))
console.error('数据解析失败:', error);
return [];
}
}
/**
* 在地图上添加Marker,并显示
* @param lat 维度
* @param lng 经度
*/
addMarker(lat: number, lng: number) {
Logger.debug('设置标注点----------开始')
let marker = new Marker({
position: new LatLng(lat, lng),
icon: new ImageEntity('rawfile://user_loc_icon.png')
});
//在地图上添加Marker,并显示
this.mapController?.addOverlay(marker);
Logger.debug('设置标注点----------结束')
}
// 创建定时器实例
private arrayTimer: ArrayTimerModel | null = null;
aboutToAppear(): void {
this.readJsonData();
Logger.debug('this.dataArray=' + JSON.stringify(this.dataArray))
this.arrayTimer = new ArrayTimerModel(this.dataArray);
// 设置回调函数
this.arrayTimer.setCallback((item: RadiationData, index: number) => {
Logger.debug('获取到第' + (index + 1) + '个元素=' + JSON.stringify(item));
this.addMarker(item.lat, item.lng);
});
this.arrayTimer.start(1000); // 每秒获取一个元素
}
// 页面销毁时清理资源
aboutToDisappear() {
this.arrayTimer?.destroy();
}
build() {
Column() {
MapComponent({
onReady: (err, mapController: MapController) => {
if (!err) {
this.mapController = mapController;
}
}, mapOptions: this.mapOpt
})
.height('100%')
.width('100%')
}
.height('100%')
.width('100%')
}
}
ArrayTimerModel代码如下:
js
export interface RadiationData {
miaoshu: string;
lat: number; //纬度
lng: number; //经度
}
export class ArrayTimerModel {
private dataArray: RadiationData[] = [];
private currentIndex: number = 0;
private timerId: number = -1;
private onItemCallback: (item: RadiationData, index: number) => void = () => {};
// 初始化数据
constructor(data: RadiationData[]) {
this.dataArray = data;
}
// 设置回调函数,每次获取元素时调用
setCallback(callback: (item: RadiationData, index: number) => void): void {
this.onItemCallback = callback;
}
// 开始定时获取元素
start(interval: number = 1000): void {
if (this.timerId !== -1) {
console.log('定时器已经在运行中');
return;
}
console.log('开始定时获取数组元素');
this.timerId = setInterval(() => {
this.getNextItem();
}, interval);
}
// 获取下一个元素
private getNextItem(): void {
if (this.dataArray.length === 0) {
console.log('数组为空');
this.stop();
return;
}
// 如果当前索引超出数组长度,则重置或停止
if (this.currentIndex >= this.dataArray.length) {
console.log('已遍历完所有元素');
this.stop();
return;
}
const item = this.dataArray[this.currentIndex];
// 执行回调
this.onItemCallback(item, this.currentIndex);
// 增加索引
this.currentIndex++;
}
// 停止定时器
stop(): void {
if (this.timerId !== -1) {
clearInterval(this.timerId);
this.timerId = -1;
console.log('定时器已停止');
}
}
// 重置定时器(从头开始)
reset(): void {
this.stop();
this.currentIndex = 0;
console.log('定时器已重置');
}
// 手动获取当前索引的元素
getCurrentItem(): RadiationData | null {
if (this.currentIndex < this.dataArray.length) {
return this.dataArray[this.currentIndex];
}
return null;
}
// 设置新的数据数组
setData(newData: RadiationData[]): void {
this.dataArray = newData;
this.currentIndex = 0;
}
// 清理资源
destroy(): void {
this.stop();
this.dataArray = [];
this.currentIndex = 0;
}
}
JSON文件放在【rawfile】目录,内容如下:
js
[
{
"miaoshu": "北京故宫",
"location": "39.916345°N 116.397155°E"
},
{
"miaoshu": "上海东方明珠广播电视塔",
"location": "31.239679°N 121.499758°E"
},
{
"miaoshu": "天津之眼摩天轮",
"location": "39.153385°N 117.182306°E"
},
{
"miaoshu": "重庆洪崖洞",
"location": "29.563010°N 106.577500°E"
},
{
"miaoshu": "吉林长白山风景区",
"location": "42.012143°N 128.062466°E"
},
{
"miaoshu": "辽宁本溪水洞",
"location": "41.296446°N 124.087891°E"
},
{
"miaoshu": "甘肃敦煌莫高窟",
"location": "40.041206°N 94.807923°E"
},
{
"miaoshu": "青海青海湖",
"location": "36.623236°N 100.215808°E"
},
{
"miaoshu": "陕西华山",
"location": "34.483727°N 110.074478°E"
},
{
"miaoshu": "河南嵩山少林寺",
"location": "34.508522°N 112.940175°E"
},
{
"miaoshu": "河北承德避暑山庄",
"location": "41.005442°N 117.935190°E"
},
{
"miaoshu": "山东泰山",
"location": "36.256944°N 117.103611°E"
},
{
"miaoshu": "山西五台山",
"location": "39.030771°N 113.590706°E"
},
{
"miaoshu": "安徽黄山",
"location": "30.132855°N 118.168859°E"
},
{
"miaoshu": "湖北武汉黄鹤楼",
"location": "30.546545°N 114.298454°E"
},
{
"miaoshu": "湖南湘西凤凰古城",
"location": "27.948230°N 109.593903°E"
},
{
"miaoshu": "四川阿坝九寨沟",
"location": "33.260108°N 103.920197°E"
},
{
"miaoshu": "云南大理古城",
"location": "25.692711°N 100.156265°E"
},
{
"miaoshu": "广西桂林漓江",
"location": "25.234479°N 110.179953°E"
}
]
在真机上运行页面就可以出现演示视频的效果了
2. 路线规划
支持路线规划:步行和骑行
导入依赖有变化,依赖换成如下即可:
js
"@bdmap/base": "2.0.3",
"@bdmap/map": "2.0.3",
"@bdmap/verify": "1.0.4",
"@bdmap/map_walkride_search": "2.0.3"
EntryAbility.ets文件中只需要在【onCreate】函数中添加下面代码即可:
js
import { Initializer } from "@bdmap/map_walkride_search";
//初始化秘钥
Initializer.getInstance().initialize(MAP_KEY, this.context)
页面代码如下:
js
import {
MapComponent,
MapOptions,
BDNaviService,
NaviType,
RoutePlanOption,
RouteNodeInfo,
LatLng,
walkRideDefaultUIPage,
NaviMode,
MapController,
IRoutePlanListener,
RoutePlanError
} from "@bdmap/map_walkride_search";
/**
* 步行路线规划-案例
*/
@Entry
@ComponentV2
struct DriveCar {
// 控制器
mapController: MapController | null = null;
// 设置地图控件参数
@Local mapOpt: MapOptions = new MapOptions({
gestures: {
zoom: true,
move: true,
rotate: true,
overlooking: true,
}
});
//路线规划
init2() {
// 初始化导航服务
const service = new BDNaviService(NaviType.RIDE);// 这里可以指定是步行还是骑行
service.initializer().init(getContext(this), this.mapController)
// 配置路线规划参数
let param = new RoutePlanOption();
let startLocation = new RouteNodeInfo();
let endLocation = new RouteNodeInfo();
// 设置起终点
startLocation.location = new LatLng(30.624530, 114.261376) //汉口火车站
endLocation.location = new LatLng(30.537494, 114.323302) //武昌火车站
param.startNodeInfo(startLocation)
.endNodeInfo(endLocation)
.extraNaviMode(NaviMode.RealNavi);
// 路线规划
service.routePlanService().routePlanWithRouteNode(param, new Object({
//引擎开始路线规划
onRoutePlanStart: () => {
},
// 正常规划成功
onRoutePlanSuccess: () => {
// 展示路线
service.routePlanService().displayRoutePlanResult()
},
// 正常规划失败
onRoutePlanFail: (error: RoutePlanError) => {
console.log('正常规划失败,error=' + JSON.stringify(error))
}
}) as IRoutePlanListener);
// 开始导航
service.navigationService().lifecycle().start();
}
aboutToAppear(): void {
setTimeout(() => {
this.init2();
}, 3000)
}
build() {
Column() {
MapComponent({
onReady: (err, mapController: MapController) => {
if (!err) {
this.mapController = mapController;
}
}, mapOptions: this.mapOpt
})
.height('100%')
.width('100%')
}
.height('100%')
.width('100%')
}
}
演示效果如下:
路线规划演示视频
效果是:进入页面3秒后,自动规划起点到终点的路线(代码中可以设置步行或者骑行)
最后
- 希望本文对你有所帮助!
- 本人如有任何错误或不当之处,请留言指出,谢谢!