许多 GeoJSON 或 shapefile 点作为 Android 中的地理围栏?
Many GeoJSON or shapefile points as Geofences in Android?
我有一个 GEOJSON(我可以将它转换成 Shapefile 或其他地理参考文件),其中有很多点(几百个),我想在所有点上创建地理围栏。我该怎么做呢?我有完整的代码来获得一个点的地理围栏,但我如何在多个点上创建地理围栏?
当在屏幕上长按时,将添加一个标记,该标记会自动获得一个地理围栏
public void onMapLongClick(LatLng latLng) { // lange Klicken, bis Marker scheint
if (Build.VERSION.SDK_INT >= 29) {
// We need background permission (Manifest.xml)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) { // wenn permission granted
tryAddingGeofence(latLng);
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)){
//We show a dialog and ask for permission
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE);
}
}
} else {
tryAddingGeofence(latLng);
}
}
private void tryAddingGeofence(LatLng latLng) {
mMap.clear();
addMarker(latLng);
addCircle(latLng, GEOFENCE_RADIUS);
addGeofence(latLng, GEOFENCE_RADIUS);
}
private void addGeofence(LatLng latLng, float radius){
Geofence geofence = geofenceHelper.getGeofence(GEOFENCE_ID, latLng, radius,
Geofence.GEOFENCE_TRANSITION_ENTER |
// Geofence.GEOFENCE_TRANSITION_DWELL |
Geofence.GEOFENCE_TRANSITION_EXIT); // wann wird geofence getriggert? -> reinlaufen, darin laufen oder rausgehen
GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence);
PendingIntent pendingIntent = geofenceHelper.getPendingIntent();
geofencingClient.addGeofences(geofencingRequest, pendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Geofence Added...");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
String errorMessage = geofenceHelper.getErrorString(e);
Log.d(TAG, "onFailure: " + errorMessage);
}
});
}
private void addMarker(LatLng latLng) {
MarkerOptions markerOptions = new MarkerOptions().position(latLng);
mMap.addMarker(markerOptions);
}
private void addCircle(LatLng latLng, float radius){
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(latLng);
circleOptions.radius(radius);
circleOptions.strokeColor(Color.argb(255,255,0,0));
circleOptions.fillColor(Color.argb(64,255,0,0));
circleOptions.strokeWidth(4);
mMap.addCircle(circleOptions);
} ```
我为遇到此问题的任何人找到了一个简单的解决方案:
我们需要创建一个包含所有坐标的列表。所以首先我们需要从geojson文件中获取坐标。在接下来的解决方案中,我有一个 KML 文件,但最后它得到了相同的结果。
- 我创建了一个读取 txt 文件的方法(您必须先将 geojson 或 kml 转换为 .txt,然后将其复制到 src/main/res/raw。在我的例子中,我有“monitoring.txt” 所以不要忘记将名称更改为您的文件名。)
在第一部分中,它读取 .txt 并将其保存到一个字符串中。
在第二部分,它从中读取坐标> 和坐标之间的字符串。 "(.*?)" 表示它需要介于两者之间的所有内容。当您拥有 GeoJson 时,请记住查看坐标之间的字符串。然后我获取这个字符串(表示坐标),将它们拆分并将 Latitude 和 Longitude 解析为 double,这样我就可以将它作为 LatLng 对象保护起来。它必须在一个循环中,以便 kml/geojson/txt 文件中的每个坐标都将被获取并存储到列表“dangerousArea”中。
private List<LatLng> dangerousArea = new ArrayList<>();
private void readCoordinatesFromKml() throws IOException {
InputStream inputStream = getResources().openRawResource(R.raw.monitoring);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
try {
i = inputStream.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = inputStream.read();
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
Pattern pattern = Pattern.compile("<coordinates>(.*?)</coordinates>", Pattern.DOTALL);
Matcher matcher = pattern.matcher(byteArrayOutputStream.toString());
while (matcher.find()) {
String[] str = matcher.group(1).split(",");
double Longitude = Double.parseDouble(str[0]);
double Latitude = Double.parseDouble(str[1]);
dangerousArea.add(new LatLng(Latitude, Longitude));
}
}
- 然后您可以添加存储在列表中作为地理围栏的坐标。这取决于您如何调用围绕您的点创建地理围栏的方法:
dangerousArea.forEach(coordinate -> {tryAddingGeofence(coordinate);});
对于最后一件事,您必须查看您的代码在哪里执行此操作。通常它在一个已经确保允许您获取用户位置的功能下。
我有一个 GEOJSON(我可以将它转换成 Shapefile 或其他地理参考文件),其中有很多点(几百个),我想在所有点上创建地理围栏。我该怎么做呢?我有完整的代码来获得一个点的地理围栏,但我如何在多个点上创建地理围栏?
当在屏幕上长按时,将添加一个标记,该标记会自动获得一个地理围栏
public void onMapLongClick(LatLng latLng) { // lange Klicken, bis Marker scheint
if (Build.VERSION.SDK_INT >= 29) {
// We need background permission (Manifest.xml)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) { // wenn permission granted
tryAddingGeofence(latLng);
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)){
//We show a dialog and ask for permission
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE);
}
}
} else {
tryAddingGeofence(latLng);
}
}
private void tryAddingGeofence(LatLng latLng) {
mMap.clear();
addMarker(latLng);
addCircle(latLng, GEOFENCE_RADIUS);
addGeofence(latLng, GEOFENCE_RADIUS);
}
private void addGeofence(LatLng latLng, float radius){
Geofence geofence = geofenceHelper.getGeofence(GEOFENCE_ID, latLng, radius,
Geofence.GEOFENCE_TRANSITION_ENTER |
// Geofence.GEOFENCE_TRANSITION_DWELL |
Geofence.GEOFENCE_TRANSITION_EXIT); // wann wird geofence getriggert? -> reinlaufen, darin laufen oder rausgehen
GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence);
PendingIntent pendingIntent = geofenceHelper.getPendingIntent();
geofencingClient.addGeofences(geofencingRequest, pendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Geofence Added...");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
String errorMessage = geofenceHelper.getErrorString(e);
Log.d(TAG, "onFailure: " + errorMessage);
}
});
}
private void addMarker(LatLng latLng) {
MarkerOptions markerOptions = new MarkerOptions().position(latLng);
mMap.addMarker(markerOptions);
}
private void addCircle(LatLng latLng, float radius){
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(latLng);
circleOptions.radius(radius);
circleOptions.strokeColor(Color.argb(255,255,0,0));
circleOptions.fillColor(Color.argb(64,255,0,0));
circleOptions.strokeWidth(4);
mMap.addCircle(circleOptions);
} ```
我为遇到此问题的任何人找到了一个简单的解决方案: 我们需要创建一个包含所有坐标的列表。所以首先我们需要从geojson文件中获取坐标。在接下来的解决方案中,我有一个 KML 文件,但最后它得到了相同的结果。
- 我创建了一个读取 txt 文件的方法(您必须先将 geojson 或 kml 转换为 .txt,然后将其复制到 src/main/res/raw。在我的例子中,我有“monitoring.txt” 所以不要忘记将名称更改为您的文件名。) 在第一部分中,它读取 .txt 并将其保存到一个字符串中。 在第二部分,它从中读取坐标> 和坐标之间的字符串。 "(.*?)" 表示它需要介于两者之间的所有内容。当您拥有 GeoJson 时,请记住查看坐标之间的字符串。然后我获取这个字符串(表示坐标),将它们拆分并将 Latitude 和 Longitude 解析为 double,这样我就可以将它作为 LatLng 对象保护起来。它必须在一个循环中,以便 kml/geojson/txt 文件中的每个坐标都将被获取并存储到列表“dangerousArea”中。
private List<LatLng> dangerousArea = new ArrayList<>();
private void readCoordinatesFromKml() throws IOException {
InputStream inputStream = getResources().openRawResource(R.raw.monitoring);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
try {
i = inputStream.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = inputStream.read();
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
Pattern pattern = Pattern.compile("<coordinates>(.*?)</coordinates>", Pattern.DOTALL);
Matcher matcher = pattern.matcher(byteArrayOutputStream.toString());
while (matcher.find()) {
String[] str = matcher.group(1).split(",");
double Longitude = Double.parseDouble(str[0]);
double Latitude = Double.parseDouble(str[1]);
dangerousArea.add(new LatLng(Latitude, Longitude));
}
}
- 然后您可以添加存储在列表中作为地理围栏的坐标。这取决于您如何调用围绕您的点创建地理围栏的方法:
dangerousArea.forEach(coordinate -> {tryAddingGeofence(coordinate);});
对于最后一件事,您必须查看您的代码在哪里执行此操作。通常它在一个已经确保允许您获取用户位置的功能下。