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

前言

在开发运动类应用时,集成地图功能以及实时记录运动轨迹和公里数是核心需求之一。本文将详细介绍如何在 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 开发中取得更好的成果!

发表评论

评论已关闭。

相关文章