在现代应用中,位置服务与传感器能力已经成为标配。无论是外卖配送、运动健康还是AR导航,都离不开精准的定位和传感器数据。HarmonyOS 提供了完善的地理位置、地图渲染与传感器能力,让开发者可以快速构建位置感知与运动交互应用。
本文将从实战角度出发,带你掌握 HarmonyOS 中的定位服务、地图组件与传感器能力,涵盖权限申请、定位策略、地图渲染、标记交互以及常用传感器的使用与数据处理。
---
使用定位服务前,需要在 `module.json5` 中声明权限:
{
"module": {
"requestPermissions": [
{
"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"
}
}
]
}
}- `APPROXIMATELY_LOCATION`:模糊定位(精度约5km) - `LOCATION`:精确定位(精度可达米级)
import { abilityAccessCtrl, common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';async function requestLocationPermission(context: common.UIAbilityContext): Promise { const atManager = abilityAccessCtrl.createAtManager(); const permissions: Array = [ 'ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION' ];
try { const result = await atManager.requestPermissionsFromUser(context, permissions); return result.authResults.every(r => r === 0); } catch (err) { console.error(`requestPermission failed: ${JSON.stringify(err)}`); return false; } }
import { geoLocationManager } from '@kit.LocationKit';async function getCurrentLocation(): Promise { const request: geoLocationManager.CurrentLocationRequest = { priority: geoLocationManager.LocationRequestPriority.FIRST_FIX, scenario: geoLocationManager.LocationRequestScenario.UNSET, maxAccuracy: 0 };
try { const location = await geoLocationManager.getCurrentLocation(request); console.info(`Latitude: ${location.latitude}, Longitude: ${location.longitude}`); return location; } catch (err) { console.error(`getCurrentLocation failed: ${JSON.stringify(err)}`); return null; } }
参数说明: - `priority`:定位优先级(精度优先 / 速度优先) - `scenario`:定位场景(导航 / 运动 / 日常) - `maxAccuracy`:期望精度(米)
function startLocationTracking() {
const request: geoLocationManager.LocationRequest = {
priority: geoLocationManager.LocationRequestPriority.ACCURACY,
scenario: geoLocationManager.LocationRequestScenario.NAVIGATION,
timeInterval: 1,
distanceInterval: 10,
maxAccuracy: 0
};const callback = (location: geoLocationManager.Location) => { console.info(`New location: ${location.latitude}, ${location.longitude}`); };
try { geoLocationManager.on('locationChange', request, callback); } catch (err) { console.error(`startLocationTracking failed: ${JSON.stringify(err)}`); } }
function stopLocationTracking() { try { geoLocationManager.off('locationChange'); } catch (err) { console.error(`stopLocationTracking failed: ${JSON.stringify(err)}`); } }
适用场景: - `timeInterval`:时间间隔(秒),适合周期性上报 - `distanceInterval`:距离间隔(米),适合轨迹记录
---
HarmonyOS 支持集成主流地图服务(高德、百度、华为 Petal Maps)。以 Petal Maps 为例:
在 `oh-package.json5` 中添加依赖:
{
"dependencies": {
"@hmscore/map-kit": "^1.0.0"
}
}import { map } from '@kit.MapKit';@Entry @Component struct MapPage { private mapController: map.MapComponentController = new map.MapComponentController(); @State centerLocation: map.LatLng = { latitude: 39.9042, longitude: 116.4074 };
build() { Column() { MapComponent({ mapOptions: { position: { target: this.centerLocation, zoom: 12 } }, mapCallback: (err, mapController) => { if (!err) { this.mapController = mapController; console.info('Map initialized successfully'); } } }) .width('100%') .height('100%') } } }
addMarker(latitude: number, longitude: number, title: string) {
const markerOptions: map.MarkerOptions = {
position: { latitude, longitude },
title: title,
clickable: true
};this.mapController.addMarker(markerOptions, (err, marker) => { if (!err) { console.info(`Marker added: ${title}`); // 监听标记点击 marker.on('click', () => { console.info(`Marker clicked: ${title}`); }); } }); }
drawRoute(points: Array) {
const polylineOptions: map.PolylineOptions = {
points: points,
color: 'this.mapController.addPolyline(polylineOptions, (err, polyline) => { if (!err) { console.info('Polyline drawn'); } }); }
// 移动到指定位置
moveToLocation(latitude: number, longitude: number, zoom: number = 15) {
const cameraUpdate = map.CameraUpdateFactory.newLatLngZoom(
{ latitude, longitude },
zoom
);
this.mapController.moveCamera(cameraUpdate);
}// 监听地图点击 this.mapController.on('mapClick', (latLng: map.LatLng) => { console.info(`Map clicked: ${latLng.latitude}, ${latLng.longitude}`); });
---
HarmonyOS 提供了丰富的传感器支持:
| 传感器 | 用途 | 数据类型 | |--------|------|----------| | 加速度传感器 | 检测设备加速度 | x, y, z 轴加速度 | | 陀螺仪 | 检测设备旋转 | x, y, z 轴角速度 | | 磁力计 | 检测磁场强度 | x, y, z 轴磁场 | | 方向传感器 | 获取设备朝向 | alpha, beta, gamma | | 重力传感器 | 检测重力方向 | x, y, z 轴重力 | | 计步器 | 统计步数 | steps | | 心率传感器 | 测量心率 | heartRate |
import { sensor } from '@kit.SensorServiceKit';function startAccelerometer() { const callback = (data: sensor.AccelerometerResponse) => { console.info(`Accelerometer - x: ${data.x}, y: ${data.y}, z: ${data.z}`); };
try { sensor.on(sensor.SensorId.ACCELEROMETER, callback, { interval: 100000000 }); // 100ms } catch (err) { console.error(`startAccelerometer failed: ${JSON.stringify(err)}`); } }
function stopAccelerometer() { try { sensor.off(sensor.SensorId.ACCELEROMETER); } catch (err) { console.error(`stopAccelerometer failed: ${JSON.stringify(err)}`); } }
function startGyroscope() {
const callback = (data: sensor.GyroscopeResponse) => {
console.info(`Gyroscope - x: ${data.x}, y: ${data.y}, z: ${data.z}`);
};try { sensor.on(sensor.SensorId.GYROSCOPE, callback, { interval: 100000000 }); } catch (err) { console.error(`startGyroscope failed: ${JSON.stringify(err)}`); } }
function startOrientation() {
const callback = (data: sensor.OrientationResponse) => {
console.info(`Orientation - alpha: ${data.alpha}, beta: ${data.beta}, gamma: ${data.gamma}`);
};try { sensor.on(sensor.SensorId.ORIENTATION, callback, { interval: 100000000 }); } catch (err) { console.error(`startOrientation failed: ${JSON.stringify(err)}`); } }
function startPedometer() {
const callback = (data: sensor.PedometerResponse) => {
console.info(`Steps: ${data.steps}`);
};try { sensor.on(sensor.SensorId.PEDOMETER, callback); } catch (err) { console.error(`startPedometer failed: ${JSON.stringify(err)}`); } }
---
结合定位、地图与传感器,构建一个运动轨迹记录应用:
import { geoLocationManager } from '@kit.LocationKit';
import { map } from '@kit.MapKit';
import { sensor } from '@kit.SensorServiceKit';@Entry @Component struct TrackingPage { private mapController: map.MapComponentController = new map.MapComponentController(); @State isTracking: boolean = false; @State distance: number = 0; @State steps: number = 0; @State trackPoints: Array = []; private lastLocation: geoLocationManager.Location | null = null;
startTracking() { this.isTracking = true;
// 开启定位 const locationRequest: geoLocationManager.LocationRequest = { priority: geoLocationManager.LocationRequestPriority.ACCURACY, scenario: geoLocationManager.LocationRequestScenario.SPORT, timeInterval: 5, distanceInterval: 10 };
geoLocationManager.on('locationChange', locationRequest, (location) => { const latLng = { latitude: location.latitude, longitude: location.longitude }; this.trackPoints.push(latLng);
// 计算距离 if (this.lastLocation) { this.distance += this.calculateDistance( this.lastLocation.latitude, this.lastLocation.longitude, location.latitude, location.longitude ); } this.lastLocation = location;
// 绘制轨迹 if (this.trackPoints.length > 1) { this.drawRoute(this.trackPoints); } });
// 开启计步器 sensor.on(sensor.SensorId.PEDOMETER, (data: sensor.PedometerResponse) => { this.steps = data.steps; }); }
stopTracking() { this.isTracking = false; geoLocationManager.off('locationChange'); sensor.off(sensor.SensorId.PEDOMETER); }
calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number { const R = 6371e3; // 地球半径(米) const φ1 = lat1 * Math.PI / 180; const φ2 = lat2 * Math.PI / 180; const Δφ = (lat2 - lat1) * Math.PI / 180; const Δλ = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; }
drawRoute(points: Array) { const polylineOptions: map.PolylineOptions = { points: points, color: '
build() { Column() { MapComponent({ mapOptions: { position: { target: { latitude: 39.9042, longitude: 116.4074 }, zoom: 15 } }, mapCallback: (err, controller) => { if (!err) { this.mapController = controller; } } }) .width('100%') .height('70%')
Row() { Text(`距离: ${(this.distance / 1000).toFixed(2)} km`) .fontSize(18) .margin({ right: 20 }) Text(`步数: ${this.steps}`) .fontSize(18) } .margin({ top: 10 })
Button(this.isTracking ? '停止记录' : '开始记录') .width('80%') .margin({ top: 20 }) .onClick(() => { if (this.isTracking) { this.stopTracking(); } else { this.startTracking(); } }) } .width('100%') .height('100%') } }
---
- 按需选择精度:日常签到用模糊定位,导航用精确定位 - 合理设置间隔:避免过高频率消耗电量 - 及时关闭定位:不使用时调用 `off` 注销监听
- 标记聚合:大量标记时使用聚合显示 - 懒加载数据:根据可视区域加载标记 - 避免频繁重绘:批量更新标记和路线
- 选择合适采样率:游戏场景用高频,健康监测用低频 - 及时注销监听:页面销毁时必须调用 `off` - 数据过滤:使用滑动平均或卡尔曼滤波减少噪声
- 最小化原则:只申请必要的权限 - 场景化说明:在申请时明确告知用途 - 降级方案:权限拒绝时提供替代功能
---
本文系统介绍了 HarmonyOS 中的地图、定位与传感器能力:
- 定位服务:从单次定位到连续跟踪,支持多种场景与精度策略 - 地图能力:标记、路线、交互,构建位置可视化界面 - 传感器:加速度、陀螺仪、计步器等,支持运动与交互检测 - 实战案例:运动轨迹记录,融合定位、地图与传感器
掌握这些能力后,你可以构建外卖配送、运动健康、AR导航等位置感知与运动交互应用。下一步可以深入学习性能优化、离线地图与室内定位等高级主题。
---
相关文档: - [HarmonyOS 定位服务开发指南](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/geolocate-V5) - [HarmonyOS Map Kit 开发指南](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/map-V5) - [HarmonyOS 传感器服务开发指南](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/sensor-V5)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。