HarmonyOS鸿蒙Next中地理围栏要怎么做啊?网上找不到开发案例

HarmonyOS鸿蒙Next中地理围栏要怎么做啊?网上找不到开发案例 有没有什么开发案例推荐一下啊大佬们

12 回复

开发者您好,请查看如下解决方案:

【解决方案】 您可参考地理围栏开发指导,其中云侧围栏开发指导已提供示例代码,根据端侧GNSS围栏开发指导整合的参考示例如下(module.json5中需添加ohos.permission.APPROXIMATELY_LOCATION权限):

// Index.ets
import { geoLocationManager } from '@kit.LocationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { notificationManager } from '@kit.NotificationKit';
import { common } from '@kit.AbilityKit';
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';

// 创建围栏
// 通过WantAgentInfo的operationType设置动作类型
let geofence: geoLocationManager.Geofence = {
  'latitude': 34.12,
  'longitude': 124.11,
  'radius': 10000.0,
  'expiration': 10000.0
};

// 指定APP需要监听的地理围栏事件类型,这里表示需要监听进入围栏和退出围栏
let transitionStatusList: Array<geoLocationManager.GeofenceTransitionEvent> = [
  geoLocationManager.GeofenceTransitionEvent.GEOFENCE_TRANSITION_EVENT_ENTER,
  geoLocationManager.GeofenceTransitionEvent.GEOFENCE_TRANSITION_EVENT_EXIT
];

// 创建GEOFENCE_TRANSITION_EVENT_ENTER、GEOFENCE_TRANSITION_EVENT_EXIT事件对应的通知对象
// GEOFENCE_TRANSITION_EVENT_ENTER事件
let notificationRequest1: notificationManager.NotificationRequest = {
  id: 1,
  content: {
    notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
    normal: {
      title: '围栏通知',
      text: '围栏进入',
      additionalText: ''
    }
  }
};
// 创建GEOFENCE_TRANSITION_EVENT_EXIT事件对应的通知对象
let notificationRequest2: notificationManager.NotificationRequest = {
  id: 2,
  content: {
    notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
    normal: {
      title: '围栏通知',
      text: '围栏退出',
      additionalText: ''
    }
  }
};

@Entry
@Component
struct Index {
  fenceId: number = 0;
  context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  private permissions: Array<Permissions> = [
    'ohos.permission.APPROXIMATELY_LOCATION' // 若想获取精准位置,可添加ohos.permission.LOCATION,module.json5中同步添加
  ];

  aboutToAppear(): void {
    // 打开系统位置服务,如果已经打开则无需跳转
    this.jumpToLocationSettings();
  }

  private jumpToLocationSettings() {
    // 1. 检查系统定位开关状态
    const isEnabled = geoLocationManager.isLocationEnabled();

    if (!isEnabled) {
      // 2. 执行跳转操作
      try {
        this.context.startAbility({
          bundleName: 'com.huawei.hmos.settings',
          abilityName: 'com.huawei.hmos.settings.MainAbility',
          uri: 'location_manager_settings'
        }).catch((error: BusinessError) => {
          console.error('跳转失败: ' + error.code + ' - ' + error.message);
        });
      } catch (paramError) {
        console.error('参数错误: ' + paramError);
      }
    } else {
      console.info('位置服务已开启,无需跳转');
      // 此处可添加提示逻辑
    }
  }

  reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
    const atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
    // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
    atManager.requestPermissionsFromUser(context, permissions).then((data) => {
      let grantStatus: Array<number> = data.authResults;
      let length: number = grantStatus.length;
      for (let i = 0; i < length; i++) {
        if (grantStatus[i] === 0) {
          // 用户授权,可以继续访问目标操作
        } else {
          // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
          return;
        }
      }
      // 授权成功
      console.info('ohos.permission.APPROXIMATELY_LOCATION获取权限成功');
    }).catch((err: BusinessError) => {
      console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
    });
  }

  addGnss() {
    // 把创建的通知对象存入Array中,存入顺序与transitionStatusList一致
    let notificationRequestList: Array<notificationManager.NotificationRequest> =
      [notificationRequest1, notificationRequest2];
    // 构造GNSS地理围栏请求对象gnssGeofenceRequest
    let gnssGeofenceRequest: geoLocationManager.GnssGeofenceRequest = {
      // 围栏属性,包含圆心和半径等信息
      geofence: geofence,
      // 指定APP需要监听的地理围栏事件类型
      monitorTransitionEvents: transitionStatusList,
      // 地理围栏事件对应的通知对象,该参数为可选
      notifications: notificationRequestList,
      // 用于监听围栏事件的callback
      geofenceTransitionCallback: (err: BusinessError, transition: geoLocationManager.GeofenceTransition) => {
        if (err) {
          console.error('geofenceTransitionCallback: err=' + JSON.stringify(err));
        }
        if (transition) {
          console.info('GeofenceTransition: %{public}s', JSON.stringify(transition));
        }
      }
    };
    try {
      // 添加围栏
      geoLocationManager.addGnssGeofence(gnssGeofenceRequest).then((id) => {
        // 围栏添加成功后返回围栏ID
        console.info('addGnssGeofence success, fence id: ' + id);
        this.fenceId = id;
      }).catch((err: BusinessError) => {
        console.error('addGnssGeofence failed, promise errCode:' + (err as BusinessError).code +
          ',errMessage:' + (err as BusinessError).message);
      });
    } catch (error) {
      console.error('addGnssGeofence failed, err:' + JSON.stringify(error));
    }
  }

  removeGnss() {
    // fenceId是在geoLocationManager.addGnssGeofence执行成功后获取的
    let fenceId = this.fenceId;
    try {
      geoLocationManager.removeGnssGeofence(fenceId).then(() => {
        console.info('removeGnssGeofence success fenceId:' + fenceId);
      }).catch((error: BusinessError) => {
        console.error('removeGnssGeofence: error=' + JSON.stringify(error));
      });
    } catch (error) {
      console.error('removeGnssGeofence: error=' + JSON.stringify(error));
    }
  }

  build() {
    Column() {
      Button('申请权限')
        .onClick(() => {
          this.reqPermissionsFromUser(this.permissions, this.context);
        });

      Button('添加围栏')
        .onClick(() => {
          this.addGnss();
        });
      Button('删除围栏')
        .onClick(() => {
          this.removeGnss();
        });
    }
    .height('100%')
    .width('100%');
  }
}

更多关于HarmonyOS鸿蒙Next中地理围栏要怎么做啊?网上找不到开发案例的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙地理围栏使用 GeofenceService 实现,核心步骤:创建围栏 → 注册监听 → 处理进出回调


核心代码

import { geofence } from '@kit.LocationKit';
import { LocationRequestPriority } from '@kit.LocationKit';

// 1. 配置围栏
let fenceInfo = {
  latitude: 30.123,
  longitude: 120.123,
  radius: 500,
  expiration: -1,
  alertTypes: 4 | 8 // 进入+离开
};

// 2. 注册围栏
geofence.addGeofence(fenceInfo, (err, id) => {
  console.info('围栏ID:', id);
});

// 3. 监听事件
geofence.on('geofenceTransition', (res) => {
  console.info('状态:', res.transition); // 1=进入 2=离开
});

// 开启定位
let request = { priority: LocationRequestPriority.PRIORITY_HIGH_ACCURACY };
geofence.startLocationUpdates(request);

权限(module.json5)

"requestPermissions": [
  {"name":"ohos.permission.LOCATION"},
  {"name":"ohos.permission.LOCATION_IN_BACKGROUND"}
]

官方文档

HarmonyOS的流畅动画和过渡效果让操作更加顺畅,体验极佳。

尊敬的开发者您好,鸿蒙API中的位置服务可以提供地理围栏功能,可以参考:

端侧GNSS围栏开发指导

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/geofence-guidelines

我自己尝试实现了一下,最后发现还需要生气一下地图的key 有点麻烦, 就没继续了, 但是我主要参考的文档是下面的这俩, 你先研究一下吧

端侧GNSS围栏开发指导

FenceExtensionAbility API 参考

  1. 端侧仅支持构建圆形围栏,并且依赖GNSS芯片的地理围栏功能,仅在室外开阔区域才能准确识别用户进出围栏事件。

地理围栏所使用的接口如下,详细说明参见:Location Kit

使用地理围栏功能,需要有权限ohos.permission.APPROXIMATELY_LOCATION,位置权限申请的方法和步骤见申请位置权限开发指导

参考地址

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/geofence-guidelines

  1. 云侧围栏是指开发者直接使用云侧公共围栏,当用户进入这个区域,在移动设备上进行有针对性的提醒。

参考地址

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/fenceextensionability

你说的就是gnss围栏吧?

先添加相关权限

{
  "requestPermissions": [
    {
      "name": "ohos.permission.LOCATION",
      "reason": "需要定位权限实现地理围栏",
      "usedScene": {
        "when": "always"
      }
    },
    {
      "name": "ohos.permission.LOCATION_IN_BACKGROUND",
      "reason": "后台持续定位"
    },
    {
      "name": "ohos.permission.APP_TRACKING_CONSENT",
      "reason": "应用跟踪授权"
    }
  ]
}

然后你可以直接用下面例子试一下

import geoLocationManager from '@ohos.geoLocationManager';
import wantAgent from '@ohos.app.ability.wantAgent';
import { BusinessError } from '@ohos.base';
import promptAction from '@ohos.promptAction';

