本文档介绍了什么是客户端地理围栏、何时使用它,以及如何将其应用于移动应用中的使用情形。本文还介绍了如何使用 Google Navigation SDK 在 Android 上实现示例。

公司通常需要知道移动设备何时进入或离开特定区域。这是通过维护虚拟地理边界(即地理围栏)来实现的,以便在设备越过边界时触发软件事件。
了解特定车辆何时越过边界对于多种使用情形至关重要,例如:
- 客户互动:商家可以使用地理围栏向最终用户推送有关特惠、活动或新产品的通知。
- 安全:企业可以使用地理围栏在数据中心或仓库等敏感区域周围创建虚拟边界,并在有人进入或离开该区域时提醒安保人员。
- 运输:企业可以使用地理围栏来跟踪车辆的位置,并优化路线和时间表。
因此,您必须知道如何在面向客户的应用中表示这些区域(多边形)。此应用应跟踪设备位置,并检查设备是否闯入某个地理围栏。
范围
本文档重点介绍地理围栏的客户端实现。这意味着,客户端应用必须具备以下条件:
- 需要检查是否存在违规行为的多边形;
- 用户的实时位置信息
- 用于检查当前位置是否位于任何多边形内部或外部的逻辑。
本指南包含 Android 示例,但也有在 iOS 上实现此目的的等效方法。Android 位置信息服务内置了圆形地理围栏的实现,您可点击此处查看。下面的参考代码和说明是更复杂实现的起点。
Navigation SDK
导航 SDK 是添加到司机应用中的原生 Android / iOS 库,负责执行以下操作:
- 从运行该应用的设备获取贴合道路的位置信息。与 Android 的 FusedLocationProvider (FLP) 相比,此 API 的精确度更高,因为它会使用 Google 的道路网络将位置信息与最近的路段对齐,从而使预计到达时间 (ETA) 更加准确,并提供 FLP 中的其他信息。
- 提供精细的路线规划体验,让驾驶员能够高效地从 A 点到达 B 点,同时考虑实时路况和其他路线限制。
- 通过事件监听器和已注册的回调触发事件。
监听器
Navigation SDK 提供了许多可供您使用的监听器。下面列举了一些:
- 通过 RoadSnappedLocation 提供程序进行位置信息更改。
- 通过 ReroutingListener 重新规划路线(用户错过掉头、左转等,偏离了建议的路线)。
- 通过 ArrivalListener 接收到达事件(用户到达计划目的地)。
- 剩余距离和预计到达时间事件(当司机即将到达目的地时收到通知 - 基于米数;当司机即将到达目的地时收到通知 - 基于时间)均可通过 .RemainingTimeOrDistanceChangedListener 获得
在本指南中,仅使用 RoadSnappedLocationProvider 及其 LocationListener。
客户端地理围栏解决方案
现在,我们来逐步了解如何构建客户端地理围栏功能。在下面的示例中,我们让 Navigation SDK 以逐向导航模式运行,并在路线中定义了一个表示地理围栏的多边形。
- 地理围栏存储在 BigQuery 中,并由您的后端拉取。
- 后端会定期将地理围栏推送给驾驶应用。
- 司机进行导航,司机应用会定期检查地理围栏是否触发。
- 驾驶员应用会向后端通知触发事件,以便后端采取行动。
当车辆沿路线行驶时,应用会定期检查是否已超出多边形区域。当应用检测到已跨越地理围栏时,界面上会显示一条消息,内容为:Geofence breached(地理围栏违规)。
为 Android-Maps-Utils 配置依赖项
此解决方案使用 Android-Maps-Utils,这是一个开源库,其中包含可用于各种使用 Google Maps Android API 的应用的实用程序。
此库是公开的,托管在 GitHub 上,可通过以下网址访问:
- Android:https://github.com/googlemaps/android-maps-utils
- iOS:https://github.com/googlemaps/google-maps-ios-utils
如需将此库包含在 Android 应用(本文档的适用范围)中,您应修改 build.gradle 文件以包含此库。请注意,此 build.gradle 文件适用于您正在构建的模块(应用),而不是项目级文件。
dependencies {
...
// Utilities for Maps SDK for Android (requires Google Play Services)
implementation 'com.google.maps.android:android-maps-utils:2.3.0'
}
然后,在您将 Gradle 与最新的 build.gradle 文件同步后,即可在 Java 文件中导入 com.google.maps.android.PolyUtil:
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.maps.android.PolyUtil;
定义地理围栏
请注意,此处也导入了 PolygonOptions
。原因是,以下内容用于表示多边形:
mPolygonOptions = new PolygonOptions()
.add(new LatLng(29.4264525,-98.4948758))
.add(new LatLng(29.4267029,-98.4948758))
.add(new LatLng(29.4273742,-98.4945822))
.add(new LatLng(29.4264562,-98.4943592))
.fillColor(0x0000ff36)
.strokePattern(Arrays.asList(new Dash(45.0f), new Gap(10.0f)))
.strokeColor(Color.BLUE)
.strokeWidth(5);
如上所示,我们在此处定义了一个具有预先确定的坐标(纬度、经度)对的固定多边形。不过,在实际场景中,这些坐标和多边形定义通常来自后端端点,并且可能会远程提取。这意味着,多边形必须由应用动态创建。
如需详细了解 PolygonOptions
中可以指定的内容,请点击此处。
您应在创建 fragment 或 activity 期间定义多边形。例如:
protected void onCreate(Bundle savedInstanceState) {
...
mPolygonOptions = new PolygonOptions()
.add(new LatLng(29.4264525,-98.4948758))
.add(new LatLng(29.4267029,-98.4948758))
.add(new LatLng(29.4273742,-98.4945822))
.add(new LatLng(29.4264562,-98.4943592))
.fillColor(0x0000ff36)
.strokePattern(Arrays.asList(new Dash(45.0f), new Gap(10.0f)))
.strokeColor(Color.BLUE)
.strokeWidth(5);
...// more code here
}
监听位置信息更新
定义地理围栏后,您只需创建一个位置更新监听器,以订阅 Navigation SDK 中名为 RoadSnappedLocationProvider
的上述事件,该事件将返回设备的最新位置。
mLocListener = new RoadSnappedLocationProvider.LocationListener() {
@Override
public void onLocationChanged(Location snapped) {
LatLng snappedL = new LatLng(snapped.getLatitude(), snapped.getLongitude());
if(PolyUtil.containsLocation(snappedL, mPolygonOptions.getPoints(), true) && !mGeofenceBreached){
Log.d("Geofence", "Vehicle has breached the polygon");
}
}
@Override
public void onRawLocationUpdate(Location location) {
}
};
借助 Android-Maps-Utils,您可以使用 PolyUtil.containsLocation
检查接收到的位置是否在预定义的多边形内。在下面的示例中,我们使用了表示地理围栏的预定义多边形,但在实际应用中,您可能需要使用多个多边形,因此需要使用循环。
一种替代方法
本文档重点介绍了一种面向客户的应用,该应用可检查是否违反了自定义地理围栏(多边形)。不过,在某些情况下,您可能需要在后端进行此类检查。
这意味着,应用会将位置信息更新报告给后端,然后后端会检查车辆是否违反了某个多边形区域的规定,因此无需依赖客户端应用进行验证。
一种可能的解决方案如下:
[执行环境] 服务器端地理围栏架构
一个示例架构,展示了地理围栏的服务器端方法。

