android - 如果设备已经在 Geofence android 中,则停止初始触发

标签 android geolocation location geofencing android-geofence

我在 Android 上使用地理围栏,当创建地理围栏时,如果用户已经在地理围栏内,设备会收到通知,这不是我要寻找的行为,我只想通知转换 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 即使我没有进入,我已经在地理围栏内。 任何人都知道如何停止这个初始触发器?

最佳答案

为什么你得到了初始触发

tl;dr
It's the default behavior

我遇到了你的类似问题:

The transition type is returned as Geofence.GEOFENCE_TRANSITION_ENTER even though I am not entering, I am already inside the geofence.

经过一番研究后,我发现 GeofencingRequest.Builder documentation 上声明了这种行为:

Public Methods

public GeofencingRequest.Builder setInitialTrigger (int initialTrigger)
Sets the geofence notification behavior at the moment when the geofences are added. The default behavior is INITIAL_TRIGGER_ENTER and INITIAL_TRIGGER_DWELL.

要了解这些常量的实际含义,我们需要检查 documentation for the enclosing class, GeofencingRequest :

Constant Summary

int INITIAL_TRIGGER_DWELL
A flag indicating that geofencing service should trigger GEOFENCE_TRANSITION_DWELL notification at the moment when the geofence is added and if the device is already inside that geofence for some time.

int INITIAL_TRIGGER_ENTER
A flag indicating that geofencing service should trigger GEOFENCE_TRANSITION_ENTER notification at the moment when the geofence is added and if the device is already inside that geofence.

int INITIAL_TRIGGER_EXIT
A flag indicating that geofencing service should trigger GEOFENCE_TRANSITION_EXIT notification at the moment when the geofence is added and if the device is already outside that geofence.

这解释了为什么即使您没有使用 setInitialTrigger() 也会收到 GEOFENCE_TRANSITION_ENTER 通知 - 这是默认行为。

在调查这个问题的过程中,我发现了一些有趣的事情。如果您订阅了地理围栏的入口和导出,然后将初始触发器设置为 INITIAL_TRIGGER_ENTER | INITIAL_TRIGGER_EXIT(按位或;将两个常量相加也可以),您将收到有关您当前所在的所有地理围栏(使用 GEOFENCE_TRANSITION_ENTER)以及您所在的所有地理围栏的通知目前在外面(GEOFENCE_TRANSITION_EXIT)。我还没有想出一个好的用例,但无论如何都觉得它很有趣。


如何停止初始触发器

tl;dr
Set the initial trigger to 0, using a constant to attribute meaning to the number (e.g., private static final int NO_INITIAL_TRIGGER = 0)

仔细研究 documentation of setInitialTrigger()可以阅读:

Parameters

initialTrigger the notification behavior. It's a bit-wise of INITIAL_TRIGGER_ENTER and/or INITIAL_TRIGGER_EXIT and/or INITIAL_TRIGGER_DWELL.

使用按位运算的提示,结合为这些常量找到的文档(它们用作每种类型转换的标志)让我质疑如果所有位都关闭会发生什么。

所以我尝试将 0 的值传递给 setInitialTrigger(),以便覆盖默认行为并关闭所有初始触发器而无需求助到 workaround proposed by rfn123 :

private GeofencingRequest createGeofencingRequest(List<Geofence> geofences) {
    return new GeofencingRequest.Builder()
            .setInitialTrigger(0)
            .addGeofences(geofences)
            .build();
}

或者 - 甚至更好 - 赋予魔数(Magic Number)一些意义:

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...
}

关于android - 如果设备已经在 Geofence android 中,则停止初始触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44179175/

相关文章:

android - 如何更改本地 HTML 文件的装饰以在 Android 的 WebView 上显示它

javascript - javascript中的全局变量以获取地理位置

android - 无法在android中找到确切的当前位置

javascript - html 地理位置 : Unknown error acquiring position

php - 如何在 PHP 中使用 MaxMind GeoIP?

java - 获取给定半径(米)和位置的最大经纬度

android - 启动GPS后立即获取位置

Android "com.android.internal.util.Predicate"已弃用

android - 如何将按钮放在 Jetpack Compose 的最右上角

java - 如何从我的应用程序中注销 Facebook?