@Entry
@Component
struct GeofenceDemo {
  // 围栏ID(自定义,用于区分多个围栏)
  private fenceId: number = -1;
  // 围栏配置:中心点(北京)+ 半径100米 + 有效期1小时
  private fenceConfig = {
    latitude: 39.9042,
    longitude: 116.4074,
    radius: 100, // 单位:米
    expiration: 3600000, // 单位:毫秒,1小时
    coordinateSystemType: geoLocationManager.CoordinateSystemType.WGS84
  };

  build() {
    Column() {
      Button("添加地理围栏")
        .onClick(() => this.addGeofence())
        .margin(10)
      Button("移除地理围栏")
        .onClick(() => this.removeGeofence())
        .margin(10)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  // 1. 添加地理围栏
  async addGeofence() {
    try {
      // 1.1 配置要监听的事件:进入 + 退出
      const transitionEvents = [
        geoLocationManager.GeofenceTransitionEvent.GEOFENCE_TRANSITION_EVENT_ENTER,
        geoLocationManager.GeofenceTransitionEvent.GEOFENCE_TRANSITION_EVENT_EXIT
      ];

      // 1.2 围栏触发回调(应用前台时生效)
      const transitionCallback = (err: BusinessError, transition: geoLocationManager.GeofenceTransition) => {
        if (err) {
          console.error('围栏回调错误:', JSON.stringify(err));
          return;
        }
        // 处理事件:进入/退出
        const eventMsg = transition.transitionEvent === 1 ? '进入围栏' : '退出围栏';
        promptAction.showToast({ message: `围栏ID:${transition.geofenceId},${eventMsg}` });
        console.info('围栏事件:', JSON.stringify(transition));
      };

      // 1.3 构建围栏请求
      const geofenceRequest: geoLocationManager.GnssGeofenceRequest = {
        geofence: this.fenceConfig,
        monitorTransitionEvents: transitionEvents,
        geofenceTransitionCallback: transitionCallback
      };

      // 1.4 注册围栏(返回围栏ID)
      this.fenceId = await geoLocationManager.addGnssGeofence(geofenceRequest);
      promptAction.showToast({ message: `添加成功,围栏ID:${this.fenceId}` });
      console.info('添加围栏成功,ID:', this.fenceId);
    } catch (err) {
      const error = err as BusinessError;
      promptAction.showToast({ message: `添加失败: ${error.message}` });
      console.error('添加围栏失败:', JSON.stringify(error));
    }
  }

  // 2. 移除地理围栏
  async removeGeofence() {
    if (this.fenceId === -1) {
      promptAction.showToast({ message: '未添加围栏' });
      return;
    }
    try {
      await geoLocationManager.removeGnssGeofence(this.fenceId);
      this.fenceId = -1;
      promptAction.showToast({ message: '移除成功' });
      console.info('移除围栏成功');
    } catch (err) {
      const error = err as BusinessError;
      promptAction.showToast({ message: `移除失败: ${error.message}` });
      console.error('移除围栏失败:', JSON.stringify(error));
    }
  }
}

更多的操作,可以看官方文档:

地理围栏简介-地理围栏开发指导-Location Kit(位置服务)-应用服务 - 华为HarmonyOS开发者

看你基于哪个平台呀,这种没案例的,只能看文档自己一点一点处理

HarmonyOS支持2种类型的地理围栏:端侧围栏云侧围栏

端侧围栏:是指由开发者来管理围栏的生命周期,比如创建围栏,删除围栏,比较适合于开发者要使用自己的个性化围栏场景。目前端侧仅支持构建圆形围栏,并且依赖GNSS芯片的地理围栏功能,仅在室外开阔区域才能准确识别用户进出围栏事件。

云侧围栏:是指开发者直接使用华为云侧的公共围栏,比较适合于开发者要使用公共围栏的场景。

官方相关案例:

在HarmonyOS Next中,地理围栏通过@ohos.geolocation模块实现。使用geolocation.on('geofence')监听事件,通过GeofenceRequest定义围栏参数(经纬度、半径、触发动作等)。需申请ohos.permission.LOCATION权限。调用startGeofence()启动,stopGeofence()停止。API详见官方文档的Geolocation接口。

HarmonyOS Next 地理围栏开发主要通过 Location Kit 的 Geofence 模块实现。核心步骤:先申请位置权限,然后通过geoLocationManager创建围栏(指定坐标、半径、过期时间等),添加围栏监听后注册到系统,最后在回调中处理进出事件。官方暂缺独立示例,但可在 DevEco Studio 中通过File > New > Ability > Geofence Ability生成基础代码模板,或查阅 API 参考中的geoLocationManager文档直接入手。

回到顶部