智能客服
你问我答,随时在线为你解决问题
在实际应用开发过程中,经常需要用到移动终端设备的位置信息,比如查看所在城市天气、出行打车、旅行导航以及观察运动轨迹等。关于位置定位,位置服务提供了两种定位方式,分别为GNSS定位和网络定位,如下表所示:
定位方式 | 说明 | 优点 |
|---|---|---|
GNSS定位 | 基于全球导航卫星系统,包含GPS、GLONASS、北斗、Galileo等,通过导航卫星、设备芯片提供的定位算法,来确定设备准确位置。 | 定位精准 |
网络定位 | 通过网络进行定位,包括WLAN、蓝牙定位、基站定位。 | 定位速度快 |
利用系统的位置定位能力,可以在多种开发场景中获得实时准确的位置信息。本文将介绍如下四种常见的定位场景,并给出其具体实现方案,帮助开发者更好地掌握位置定位的基本原理和开发流程。
开发者可以根据实际业务诉求,设置相应的定位策略获取设备的当前位置信息,不同定位策略对应表1 定位方式介绍中不同的定位方式。
实现原理
位置服务提供getCurrentLocation()接口来获取当前位置信息,该接口需要用户设置关键参数——定位请求信息。定位请求信息包含定位方式优先级、单次定位超时时间等,分为CurrentLocationRequest和SingleLocationRequest两种类型。两种类型对应的定位优先级分别为LocationRequestPriority和LocatingPriority。
开发步骤
- let request: geoLocationManager.SingleLocationRequest = {
- locatingPriority: 0x502,
- locatingTimeoutMs: 10000
- };
- geoLocationManager.getCurrentLocation(request).then((location: geoLocationManager.Location) => {
- // ...
- }).catch((err: BusinessError) => {
- hilog.error(0x0000, TAG, `getCurrentLocationPosition failed, code: ${err.code}, message: ${err.message}`);
- // ...
- });
- geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
- if (data) {
- this.address = data[0]?.placeName || '';
- // ...
- } else {
- hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
- // ...
- }
- });

开发者可以根据实际用户活动场景或功耗场景,设置相应的定位策略持续获取设备的位置信息,不同定位策略对应表1 定位方式介绍中不同的定位方式。
实现原理
位置服务通过on('locationChange')接口订阅位置变化情况,实现持续获取设备位置信息的场景诉求。该订阅服务需要申请定位请求信息LocationRequest或者ContinuousLocationRequest,并在请求信息中设置定位场景类型和位置信息上报时间间隔。
开发步骤
- let request: geoLocationManager.ContinuousLocationRequest = {
- interval: 1,
- locationScenario: 0x401
- };
- geoLocationManager.on('locationChange', request, this.locationChange);
- geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
- if (data) {
- this.address = data[0]?.placeName || '';
- // ...
- } else {
- hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
- // ...
- }
- });
- try {
- geoLocationManager.off('locationChange', this.locationChange);
- } catch (err) {
- hilog.error(0x0000, TAG, `offLocationChange failed, code: ${err.code}, message: ${err.message}`);
- }


当用户将应用切至后台且依然需要获取设备的位置信息时,可以使用该方式进行后台定位。
实现原理
应用后台定位需要申请后台定位权限ohos.permission.LOCATION_IN_BACKGROUND和长时任务权限ohos.permission.KEEP_BACKGROUND_RUNNING。申请了相关权限后,开启任务模式为定位导航的长时任务,并在其回调接口中通过on('locationChange')订阅位置变化情况,在应用后台持续获取当前位置信息。
开发步骤
申请长时任务权限
- {
- "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
- "reason": "$string:running_background",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "always"
- }
- },
设置长时任务模式为定位导航类型
- "abilities": [
- {
- // ...
- "backgroundModes": [
- "location"
- ],
- // ...
- }
- ],
开启长时任务
- startContinuousTask(): void {
- let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
- if (!context) {
- return;
- }
- let wantAgentInfo: wantAgent.WantAgentInfo = {
- wants: [
- {
- bundleName: context.abilityInfo.bundleName,
- abilityName: context.abilityInfo.name
- }
- ],
- operationType: wantAgent.OperationType.START_ABILITY,
- requestCode: 1,
- wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
- };
-
- wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
- backgroundTaskManager.startBackgroundRunning(context,
- backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj).then(() => {
- this.onLocationChange();
- hilog.info(0x0000, TAG, 'startBackgroundRunning succeeded');
- }).catch((err: BusinessError) => {
- hilog.error(0x0000, TAG, `startBackgroundRunning failed, cause: ${JSON.stringify(err)}`);
- });
- }).catch((err: BusinessError) => {
- hilog.error(0x0000, TAG, `getWantAgent failed, cause: ${JSON.stringify(err)}`);
- });
- }
订阅位置变化情况
- onLocationChange(): void {
- let request: geoLocationManager.ContinuousLocationRequest = {
- interval: 1,
- locationScenario: 0x401
- };
- try {
- geoLocationManager.on('locationChange', request, this.locationChange);
- // ...
- } catch (err) {
- hilog.error(0x0000, TAG, `onLocationChange failed, code: ${err.code}, message: ${err.message}`);
- // ...
- }
- }
- geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
- if (data) {
- this.address = data[0]?.placeName || '';
- // ...
- } else {
- hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
- // ...
- }
- });
关闭长时任务
- stopContinuousTask(): void {
- let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
- if (!context) {
- return;
- }
- backgroundTaskManager.stopBackgroundRunning(context).then(() => {
- if (!this.isOnLocationChange) {
- this.offLocationChange();
- }
- hilog.info(0x0000, TAG, 'stopBackgroundRunning succeeded');
- }).catch((err: BusinessError) => {
- hilog.error(0x0000, TAG, `stopBackgroundRunning failed, cause: ${JSON.stringify(err)}`);
- });
- }
关闭位置变化订阅
- offLocationChange(): void {
- try {
- geoLocationManager.off('locationChange', this.locationChange);
- } catch (err) {
- hilog.error(0x0000, TAG, `offLocationChange failed, code: ${err.code}, message: ${err.message}`);
- }
- }


当用户设备网络信号较弱或者对系统功耗比较敏感时,可以先获取系统缓存的最新位置,即最近一次的历史定位信息。
实现原理
位置服务通过getLastLocation()接口来获取系统缓存的最新位置信息。该接口参数列表为空,返回值为Location位置信息。
开发步骤
- let location = geoLocationManager.getLastLocation();
- geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
- if (data) {
- this.address = data[0]?.placeName || '';
- // ...
- } else {
- hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
- // ...
- }
- });

问题现象
在定位过程中,获取的定位结果不准确,或者将定位结果标记在地图上时出现偏差。
可能原因
解决措施
问题现象
无法使用定位功能获取位置信息。
可能原因
解决措施
问题现象
使用getCurrentLocation()接口获取当前定位信息后,再使用getLastLocation()接口获取缓存定位信息,两次获取的定位信息不一致。
可能原因
所有应用公用系统中的同一份缓存定位信息,有可能在两次接口调用之间有其他应用发起定位,刷新了系统中的缓存定位信息。
解决措施
对比获取定位信息的时间,根据时间判断缓存定位信息是否更新。