- 驾驶员应用使用 Driver SDK 向 Fleet Engine 发送位置更新。位置更新和应用内导航通过 Navigation SDK 实现。
- Fleet Engine 会将这些更新输出到 Cloud Logging 或 Pub/Sub。
- 后端会收集这些位置信号。
- 地理围栏存储在 BigQuery 中,供后端进行分析。
- 地理围栏触发后,系统会向司机应用发送提醒。
在此架构中,使用了 Driver SDK 和 Fleet Engine。Fleet Engine 可以在 Cloud Logging 中发出 PubSub 更新和生成日志条目。在这两种情况下,都可以检索车辆位置。
然后,后端可以监控 PubSub 队列或读取日志,并留意车辆更新。然后,每当发生更新时(或每隔几秒/几分钟,具体取决于更新的重要性),后端都可以调用 BigQuery GIS 函数来确定指定车辆是在地理围栏内还是在地理围栏外。如果一个或多个地理围栏被突破,后端可以采取行动并触发内部流水线或其他相关工作流。
总结
地理围栏是一种强大的工具,可用于各种用途。商家可以使用地理围栏向最终用户投放相关广告和促销活动,提供基于位置的服务,并提高安全性和保障性。
Navigation SDK 提供了实用的事件监听器,可用于检测旅途中的许多重要时刻。公司通常需要针对特定用例使用自定义地理围栏。本文档展示了一种实现此目标的方法,但可能性是无限的。期待看到您的精彩创意。
后续操作
建议的延伸阅读材料: