本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、基础配置与权限申请
1. 权限声明
在module.json5中声明定位权限,需区分精确与模糊定位:
{
"requestPermissions": [
{
"name": "ohos.permission.LOCATION", // 精确位置(米级)
"reason": "$string:location_permission", // 权限说明
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse" // 使用时申请
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION", // 模糊位置(5公里级)
"reason": "$string:fuzzy_location_permission",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "always" // 始终申请
}
}
]
}
注意:若需后台定位,需额外申请ohos.permission.LOCATION_IN_BACKGROUND权限。
2. 动态权限检查
import { abilityAccessCtrl, Permissions } from '@kit.AbilityKit';
async function checkLocationPermission(): Promise<boolean> {
let atManager = abilityAccessCtrl.createAtManager();
try {
let status = await atManager.checkAccessToken(
abilityAccessCtrl.AccessToken.PERMISSION_LOCATION
);
return status === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
} catch (err) {
console.error('权限检查失败:', err);
return false;
}
}
二、核心API与基础定位
1. 单次定位(获取当前位置)
import geoLocationManager from '@ohos.geoLocationManager';
async function getCurrentLocation(): Promise<void> {
let request: geoLocationManager.SingleLocationRequest = {
locatingPriority: geoLocationManager.LocationPriority.ACCURACY, // 高精度模式
locatingTimeoutMs: 10000 // 超时10秒
};
try {
let location = await geoLocationManager.getCurrentLocation(request);
console.log(`纬度: ${location.latitude}, 经度: ${location.longitude}`);
} catch (err) {
console.error('定位失败:', err.code); // 错误码参考
}
}
参数说明:
locatingPriority:可选ACCURACY(GNSS优先)或LOW_POWER(网络定位) 。locatingTimeoutMs:超时时间,建议设为5-30秒。
2. 连续定位(实时更新位置)
let locationCallback = (err, location) => {
if (err) return;
console.log(`实时位置: ${location.latitude}, ${location.longitude}`);
};
function startContinuousLocation() {
let request: geoLocationManager.LocationRequest = {
locatingPriority: geoLocationManager.LocationPriority.ACCURACY,
interval: 2000 // 2秒更新一次
};
geoLocationManager.on('locationChange', request, locationCallback);
}
function stopContinuousLocation() {
geoLocationManager.off('locationChange', locationCallback);
}
三、高级功能实现
1. 逆地理编码(坐标转地址)
import geoCoder from '@ohos.geoLocationManager';
async function reverseGeocode(lat: number, lon: number): Promise<string> {
let request: geoCoder.ReverseGeoCodeRequest = {
locale: 'zh-CN', // 语言
latitude: lat,
longitude: lon
};
try {
let result = await geoCoder.getAddressesFromLocation(request);
return result[0].address; // 返回首个地址
} catch (err) {
console.error('逆地理编码失败:', err);
return '未知位置';
}
}
2. 地理围栏(区域监控)
let geofenceCallback = (err, event) => {
if (err || !event) return;
console.log(`进入围栏: ${event.geofences[0].geofenceId}`);
};
async function addGeofence() {
let fence: geoLocationManager.Geofence = {
latitude: 39.90469, // 围栏中心纬度
longitude: 116.40717, // 围栏中心经度
radius: 500, // 半径500米
expiration: 86400000 // 24小时后失效
};
try {
await geoLocationManager.addGeofence(fence, geofenceCallback);
} catch (err) {
console.error('围栏添加失败:', err);
}
}
四、第三方定位SDK集成(腾讯/百度)
1. 腾讯定位SDK集成
// 1. 安装SDK
"dependencies": {
"@tencentmap/location_sdk": "1.0.6"
}
// 2. 初始化
import { scanBarcode } from '@kit.ScanKit';
scanBarcode.startScanForResult(context, {
scanTypes: [scanBarcode.ScanType.QR_CODE]
}).then(result => {
console.log('腾讯定位结果:', result.scanResult);
});
2. 百度定位SDK集成
// 配置工程引入SDK
import { BaiduLocation } from '@baidu/location_sdk';
BaiduLocation.init().then(() => {
BaiduLocation.startLocation({
coorType: 'gcj02' // 国测局坐标
});
});
特点:提供高精度定位离线定位能力。
五、总结与优化
-
功耗优化:
- 低功耗场景使用
LOW_POWER模式。 - 非必要时不开启连续定位 。
- 低功耗场景使用
-
错误处理:
// 定位开关未打开
if (err.code === 3301100) {
prompt.showToast({ message: '请开启位置服务' });
}
3. 多设备适配:
// 手表设备使用简化定位
if (deviceInfo.deviceType === 'watch') {
request.locatingPriority = geoLocationManager.LocationPriority.LOW_POWER;
}
六、完整示例(获取位置并显示地址)
@Entry
@Component
struct LocationScreen {
@State address: string = '正在定位...';
async onPageShow() {
if (await checkLocationPermission()) {
let location = await getCurrentLocation();
this.address = await reverseGeocode(location.latitude, location.longitude);
} else {
this.address = '权限未授权';
}
}
build() {
Column() {
Text(this.address)
.fontSize(20)
.margin(10)
}
}
}
3082

被折叠的 条评论
为什么被折叠?



