为什么你得到了初始触发器
tl;dr
这是默认行为
我遇到了你的类似问题:
转换类型返回为 Geofence.GEOFENCE_TRANSITION_ENTER 即使我没有进入,我已经在地理围栏内。
经过一番研究,我发现GeofencingRequest.Builder documentation 上说明了这种行为:
公共方法
public GeofencingRequest.Builder setInitialTrigger (int initialTrigger)
设置添加地理围栏时的地理围栏通知行为。默认行为是INITIAL_TRIGGER_ENTER 和INITIAL_TRIGGER_DWELL。
要了解这些常量的实际含义,我们需要检查documentation for the enclosing class, GeofencingRequest:
不断总结
int INITIAL_TRIGGER_DWELL
一个标志,指示地理围栏服务应在添加地理围栏时触发GEOFENCE_TRANSITION_DWELL 通知,并且如果设备已经在该地理围栏内一段时间。
int INITIAL_TRIGGER_ENTER
指示地理围栏服务应在添加地理围栏时以及设备已在该地理围栏内时触发GEOFENCE_TRANSITION_ENTER 通知的标志。
int INITIAL_TRIGGER_EXIT
一个标志,指示地理围栏服务应在添加地理围栏时触发GEOFENCE_TRANSITION_EXIT 通知,如果设备已经在该地理围栏之外。
这解释了为什么即使您没有使用 setInitialTrigger() 也会通知您 GEOFENCE_TRANSITION_ENTER - 这是默认行为。
在调查这件事时,我发现了一些有趣的事情。如果您订阅地理围栏的入口和离开,然后将初始触发器设置为INITIAL_TRIGGER_ENTER | INITIAL_TRIGGER_EXIT(按位或;将两个常数相加也可以),您将收到当前所在的所有地理围栏的通知(GEOFENCE_TRANSITION_ENTER ) 以及您目前在外面的所有地理围栏(使用GEOFENCE_TRANSITION_EXIT)。我还没有想到一个好的用例,但无论如何发现它很有趣。
如何停止初始触发
tl;dr
将初始触发器设置为 0,使用常量将含义赋予数字(例如,private static final int NO_INITIAL_TRIGGER = 0)
仔细查看documentation of setInitialTrigger(),可以阅读:
参数
initialTrigger 通知行为。这有点像INITIAL_TRIGGER_ENTER 和/或INITIAL_TRIGGER_EXIT 和/或INITIAL_TRIGGER_DWELL。
使用按位运算的提示,结合为这些常量找到的文档(它们作为每种转换类型的标志)让我质疑如果所有位都关闭会发生什么。
所以我尝试将0 的值传递给setInitialTrigger(),以覆盖默认行为并关闭所有初始触发器,而不必求助于workaround proposed by rfn123:
private GeofencingRequest createGeofencingRequest(List<Geofence> geofences) {
return new GeofencingRequest.Builder()
.setInitialTrigger(0)
.addGeofences(geofences)
.build();
}
或者——也许更好——赋予幻数一些意义:
private static final int NO_INITIAL_TRIGGER = 0;
private GeofencingRequest createGeofencingRequest(List<Geofence> geofences) {
return new GeofencingRequest.Builder()
.setInitialTrigger(NO_INITIAL_TRIGGER)
.addGeofences(geofences)
.build();
}
经过几个小时的测试,这似乎是一种明智的方法即使它依赖于记录不充分的行为(如keepTrackOfYourStack has noticed,文档已更新以澄清这一点)。
请注意:根据我执行的测试,根据所选地理围栏的半径和当前位置的精度,仍然可以几乎立即触发过渡。
例如,您可能稍微远离地理围栏,然后突然更新您的位置,将您置于地理围栏内:这将触发地理围栏进入通知。
但是,这个进入通知与您配置的初始触发器无关,而是与您感知位置的更新有关。
顺便说一句,如果您不介意,我有一个替代方法来实现onHandleIntent() 方法的建议。
无需检查intent 对象的无效性,只需将该责任传递给GeofencingEvent#fromIntent() 调用即可。
然后,您可以使用保护子句检查返回的event 对象的有效性——这将增加您的方法的可读性(至少在我看来)。
这将允许您测试无效性并检查事件是否有错误。
类似这样的:
@Override
protected void onHandleIntent(@Nullable Intent intent) {
GeofencingEvent event = GeofencingEvent.fromIntent(intent);
if (event == null || event.hasError()) {
logInvalidEvent(event);
return;
}
// Process the event...
}