写点什么

HarmonyOS 运动开发:如何集成百度地图 SDK、运动跟随与运动公里数记录

  • 2025-05-07
    北京
  • 本文字数:5916 字

    阅读完需:约 19 分钟

前言


在开发运动类应用时,集成地图功能以及实时记录运动轨迹和公里数是核心需求之一。本文将详细介绍如何在 HarmonyOS 应用中集成百度地图 SDK,实现运动跟随以及运动公里数的记录。


一、集成百度地图 SDK


1.引入依赖


首先,需要在项目的文件中引入百度地图相关的依赖包:


"dependencies": {  "@bdmap/base": "1.2.6",  "@bdmap/search": "1.2.6",  "@bdmap/map": "1.2.6",  "@bdmap/locsdk": "1.1.4"}
复制代码


2.初始化百度地图


为了使用百度地图的功能,我们需要进行初始化操作。这包括设置 API Key 和初始化定位客户端。


MapUtil 类



export class MapUtil{
public static initialize(context:Context){ Initializer.getInstance().initialize("你的key"); // 设置是否同意隐私合规政策接口 // true,表示同意隐私合规政策 // false,表示不同意隐私合规政策 LocationClient.checkAuthKey("你的key", (result: string) => { console.debug("result = " + result); // 可打印出是否鉴权成功的结果 }); LocationClient.setAgreePrivacy(true); LocManager.getInstance().init(context); }
}
复制代码


LocManager 类



export class LocManager { private client: LocationClient | null = null;
private static instance: LocManager;
public static getInstance(): LocManager { if (!LocManager.instance) { LocManager.instance = new LocManager(); } return LocManager.instance; }
constructor() {
}
init(context: Context) { if (this.client == null) { try { this.client = new LocationClient(context); } catch (error) { console.error("harmony_baidu_location error: " + error.message); } } if (this.client != null) { this.client.setLocOption(this.getDefaultLocationOption()); } }
start() { if (this.client != null) { this.client.start(); } }
stop() { if (this.client != null) { this.client.stop(); } }
requestSingleLocation() { if (this.client != null) { this.client.requestSingleLocation(); } }
registerListener(listener: BDLocationListener): boolean { let isSuccess: boolean = false; if (this.client != null && listener != null) { this.client.registerLocationListener(listener); isSuccess = true; } return isSuccess; }
unRegisterListener(listener: BDLocationListener) { if (this.client != null && listener != null) { this.client.unRegisterLocationListener(listener); } }
getSDKVersion(): string { let version: string = ""; if (this.client != null) { version = this.client.getVersion(); } return version; }
enableLocInBackground(wantAgent: WantAgent) { if (this.client != null) { this.client.enableLocInBackground(wantAgent); } }
disableLocInBackground() { if (this.client != null) { this.client.disableLocInBackground(); } }
getDefaultLocationOption() { let option = new LocationClientOption(); option.setCoorType("bd09ll"); // 可选,默认为gcj02,设置返回的定位结果坐标系 option.setTimeInterval(3); // 可选,默认1秒,设置连续定位请求的时间间隔 option.setDistanceInterval(0); // 可选,默认0米,设置连续定位的距离间隔 option.setIsNeedAddress(true); // 可选,设置是否需要地址信息,默认不需要 option.setIsNeedLocationDescribe(true); // 可选,默认为false,设置是否需要地址描述 option.setIsNeedLocationPoiList(true); // 可选,默认能为false,设置是否需要POI结果 option.setLocationMode(LocationMode.High_Accuracy); // 可选,默认高精度,设置定位模式,高精度、低功耗、仅设备 option.setSingleLocatingTimeout(3000); // 可选,仅针对单次定位生效,设置单次定位的超时时间
return option; }
}
复制代码


3.定位监听器


为了处理定位数据,我们需要实现一个定位监听器:



export class MapLocationListener extends BDLocationListener { private callback: (location: BDLocation) => void;
constructor(callback: (location: BDLocation) => void) { super(); this.callback = callback; }
onReceiveLocation(bdLocation: BDLocation): void { this.callback(bdLocation); }}
复制代码


二、页面使用


1.权限申请


在文件中声明所需的权限:


"requestPermissions": [      {        "name": "ohos.permission.LOCATION",        "reason": "$string:location_permission",        "usedScene": {          "abilities": [            "EntryAbility"          ],          "when": "inuse"        }      },      {        "name": "ohos.permission.LOCATION_IN_BACKGROUND",        "reason": "$string:background_location_permission",        "usedScene": {          "abilities": [            "EntryAbility"          ],          "when": "inuse"        }      },      {        "name": "ohos.permission.APPROXIMATELY_LOCATION",        "reason": "$string:fuzzy_location_permission",        "usedScene": {          "abilities": [            "EntryAbility"          ],          "when": "inuse"        }      },      {        "name": "ohos.permission.APP_TRACKING_CONSENT",        "reason": "$string:get_oaid_permission",        "usedScene": {          "abilities": [            "EntryAbility"          ],          "when": "inuse"        }      },      {        "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",        "reason": "$string:keep_background_running_permission",        "usedScene": {          "abilities": [            "EntryAbility1"          ],          "when": "inuse"        }      }    ]
复制代码


2.请求权限


在页面中请求权限:


private async requestPermissions(): Promise<boolean> {    const permissions : Permissions[]= [      'ohos.permission.LOCATION',      'ohos.permission.APPROXIMATELY_LOCATION',      'ohos.permission.APP_TRACKING_CONSENT',    ]    return LibPermission.requestPermissions(permissions)  }
复制代码


3.页面调用


方向感应


使用鸿蒙系统自带的方向传感器来获取设备的朝向角度:


// 初始化方向传感器      sensor.on(sensor.SensorId.ORIENTATION, (data) => {        // 获取设备朝向角度(绕Z轴旋转角度)        this.currentRotation = data.alpha;        if(this.loc){          this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude);          this.loc.direction = this.currentRotation;          this.loc.radius = 0;        }      });
// 用完记得取消监听sensor.off(sensor.SensorId.ORIENTATION);
复制代码


编写定位监听器


private mListener: MapLocationListener = new MapLocationListener((bdLocation: BDLocation) => {    this.currentLatitude = bdLocation.getLatitude();    this.currentLongitude = bdLocation.getLongitude();    this.currentRadius = bdLocation.getRadius();
// 更新地图位置和位置标记 if (this.mapController) { // 更新地图中心点 this.mapController.setMapCenter({ lat: this.currentLatitude, lng: this.currentLongitude },15);
if(this.loc){ // 设置定位图标位置、指向以及范围 this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude); this.loc.direction = this.currentRotation; // 单位米 this.loc.radius = 0;
}
} });
复制代码


