我正在使用内置的地理围栏API(Play服务)并且结果不尽如人意。即使开启了GPS,且已经连接了位置客户端(LocationClient)在后台运行,设置地理围栏后,进入/离开通知的触发非常不确定。我开始监控(轮询)位置变化和距离,并在调试文本字段中看到,即使基于设备注册的位置和地理围栏位置,我在技术上仍然在/在外面地理围栏之内,有时会触发通知,有时却不会。有没有办法让这更加可预测?我几乎想放弃这个API,实现自己的(耗电)地理围栏,基于对设备位置的轮询。
我正在使用内置的地理围栏API(Play服务)并且结果不尽如人意。即使开启了GPS,且已经连接了位置客户端(LocationClient)在后台运行,设置地理围栏后,进入/离开通知的触发非常不确定。我开始监控(轮询)位置变化和距离,并在调试文本字段中看到,即使基于设备注册的位置和地理围栏位置,我在技术上仍然在/在外面地理围栏之内,有时会触发通知,有时却不会。有没有办法让这更加可预测?我几乎想放弃这个API,实现自己的(耗电)地理围栏,基于对设备位置的轮询。
确保使用BroadcastReceiver而不是Service接收转换,否则如果您的应用程序被杀死/关闭,则可能无法获取它。如此处所述: Android地理围栏最终无法获取转换意图
在设备重新启动后,请确保重新创建您的地理围栏,最好使用一个boot-broadcast receiver。 如此处所述:设备重新启动后,Android的地理围栏是否仍然处于活动状态
另一个常见误解,这使我感到困惑,因为它与IOS不同,即如果设备在创建时发现您在地理围栏内部,您将立即获得触发器。我自己使用“优雅期”解决了这个问题,在此主题中解释了这一点
最后一个重要的事情:如果您遵循以上几点,则您的应用程序连接或未连接LocationClient都不应该有任何影响。我在代码中添加或删除Geofences的过程基本上是:
创建并连接locationclient。
在连接回调中,进行geofence(s)的添加/删除
在geofence-result回调中,断开locationclient。
每次发生这种情况时,我的位置客户端总共只连接了几秒钟。操作系统仍将产生地理围栏警报,并在发生时调用我的BroadcastReceiver。
如果您做到这些,我敢打赌您的体验会得到改善。
希望能对你有所帮助!
我尝试了所有被接受的回答中的建议,但对我来说准确度并没有提高。如果您在这里寻找更多想法,您应该阅读以下内容。
我能够通过基于安卓位置API和JTS位置套件的自己的地理围栏算法来解决问题。
为了更精确,您所需做的就是创建一个代表您的围栏的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')
}