【问题标题】:How to get consistent Geofence requests如何获得一致的地理围栏请求
【发布时间】:2018-03-20 14:55:38
【问题描述】:

我已经用尽了一切,非常感谢一些帮助。

我想要做的正是地理围栏的用途:在我进入、停留或离开某个位置时收到通知。

到目前为止,性能一直很糟糕,至少可以这么说。

我已经搜索了几个星期了。 以下是我尝试过的总结:

  1. 使用广播接收器(而不是官方示例中给出的 Service,并不是说它应该改变任何东西)
  2. 使用 ENTER |戴尔 | EXIT 过渡,以便在任何过渡中获得成功
  3. 将半径增加到 250m
  4. 使用 RequestLocationUpdates 定期轮询 GPS 以获取位置

到目前为止,地理围栏触发器屡试不爽。大多数情况下它们根本不会触发,有时我在 5 分钟前开车经过该位置时触发。

似乎唯一有帮助的是定期 GPS 轮询,但即便如此,挂起的意图也会以非常不规则的间隔收到。

你还有什么我可以尝试的吗?请告诉我。 谢谢!!!

这是我的代码的一些 sn-ps:

GPS 轮询

public static void CreateLocationUpdateRequest(Context context)
{
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setInterval(10000);
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setMaxWaitTime(10000);
    locationRequest.setExpirationDuration(1000000);

    Intent locReqIntent = new Intent("LOCATION_UPDATE");
    PendingIntent locUpdatePendingIntent = PendingIntent.getBroadcast(context, 0, locReqIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);

    if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        Task<Void> locationTask = fusedLocationProviderClient.requestLocationUpdates(locationRequest, locUpdatePendingIntent);

        locationTask.addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Log.i("CreateGeofencingRequest", "SUCCESS");
            }
        });

        locationTask.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.i("CreateGeofencingRequest", "FAILED");
            }
        });
    }
}

创建地理围栏请求

geofenceTransitionType = Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT;


        Geofence geofence = new Geofence.Builder()
                                .setRequestId(String.valueOf(geofencingReq.getId()))
                                .setCircularRegion(Double.parseDouble(location.getLatitude()), Double.parseDouble(location.getLongitude()), 250)
                                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                                .setTransitionTypes(geofenceTransitionType)
                                .setLoiteringDelay(2000)
                                .build();

        GeofencingRequest geofencingRequest = new GeofencingRequest.Builder()
                                                  .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
                                                  .addGeofence(geofence)
                                                  .build();

        Intent geofencingIntent = new Intent(context, GeofenceBroadcastReceiver.class);
        geofencingIntent.putExtra("ID", geofencingReq.getId());
        geofencingIntent.setAction("GEOFENCE_TRIGGER_BROADCAST");


        PendingIntent geofencingPendingIntent = PendingIntent.getBroadcast(context, geofencingReq.getId(), geofencingIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        LocationManager locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        boolean providerEnabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            Task<Void> geofenceTask = mGeofencingClient.addGeofences(geofencingRequest, geofencingPendingIntent);

            geofenceTask.addOnSuccessListener(new OnSuccessListener<Void>() {
                @Override
                public void onSuccess(Void aVoid) {
                    Log.i("CreateGeofencingRequest", "SUCCESS");
                }
            });

            geofenceTask.addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.i("CreateGeofencingRequest", "FAIL");
                }
            });
        }
    }

【问题讨论】:

  • 你如何测试这个?当您在模拟器上测试时,地理围栏是一个命中/未命中。尝试使用模拟位置应用程序在物理设备上进行测试,例如 Lockito
  • 谢谢。我正在使用“GeoFix”应用程序在真实设备上进行测试。但现在我意识到,Android 可能需要的不仅仅是 GPS 位置来触发地理围栏。看起来它考虑了旅行路线等。所以实际上在路上尝试是最好的方法。
  • Capybara 有同样的问题。由于他的代表率低,他无法在这里发表评论。他的评论:i'm with the exactly same problem, you could answer how you did to resolve this? The problem was just the emulator and fake gps?

标签: android geolocation gps geofencing android-geofence


【解决方案1】:

我知道时间已经过去了,但我能够解决同样的问题,从而更好地控制栅栏算法。我的解决方案是基于android location api加上JTS Location Suite实现我自己的地理围栏系统

为了更准确。您只需要创建一个 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 if 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 点是否在给定多边形内。

// lat & lon values  are given from geoloc api
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')
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多