如何获得一致的地理围栏请求

时间:2017-10-09 11:48:45

标签: android geolocation gps geofencing android-geofence

我已经筋疲力尽了,真的很感激一些帮助。

我想要做的就是Geofences的用途:在我进入,停留或退出某个位置时收到通知。

到目前为止,至少可以说,表现一直很糟糕。

我已经淘汰了几个星期了。 以下是我尝试过的摘要:

  1. 使用广播接收器(而不是官方示例中给出的服务,而不是它应该改变任何东西)
  2. 使用ENTER | DEWLL | EXIT过渡,以获得任何过渡的打击
  3. 将半径增加到250米
  4. 使用RequestLocationUpdates
  5. 定期轮询GPS以查找位置

    到目前为止,地理围栏触发器是一个命中和错过。大部分时间他们根本没有被触发,有时我在5分钟前开车经过这个地点时就被触发了。

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

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

    以下是我的代码的一些片段:

    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");
                    }
                });
            }
        }
    

1 个答案:

答案 0 :(得分:1)

我知道时间已经过去了,但我能够解决同样的问题,从而更好地控制围栏算法。我的解决方案是基于 android location api plus 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')
}