我在Android上使用Geofencing,当创建地理围栏时,如果用户已经在地理围栏中,设备会收到通知,这不是我正在寻找的行为,我只想要在转换ENTER和EXIT时通知。
这就是我创建地理围栏请求的方式:
private GeofencingRequest createGeoFenceRequest(List<Geofence> geofenceList) {
return new GeofencingRequest.Builder()
//The INITIAL_TRIGGER_ENTER is used to notify the user initially if he/she/other
//is already inside the geo-fence zone
//.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofences(geofenceList)
.build();
}
在我的GeofenceTransitionService.java中:
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent != null) {
geofencingEvent = GeofencingEvent.fromIntent(intent);
// Retrieve the transition type.
geoFenceTransition = geofencingEvent.getGeofenceTransition();
}
}
转换类型以Geofence.GEOFENCE_TRANSITION_ENTER的形式返回,即使我没有进入,我已经在地理围栏中了。 任何人都知道如何阻止这个初始触发器?
答案 0 :(得分:6)
<强> TL;博士强>
这是默认行为
我遇到了与你类似的问题:
转换类型以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
通知。
这就解释了为什么即使您没有使用GEOFENCE_TRANSITION_ENTER
,也会收到setInitialTrigger()
的通知 - 这是默认行为。
在调查这个问题时,我发现了一些有趣的东西。如果您订阅了地理围栏的入口和出口,然后将初始触发器设置为INITIAL_TRIGGER_ENTER | INITIAL_TRIGGER_EXIT
(按位OR;将两个常量相加在一起也可以),您将收到您当前所有地理围栏的通知(使用GEOFENCE_TRANSITION_ENTER
)以及您目前在外的所有地理围栏(使用GEOFENCE_TRANSITION_EXIT
)。我还没有考虑过一个很好的用例,但无论如何都觉得它很有趣。
<强> TL;博士强>
将初始触发器设置为0,使用常量将属性赋值给数字(例如,private static final int NO_INITIAL_TRIGGER = 0
)
仔细查看setInitialTrigger()
的文档(请参阅此帖中的第一个链接,我没有声誉再次发布),可以阅读:
参数
initialTrigger
通知行为。它有点INITIAL_TRIGGER_ENTER
和/或INITIAL_TRIGGER_EXIT
和/或INITIAL_TRIGGER_DWELL
。
使用按位运算的提示,结合为这些常量找到的文档(作为每种转换类型的标志),让我质疑如果所有位都被关闭会发生什么。
所以我尝试将0
的值传递给setInitialTrigger()
,以覆盖默认行为并关闭所有初始触发器,而不必诉诸sybilcut的建议解决方法:
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();
}
经过几个小时的测试后,这似乎是一种明智的做法,即使它依赖于记录不良的行为。
请注意:从我执行的测试中,仍然可以获得几乎即时的触发转换,具体取决于所选择的地理位置&#39;半径和当前位置的精度。
例如,您可能稍微远离地理围栏然后突然更新您的位置,将您置于地理围栏内:这将触发地理围栏入口通知。 但是,此入口通知与您已配置的初始触发器无关,而与您感知位置的更新无关。
在离开的说明中,如果您不介意,我建议您采用其他方式来实施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...
}
答案 1 :(得分:1)
解决方法可能是将INITIAL_TRIGGER_DWELL
传递给setInitialTrigger()
方法。
如果设备已经在地理围栏内一段时间,这将仅触发通知。您可以将此时间设置为非常大的数字。
但是,只有在初始触发时单独使用GEOFENCE_TRANSITION_DWELL
并且对添加暂停通知不感兴趣时,此功能才有效。
答案 2 :(得分:1)
看起来好像他们修复了文档,即使没有常量,0也能正常工作