我正在使用内置的地理围栏 API(播放服务)并且结果好坏参半。看起来在设置地理围栏后,即使 GPS 开启,进入/退出的通知也非常不一致,具有最新的位置(LocationClient 已连接,在后台运行。)我开始监控(轮询)位置变化和调试文本字段中的距离,并看到,即使基于设备注册的位置和地理围栏的位置,我在技术上位于地理围栏内部/外部,有时会触发通知,有时不会触发通知。有什么办法可以让这更可预测?我几乎想放弃这个 api 并根据设备位置的轮询实现我自己的(电池耗尽)地理围栏。
2 回答
几个建议:
确保您使用的是 BroadcastReceiver 而不是 Service 来接收转换,否则如果您的应用程序被杀死/关闭,您将不会/可能不会收到它。如此处所述: Android Geofence 最终停止获取转换意图
确保在设备重新启动后重新创建地理围栏,最好使用引导广播接收器。如此处所述: 设备重启后,地理围栏是否在 android 中保持活动状态
另一个常见的误解让我感到困惑,因为它与 IOS 不同,如果设备在创建它时发现您在地理围栏内,您总是会立即获得新创建的地理围栏的触发器。我已经使用新创建的地理围栏的“宽限期”自己解决了这个问题,我在这个线程中解释了这一点: addProximityAlert 不能按预期工作
最后一件重要的事情:如果您遵循上述几点,是否将 LocationClient 连接到您的应用程序中并不重要。我在代码中添加或删除地理围栏的过程基本上是:
创建并连接 locationclient。
在连接回调中,添加/删除地理围栏
在 geofence-result 回调中,断开 locationclient。
每次发生这种情况时,我的位置客户端总共只连接了几秒钟。操作系统仍然会产生地理围栏警报,并在它们发生时调用我的 BroadcastReceiver。
如果你做这些事情,我敢打赌你的经验会改善。
希望这可以帮助!
我尝试了接受回复中的所有建议,但准确度对我来说并不好。如果您在这里寻找更多想法,您应该阅读以下内容。
我能够根据android location api plus JTS Location Suite来解决我自己的地理围栏算法的问题
为了更准确。您所需要的只是创建一个 jts 多边形,它在数学上代表您的围栏。
static GeometryFactory GF = new GeometryFactory();
public Polygon getPolygon() {
ArrayList<Coordinate> coors = new ArrayList<>();
for (Point p : getPolygonPoints()) {
coors.add(new Coordinate(p.lat, p.lon));
}
// close the polygon is needs
final Coordinate first = coors.get(0);
final Coordinate last = coors.get(coors.size()-1);
if (!first.equals2D(last)) {
coors.add(coors.get(0));
}
// create polygon
return GF.createPolygon(coors.toArray(new Coordinate[] {}));
}
然后您可以检查当前 GPS 点是否在给定多边形的内部。
final Point point = GF.createPoint(new Coordinate(lat, lon));
if (point.within(getPolygon())) {
// hit
} else {
// miss
}
就是这样。然后,您可以创建一个java.util.Timer来定期迭代多边形列表(地理围栏)以了解哪个被击中或哪个在后面。
注意:在您的模块 build.gradle 中添加以下内容以在您的项目中添加 JTS 库:
implementation(group: 'org.locationtech.jts.io', name: 'jts-io-common', version: '1.18.1') {
exclude(group: 'org.hamcrest')
}