开发 HarmonyOS NEXT 定位SDK 开发指南 辅助功能 地理围栏

地理围栏 最后更新时间: 2025年12月18日

以下内容自定位 SDK V1.2.2 版本后支持。

第一步,创建地理围栏

地理围栏没有最大个数限制,您可以无限制的创建围栏。但请您根据业务需求合理的创建围栏,控制围栏个数可以有效的保证程序执行效率。定位 SDK 提供根据高德POI、行政区划,自定义圆形、多边形四种方式创建地理围栏。

注意当用户将应用定位权限设置为“模糊定位”时,地理围栏功能无法正常工作。

1、创建地理围栏对象

//实例化地理围栏客户端 let fenceClient: GeoFenceClient = new GeoFenceClient(this.context); //设置希望侦测的围栏触发行为,默认只侦测用户进入围栏的行为 //public static readonly GEOFENCE_IN 进入地理围栏 //public static readonly GEOFENCE_OUT 退出地理围栏 //public static readonly GEOFENCE_STAYED 停留在地理围栏内10分钟 fenceClient.setActivateAction(GEOFENCE_IN|GEOFENCE_OUT|GEOFENCE_STAYED)

2、创建高德POI地理围栏

提供两个创建高德POI围栏的接口,一个是根据关键字创建POI围栏,另一个是根据经纬度进行周边搜索创建POI围栏。

根据关键字创建围栏

通过以下方法执行POI关键字搜索并创建高德POI地理围栏。

 addKeywordGeoFence(keyword: string, poiType: string, city: string, size: number, customId: string) 

参数说明

参数

说明

示例

keyword

POI关键字

例如:首开广场

poiType

POI类型

例如:写字楼

city

POI所在的城市名称

例如:北京

customId 

与围栏关联的自有业务Id

示例代码

 fenceClient.addKeywordGeoFence("首开广场","写字楼","北京",1,"000FATE23(考勤打卡)"); 

根据周边POI创建围栏

通过以下方法执行POI周边搜索并创建高德POI地理围栏。

 addNearbyGeoFence(keyword: string, poiType: string, point: DPoint, aroundRadius: number, size: number, customId: string) 

参数说明

参数

说明

示例

keyword

POI关键字

例如:首开广场

poiType

POI类型

例如:写字楼

point

周边区域中心点的经纬度,以此中心点建立周边地理围栏

例如:北京

aroundRadius

周边半径,0-50000米,默认3000米

customId 

与围栏关联的自有业务Id

示例代码

 //创建一个中心点坐标 let centerPoint: DPoint = new DPoint(); //设置中心点纬度 centerPoint.setLatitude(39.123D); //设置中心点经度 centerPoint.setLongitude(116.123D); //执行添加围栏的操作 fenceClient.addNearbyGeoFence("肯德基","餐饮",centerPoint,1000F,10,"自有ID"); 

3、创建行政区划围栏

可根据行政区划关键字创建行政区划围栏。

根据关键字创建围栏

 addDistrictGeoFence(keyword: string, customId: string) 

参数说明

参数

说明

示例

keyword

行政区划关键字

例如:朝阳区

customId 

与围栏关联的自有业务Id

示例代码

 fenceClient.addDistrictGeoFence("海淀区","00FDTW103(在北京海淀的化妆品促销活动)"); 

4、创建自定义围栏

自定义围栏包含圆形围栏、多边形围栏两种,自定义围栏一次接口调用只可以创建一个围栏,创建多个自定义围栏需要多次调用创建接口。

圆形围栏

圆形围栏需要提供中心点,以及半径。

 addRoundGeoFence(point: DPoint, radius: number, customId: string) 

参数说明

参数

说明

示例

point

围栏中心点

radius

要创建的围栏半径 ,半径无限制,单位米

customId 

与围栏关联的自有业务Id

示例代码

 /创建一个中心点坐标 let centerPoint: DPoint = new DPoint(); //设置中心点纬度 centerPoint.setLatitude(39.123D); //设置中心点经度 centerPoint.setLongitude(116.123D); fenceClient.addRoundGeoFence(centerPoint,500,"自有业务Id"); 

多边形围栏

 addPolygonGeoFence(points: ArrayList<DPoint>, customId: string) 

参数说明

参数

说明

示例

points

多边形的边界坐标点,最少传3个

customId 

与围栏关联的自有业务Id

示例代码

 let points: ArrayList<DPoint> = new ArrayList<DPoint>(); points.add(new DPoint(39.992702, 116.470470)); points.add(new DPoint(39.994387, 116.472498)); points.add(new DPoint(39.994478, 116.474161)); points.add(new DPoint(39.993163, 116.474504)); points.add(new DPoint(39.991363, 116.472605)); fenceClient.addPolygonGeoFence(points,"自有业务ID"); 

第二步,开始定位

当围栏创建完毕,需要您启动定位,通过定位的回调校验当前位置与围栏的关系

fenceClient.doCheckFence(location)

启动的定位机制:通过“远离围栏时的超低频定位策略”来降低电量消耗,“离近围栏会逐渐提高定位频率”,保证有足够的定位精度来完成围栏位置检测。

需要注意,如果您希望程序在后台持续检测围栏触发行为,您务必要在应用本地服务中启动 GeoFenceClient,且确保这个本地服务一直存活。

下面介绍如何知道创建围栏是成功还是失败。

第三步,接收围栏创建后的回调

围栏创建完毕的信息会通过 GeoFenceListener 进行回调。可以在回调中知道创建围栏成功与否,以及查看所创建围栏的具体内容。

//地理围栏回调 geoFenceListener: GeoFenceListener = { onGeoFenceCreateFinished: (geoFenceList: ArrayList<GeoFence>, errorCode: number, customId: string): void => { if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) { this.promptAction.showToast({ message: '添加围栏成功' }) } else { this.promptAction.showToast({ message: '添加围栏失败' + errorCode }) } } } //设置添加围栏监听 fenceClient.setGeoFenceListener(this.geoFenceListener); 

Java

第四步,接收围栏触发行为广播

用户与围栏位置发生变化的行为称为围栏触发行为,围栏触发行为也是用户进入围栏、退出围栏、在围栏内停留这三种行为的统称,行为的触发是通过鸿蒙的emitter广播进行发送的。

围栏触发行为的广播内容是可选性的,在第一步“创建地理围栏对象”中讲到可以应用 setActiveAction() 方法设置希望侦测到的围栏触发行为。

当定位启动后会马上得到符合希望的所有围栏的状态检测广播,这些广播会告诉上层逻辑每个围栏和当前用户位置的初始状态究竟是IN(定位点在围栏里)还是OUT(定位点在围栏外),这种广播不是围栏触发行为广播,是每个围栏的初始状态广播,不会经常收到,在有新的围栏被创建,或者希望侦测的Action改变时会收到。接下来的每次广播都是围栏触发行为广播(当然,触发前提是位置和围栏的关系发生了改变)。

1、创建并设置emitter

 //订阅广播 const EVENT_NAME = 'GeoFence'; // 收到eventId为GeoFence的事件后执行回调函数 emitter.on(EVENT_NAME, emitterCallback); 

2、创建广播回调

//广播回调 emitterCallback: Callback<emitter.EventData> = (eventData: emitter.EventData) => { if (eventData.data) { let geoFence: object = JSON.parse(eventData.data['geoFence']) let res = '' switch (Number.parseInt(geoFence['status'])) { case GeoFence.STATUS_IN: res = "当前位置进入" + geoFence['customId'] + "围栏\n" break; case GeoFence.STATUS_OUT: res = "当前位置离开" + geoFence['customId'] + "围栏\n" break; case GeoFence.STATUS_STAYED: res = "当前位置停留在" + geoFence['customId'] + "围栏\n" break; default: break } } }

3、解析广播内容

当上一步完成之后,可以在第2步创建的回调中对广播内容进行解析。广播内容是通过 EventData 进行传递的。

 let geoFence: object = JSON.parse(eventData.data['geoFence']) let res = "当前位置进入" + geoFence['customId'] + "围栏\n" 

最后,清除所有围栏

当不再需要使用围栏时,可以调用以下代码对已经设定的围栏进行清除操作。

//会清除所有围栏 fenceClient.removeGeoFence();
返回顶部 示例中心 常见问题 智能客服 公众号
二维码