启动和关闭定位


// 启动定位LocManager.getInstance().registerListener(this.mListener);LocManager.getInstance().start();
// 关闭定位LocManager.getInstance().unRegisterListener(this.mListener);LocManager.getInstance().stop();
复制代码


百度地图集成


在页面中集成百度地图:


MapComponent({ onReady: async (err, mapController:MapController) => {          if (!err) {            // 获取地图的控制器类,用来操作地图            this.mapController= mapController;            let result = this.mapController.getLayerByTag(SysEnum.LayerTag.LOCATION);            if(result){              this.loc = result as LocationLayer;            }
if(this.currentLatitude!=0&&this.currentLongitude!=0){ if(this.loc){ // 设置定位图标位置、指向以及范围 this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude); this.loc.direction = this.currentRotation; // 单位米 this.loc.radius = 0; }
this.mapController.setMapCenter({ lat: this.currentLatitude, lng: this.currentLongitude },15);
} } }, mapOptions: this.mapOpt }).width('100%').height('100%')
复制代码


三、公里数计算


在运动应用中,记录用户的运动轨迹并计算运动的总距离是核心功能之一。为了实现这一功能,我们需要设计一个数据模型来记录运动轨迹点,并通过这些点计算总距离。


1.运动轨迹点模型


定义一个RunPoint类来表示运动轨迹中的一个点,包含纬度、经度和时间戳:


/** * 运动轨迹点数据模型 */export class RunPoint {  // 纬度  latitude: number;  // 经度  longitude: number;  // 时间戳  timestamp: number;  // 所属公里数分组(第几公里)  kilometerGroup: number;
constructor(latitude: number, longitude: number) { this.latitude = latitude; this.longitude = longitude; this.timestamp = Date.now(); this.kilometerGroup = 0; // 默认分组为0 }}
复制代码


2.运动轨迹管理类


创建一个RunTracker类来管理运动轨迹点,并计算总距离:



/** * 运动轨迹管理类 */export class RunTracker { // 所有轨迹点 private points: RunPoint[] = []; // 当前总距离(公里) private totalDistance: number = 0; // 当前公里数分组 private currentKilometerGroup: number = 0;
/** * 添加新的轨迹点 * @param latitude 纬度 * @param longitude 经度 * @returns 当前总距离(公里) */ addPoint(latitude: number, longitude: number): number { const point = new RunPoint(latitude, longitude);
if (this.points.length > 0) { // 计算与上一个点的距离 const lastPoint = this.points[this.points.length - 1]; const distance = this.calculateDistance(lastPoint, point); this.totalDistance += distance;
// 更新公里数分组 point.kilometerGroup = Math.floor(this.totalDistance); if (point.kilometerGroup > this.currentKilometerGroup) { this.currentKilometerGroup = point.kilometerGroup; } }
this.points.push(point); return this.totalDistance; }
/** * 计算两点之间的距离(公里) * 使用Haversine公式计算球面距离 */ private calculateDistance(point1: RunPoint, point2: RunPoint): number { const R = 6371; // 地球半径(公里) const lat1 = this.toRadians(point1.latitude); const lat2 = this.toRadians(point2.latitude); const deltaLat = this.toRadians(point2.latitude - point1.latitude); const deltaLon = this.toRadians(point2.longitude - point1.longitude);
const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; }
/** * 将角度转换为弧度 */ private toRadians(degrees: number): number { return degrees * (Math.PI / 180); }
/** * 获取当前总距离 */ getTotalDistance(): number { return this.totalDistance; }
/** * 获取指定公里数分组的轨迹点 */ getPointsByKilometer(kilometer: number): RunPoint[] { return this.points.filter(point => point.kilometerGroup === kilometer); }
/** * 清空轨迹数据 */ clear(): void { this.points = []; this.totalDistance = 0; this.currentKilometerGroup = 0; }}
复制代码


3.页面的监听器里记录公里数


在页面中使用RunTracker类来记录运动轨迹点并计算总距离:


  private runTracker: RunTracker = new RunTracker();监听器添加代码      const distance = this.runTracker.addPoint(this.currentLatitude, this.currentLongitude);
distance就是当前运动的公里数
复制代码


四、总结


本文详细介绍了如何在 HarmonyOS 应用中集成百度地图 SDK,实现运动跟随以及运动公里数的记录。通过以下步骤,我们可以实现一个功能完整的运动应用:


• 集成百度地图 SDK:


• 引入必要的依赖包。


• 初始化百度地图并设置定位选项。


• 页面使用:


• 请求必要的权限。


• 启动和关闭定位。


• 实时更新地图位置和方向。


• 公里数计算:


• 定义运动轨迹点模型。


• 使用 Haversine 公式计算两点之间的距离。


• 记录运动轨迹点并实时更新总距离。


通过这些步骤,开发者可以轻松实现一个功能强大的运动应用,为用户提供实时的运动数据和地图跟随功能。希望本文的内容能够帮助你在 HarmonyOS 开发中取得更好的成果!

发布于: 刚刚阅读数: 5
用户头像

还未添加个人签名 2021-11-19 加入

还未添加个人简介

评论

发布
暂无评论
HarmonyOS运动开发:如何集成百度地图SDK、运动跟随与运动公里数记录_鸿蒙_王二蛋和他的张大花_InfoQ写作社区