HarmonyOS Sports Development: How to Integrate Baidu Map SDK, Sports Tracking, and Distance Recording
Foreword
When developing sports applications, integrating map functionality and real-time recording of sports trajectories and distances is one of the core requirements. This article will detail how to integrate the Baidu Map SDK in a HarmonyOS application to achieve sports tracking and distance recording.
I. Integrating Baidu Map SDK
- Adding Dependencies
First, you need to add the Baidu Map related dependency packages to your project file:
"dependencies": {
"@bdmap/base": "1.2.6",
"@bdmap/search": "1.2.6",
"@bdmap/map": "1.2.6",
"@bdmap/locsdk": "1.1.4"
}
- Initializing Baidu Map
To use Baidu Map's functionality, we need to perform initialization operations. This includes setting the API Key and initializing the location client.
MapUtil Class
export class MapUtil {
public static initialize(context: Context) {
Initializer.getInstance().initialize("your_key");
// Set whether to agree to the privacy compliance policy interface
// true, indicates agreement with the privacy compliance policy
// false, indicates disagreement with the privacy compliance policy
LocationClient.checkAuthKey("your_key", (result: string) => {
console.debug("result = " + result); // Can print out the result of whether authorization is successful
});
LocationClient.setAgreePrivacy(true);
LocManager.getInstance().init(context);
}
}
LocManager Class
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"); // Optional, default is gcj02, set the coordinate system of the returned location result
option.setTimeInterval(3); // Optional, default is 1 second, set the time interval for continuous location requests
option.setDistanceInterval(0); // Optional, default is 0 meters, set the distance interval for continuous location
option.setIsNeedAddress(true); // Optional, set whether address information is needed, default is no
option.setIsNeedLocationDescribe(true); // Optional, default is false, set whether address description is needed
option.setIsNeedLocationPoiList(true); // Optional, default is false, set whether POI results are needed
option.setLocationMode(LocationMode.High_Accuracy); // Optional, default is high accuracy, set the location mode, high accuracy, low power consumption, only device
option.setSingleLocatingTimeout(3000); // Optional, only effective for single location, set the timeout for single location
return option;
}
}
- Location Listener
To handle location data, we need to implement a location listener:
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);
}
}
II. Page Usage
- Requesting Permissions
Declare the required permissions in the file:
"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"
}
}
]
- Requesting Permissions
Request permissions in the page:
private async requestPermissions(): Promise<boolean> {
const permissions: Permissions[] = [
'ohos.permission.LOCATION',
'ohos.permission.APPROXIMATELY_LOCATION',
'ohos.permission.APP_TRACKING_CONSENT',
];
return LibPermission.requestPermissions(permissions);
}
- Page Invocation
Direction Sensing
Use the built-in direction sensor of the HarmonyOS system to obtain the device's orientation angle:
// Initialize the orientation sensor
sensor.on(sensor.SensorId.ORIENTATION, (data) => {
// Get the device's orientation angle (rotation around the Z-axis)
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;
}
});
// Remember to cancel the listener after use
sensor.off(sensor.SensorId.ORIENTATION);
Writing the Location Listener
private mListener: MapLocationListener = new MapLocationListener((bdLocation: BDLocation) => {
this.currentLatitude = bdLocation.getLatitude();
this.currentLongitude = bdLocation.getLongitude();
this.currentRadius = bdLocation.getRadius();
// Update map location and location marker
if (this.mapController) {
// Update map center
this.mapController.setMapCenter({
lat: this.currentLatitude,
lng: this.currentLongitude
}, 15);
if (this.loc) {
// Set the location icon's position, direction, and range
this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude);
this.loc.direction = this.currentRotation;
// Unit: meters
this.loc.radius = 0;
}
}
});
Starting and Stopping Location
// Start location
LocManager.getInstance().registerListener(this.mListener);
LocManager.getInstance().start();
// Stop location
LocManager.getInstance().unRegisterListener(this.mListener);
LocManager.getInstance().stop();
Baidu Map Integration
Integrate Baidu Map in the page:
MapComponent({
onReady: async (err, mapController: MapController) => {
if (!err) {
// Get the map controller class to operate the map
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) {
// Set the location icon's position, direction, and range
this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude);
this.loc.direction = this.currentRotation;
// Unit: meters
this.loc.radius = 0;
}
this.mapController.setMapCenter({
lat: this.currentLatitude,
lng: this.currentLongitude
}, 15);
}
}
},
mapOptions: this.mapOpt
}).width('100%').height('100%');
III. Distance Calculation
In sports applications, recording the user's sports trajectory and calculating the total distance traveled is one of the core functions. To achieve this functionality, we need to design a data model to record the sports trajectory points and calculate the total distance through these points.
- Sports Trajectory Point Model
Define a RunPoint
class to represent a point in the sports trajectory, including latitude, longitude, and timestamp:
/**
* Sports trajectory point data model
*/
export class RunPoint {
// Latitude
latitude: number;
// Longitude
longitude: number;
// Timestamp
timestamp: number;
// Kilometer group (which kilometer)
kilometerGroup: number;
constructor(latitude: number, longitude: number) {
this.latitude = latitude;
this.longitude = longitude;
this.timestamp = Date.now();
this.kilometerGroup = 0; // Default group is 0
}
}
- Sports Trajectory Management Class
Create a RunTracker
class to manage the sports trajectory points and calculate the total distance:
/**
* Sports trajectory management class
*/
export class RunTracker {
// All trajectory points
private points: RunPoint[] = [];
// Current total distance (kilometers)
private totalDistance: number = 0;
// Current kilometer group
private currentKilometerGroup: number = 0;
/**
* Add a new trajectory point
* @param latitude Latitude
* @param longitude Longitude
* @returns Current total distance (kilometers)
*/
addPoint(latitude: number, longitude: number): number {
const point = new RunPoint(latitude, longitude);
if (this.points.length > 0) {
// Calculate the distance from the last point
const lastPoint = this.points[this.points.length - 1];
const distance = this.calculateDistance(lastPoint, point);
this.totalDistance += distance;
// Update kilometer group
point.kilometerGroup = Math.floor(this.totalDistance);
if (point.kilometerGroup > this.currentKilometerGroup) {
this.currentKilometerGroup = point.kilometerGroup;
}
}
this.points.push(point);
return this.totalDistance;
}
/**
* Calculate the distance between two points (kilometers)
* Use the Haversine formula to calculate the spherical distance
*/
private calculateDistance(point1: RunPoint, point2: RunPoint): number {
const R = 6371; // Earth's radius (kilometers)
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;
}
/**
* Convert degrees to radians
*/
private toRadians(degrees: number): number {
return degrees * (Math.PI / 180);
}
/**
* Get the current total distance
*/
getTotalDistance(): number {
return this.totalDistance;
}
/**
* Get trajectory points for a specific kilometer group
*/
getPointsByKilometer(kilometer: number): RunPoint[] {
return this.points.filter(point => point.kilometerGroup === kilometer);
}
/**
* Clear trajectory data
*/
clear(): void {
this.points = [];
this.totalDistance = 0;
this.currentKilometerGroup = 0;
}
}
- Recording Distance in the Page Listener
Use the RunTracker
class in the page to record sports trajectory points and calculate the total distance:
private runTracker: RunTracker = new RunTracker();
// Listener addition code
const distance = this.runTracker.addPoint(this.currentLatitude, this.currentLongitude);
// Distance is the current sports distance in kilometers
IV. Summary
This article has detailed how to integrate the Baidu Map SDK in a HarmonyOS application to achieve sports tracking and distance recording. By following these steps, we can implement a fully functional sports application:
-
Integrate Baidu Map SDK:
- Add the necessary dependency packages.
- Initialize Baidu Map and set location options.
-
Page Usage:
- Request the necessary permissions.
- Start and stop location.
- Real-time update of map location and direction.
-
Distance Calculation:
- Define the sports trajectory point model.
- Use the Haversine formula to calculate the distance between two points.
- Record sports trajectory points and real-time update of total distance.
By following these steps, developers can easily implement a powerful sports application that provides real-time sports data and map tracking functions. I hope the content of this article can help you achieve better results in HarmonyOS development!
Top comments (0)