如何提高Android地理围栏进入/退出通知的一致性?

时间:2014-01-28 18:44:32

标签: android android-maps-v2 android-geofence

我正在使用内置的地理栅栏API(播放服务),并且结果好坏参半。看起来在设置地理围栏之后,即使GPS打开,进入/退出的通知也非常不一致,具有最新位置(连接了LocationClient,在后台运行。)我开始监控(轮询)位置变化和调试文本字段中的距离,并且即使基于设备注册的位置和地理围栏的位置(我在技术上是在地理围栏的内部/外部),通常有时会触发通知,有时也不会。有什么方法可以让它更具可预测性?我几乎想要放弃这个api并根据设备位置的轮询实现我自己的(电池耗尽)地理围栏。

2 个答案:

答案 0 :(得分:45)

一些建议:

  1. 确保您使用BroadcastReceiver而不是服务来接收转换,否则如果您的应用被杀/关闭,您将不会/可能无法获得它。如下所述: Android Geofence eventually stop getting transition intents

  2. 确保在设备重启后重新创建地理围栏,最好使用启动广播接收器。如下所述: Do Geofences remain active in android after a device reboot

  3. 另一个常见的错误观念,因为它与IOS不同而让我感到困惑的是,如果设备在创建时发现你在地理围栏中,你会立即获得新创建的地理围栏的触发器。我已经使用新创建的地理围栏的“宽限期”解决了这个问题,我在这个帖子中解释过: addProximityAlert doesn't work as expected

  4. 最后一件重要的事情:在您的应用中连接您的LocationClient,或者根本无关紧要,请按照上述要点进行操作。我在代码中添加或删除Geofences的过程基本上是:

    1. 创建并连接locationclient。

    2. 在连接回调中,添加/删除地理围栏

    3. 在geofence-result回调中,断开locationclient。

    4. 每次发生这种情况时,我的位置客户端总共连接几秒钟。操作系统仍会产生地理围栏警报,并在发生时调用我的BroadcastReceiver。

      如果你做这些事我敢打赌你的经历会有所改善。

      希望这有帮助!

答案 1 :(得分:0)

我尝试了已接受回复中的所有建议,但准确的建议并不适合我。如果您在这里寻找更多想法,您应该阅读以下内容。

我能够根据 android location api 加上 JTS Location Suite

使用自己的地理围栏算法来解决问题

为了更准确。您只需要创建一个 jts 多边形,在数学上代表您的围栏。

import pandas as pd
df  = pd.DataFrame.from_records(data)
print(df)
print(df.dtypes)

然后你可以检查当前的 GPS 点是否在给定的多边形内。

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[] {}));
}

仅此而已。然后您可以创建一个 java.util.Timer 来定期迭代多边形列表(地理围栏)以了解哪个被击中或哪个在后面。

注意:在您的模块 build.gradle 中添加以下内容以在您的项目中添加 JTS 库:

final Point point = GF.createPoint(new Coordinate(lat, lon));
if (point.within(getPolygon())) {
   // hit
} else {
   // miss
}