androidgeojsonshapefilepointsgeofence

Many GeoJSON or shapefile points as Geofences in Android?


I have a GEOJSON (I could convert it into Shapefile or another georeferenced file) with many points (a few hundreds) and I want to create geofences on all of them. How do I do this? I have the whole code to get a geofence of one point but how do I create geofences on many points?

When clicking long on the screen, a marker will be added which gets automatically a geofence

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

Solution

  • I found an easy solution for anyone who will have this problem: We need to create a list of all the coordinates. So at first we need to get the coordinates from the geojson file. In the followed solution I had a KML file but at the end it gets the same result.

    1. I created a method which reads a txt file (you have to convert geojson or kml into .txt first and then copy it into src/main/res/raw. In my case I have "monitoring.txt" So dont forget to change the name into your filename.) In the first part it reads the .txt and saves it into a String. In the scond part it reads from it that String that is in between coordinates> and </coordinates. "(.*?)" shows that it takes everything that is between. When you have a GeoJson remember to look between what Strings the coordinates are. Then I take this String (means the coordinates), split them and parse Latitude and Longitude into double so that I can then safe it as LatLng Object. It has to be in a loop so that every coordinate in the kml/geojson/txt file will be taken and stored into the list "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));
    
            }
        }
    
    1. Then you can just add the coordinates which are stored in the list as Geofences. This depends on what you called your method which creates a Geofence around your points:
    dangerousArea.forEach(coordinate -> {tryAddingGeofence(coordinate);});
    

    For the last thing you have to look at your code where to do this. Normally it is under a function which already made sure that you are allowed to get the location of the user.