diff --git a/app/src/main/java/com/a1/nextlocation/fragments/RouteFragment.java b/app/src/main/java/com/a1/nextlocation/fragments/RouteFragment.java index 8e33968..d61a62a 100644 --- a/app/src/main/java/com/a1/nextlocation/fragments/RouteFragment.java +++ b/app/src/main/java/com/a1/nextlocation/fragments/RouteFragment.java @@ -12,6 +12,8 @@ import android.view.View; import android.view.ViewGroup; import com.a1.nextlocation.R; +import com.a1.nextlocation.data.Location; +import com.a1.nextlocation.data.Route; import com.a1.nextlocation.json.DirectionsResult; import com.a1.nextlocation.network.ApiHandler; import com.a1.nextlocation.network.DirectionsListener; @@ -37,11 +39,17 @@ public class RouteFragment extends Fragment { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - ApiHandler.INSTANCE.getDirections(8.681436,49.41461,8.687872,49.420318); +// ApiHandler.INSTANCE.getDirections(8.681436,49.41461,8.687872,49.420318); + Route r = new Route("test"); + r.addLocation(new Location("test",8.681436,49.41461,"route",null)); + r.addLocation(new Location("test",8.687872,49.420318,"route",null)); + ApiHandler.INSTANCE.getDirections(r); } public void onDirectionsAvailable(DirectionsResult result) { Log.d(TAG, "onDirectionsAvailable: got result! " + result); + + } } \ No newline at end of file diff --git a/app/src/main/java/com/a1/nextlocation/json/DirectionsResult.java b/app/src/main/java/com/a1/nextlocation/json/DirectionsResult.java index 0282174..8cf1c7c 100644 --- a/app/src/main/java/com/a1/nextlocation/json/DirectionsResult.java +++ b/app/src/main/java/com/a1/nextlocation/json/DirectionsResult.java @@ -8,7 +8,9 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import org.json.JSONArray; import org.osmdroid.util.GeoPoint; import java.lang.reflect.Array; @@ -50,6 +52,10 @@ public class DirectionsResult { this.steps.add(step); } + /** + * parses a given json string into this object. It gets all the waypoints and steps and combines them so that every step also has the correct coordinates associated with it + * @param json the json string to parse. + */ public void parse(String json) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); @@ -59,6 +65,7 @@ public class DirectionsResult { this.wayPointCoordinates = new double[wayPointCoordinates.size()][2]; + // fill the way point coordinates list for later use for (int i = 0; i < wayPointCoordinates.size(); i++) { JsonElement j = wayPointCoordinates.get(i); JsonArray arr = j.getAsJsonArray(); @@ -67,27 +74,91 @@ public class DirectionsResult { } - JsonObject segment = properties.getAsJsonArray("segments").get(0).getAsJsonObject(); + JsonArray segments = properties.getAsJsonArray("segments"); - setDistance(segment.get("distance").getAsDouble()); - setDuration(segment.get("duration").getAsDouble()); + for (JsonElement element : segments) { + JsonObject segment = element.getAsJsonObject(); - JsonArray steps = segment.getAsJsonArray("steps"); + setDistance(segment.get("distance").getAsDouble()); + setDuration(segment.get("duration").getAsDouble()); - for (JsonElement j : steps) { - DirectionsStep step = gson.fromJson(j,DirectionsStep.class); - double lat; - double longl; - for (int i = 0; i < 2; i++) { - lat = this.wayPointCoordinates[step.getWay_points().get(i)][0]; - longl = this.wayPointCoordinates[step.getWay_points().get(i)][1]; - step.getWaypoints()[i] = new GeoPoint(lat,longl); + JsonArray steps = segment.getAsJsonArray("steps"); + + for (JsonElement j : steps) { + + DirectionsStep step = gson.fromJson(j,DirectionsStep.class); + double lat; + double longl; + + // kinda stinky but it works + for (int i = 0; i < 2; i++) { + lat = this.wayPointCoordinates[step.getWay_points().get(i)][0]; + longl = this.wayPointCoordinates[step.getWay_points().get(i)][1]; + step.getWaypoints()[i] = new GeoPoint(lat,longl); + } + + addStep(step); + Log.d(TAG, "parse: added step" + step); + } + } + + } + + public void parseRoute(String json) { + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + JsonArray routes = JsonParser.parseString(json).getAsJsonObject().getAsJsonArray("routes"); + for (JsonElement element : routes) { + JsonObject route = element.getAsJsonObject(); + JsonObject summary = route.getAsJsonObject("summary"); + this.distance = summary.get("distance").getAsDouble(); + this.duration = summary.get("duration").getAsDouble(); + + JsonPrimitive geometry = route.getAsJsonPrimitive("geometry"); + JsonArray wayPointCoordinates = GeometryDecoder.decodeGeometry(geometry.getAsString(),false); + this.wayPointCoordinates = new double[wayPointCoordinates.size()][2]; + + + // fill the way point coordinates list for later use + for (int i = 0; i < wayPointCoordinates.size(); i++) { + JsonElement j = wayPointCoordinates.get(i); + JsonArray arr = j.getAsJsonArray(); + this.wayPointCoordinates[i][0] = arr.get(0).getAsDouble(); + this.wayPointCoordinates[i][1] = arr.get(1).getAsDouble(); + } + + + JsonArray segments = route.getAsJsonArray("segments"); + + for (JsonElement e : segments) { + JsonObject segment = e.getAsJsonObject(); + + setDistance(segment.get("distance").getAsDouble()); + setDuration(segment.get("duration").getAsDouble()); + + JsonArray steps = segment.getAsJsonArray("steps"); + + for (JsonElement j : steps) { + + DirectionsStep step = gson.fromJson(j,DirectionsStep.class); + double lat; + double longl; + + // kinda stinky but it works + for (int i = 0; i < 2; i++) { + lat = this.wayPointCoordinates[step.getWay_points().get(i)][0]; + longl = this.wayPointCoordinates[step.getWay_points().get(i)][1]; + step.getWaypoints()[i] = new GeoPoint(lat,longl); + } + + addStep(step); + Log.d(TAG, "parse: added step" + step); + } } - addStep(step); - Log.d(TAG, "parse: added step" + step); } + } } diff --git a/app/src/main/java/com/a1/nextlocation/json/GeometryDecoder.java b/app/src/main/java/com/a1/nextlocation/json/GeometryDecoder.java new file mode 100644 index 0000000..3884e52 --- /dev/null +++ b/app/src/main/java/com/a1/nextlocation/json/GeometryDecoder.java @@ -0,0 +1,63 @@ +package com.a1.nextlocation.json; + +import com.google.gson.JsonArray; + +import org.json.JSONArray; +import org.json.JSONException; + +/** + * source: https://github.com/GIScience/openrouteservice-docs#geometry-decoding + */ +public class GeometryDecoder { + + public static JsonArray decodeGeometry(String encodedGeometry, boolean inclElevation) { + JsonArray geometry = new JsonArray(); + int len = encodedGeometry.length(); + int index = 0; + int lat = 0; + int lng = 0; + int ele = 0; + + while (index < len) { + int result = 1; + int shift = 0; + int b; + do { + b = encodedGeometry.charAt(index++) - 63 - 1; + result += b << shift; + shift += 5; + } while (b >= 0x1f); + lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1); + + result = 1; + shift = 0; + do { + b = encodedGeometry.charAt(index++) - 63 - 1; + result += b << shift; + shift += 5; + } while (b >= 0x1f); + lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1); + + + if(inclElevation){ + result = 1; + shift = 0; + do { + b = encodedGeometry.charAt(index++) - 63 - 1; + result += b << shift; + shift += 5; + } while (b >= 0x1f); + ele += (result & 1) != 0 ? ~(result >> 1) : (result >> 1); + } + + JsonArray location = new JsonArray(); + location.add(lat / 1E5); + location.add(lng / 1E5); + if(inclElevation){ + location.add((float) (ele / 100)); + } + geometry.add(location); + } + return geometry; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/a1/nextlocation/network/ApiHandler.java b/app/src/main/java/com/a1/nextlocation/network/ApiHandler.java index 0bf76dc..1b480a8 100644 --- a/app/src/main/java/com/a1/nextlocation/network/ApiHandler.java +++ b/app/src/main/java/com/a1/nextlocation/network/ApiHandler.java @@ -5,6 +5,8 @@ import android.util.Log; import com.a1.nextlocation.data.Location; import com.a1.nextlocation.data.Route; import com.a1.nextlocation.json.DirectionsResult; +import com.google.gson.Gson; +import com.google.gson.JsonObject; import java.io.IOException; import java.util.ArrayList; @@ -15,6 +17,7 @@ import java.util.concurrent.atomic.AtomicReference; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; public enum ApiHandler { @@ -72,6 +75,55 @@ public enum ApiHandler { this.listeners.add(listener); } + public void getDirections(Route route) { +// for (int i = 0; i < route.getLocations().size()-1; i+= 2) { +// Location start = route.getLocations().get(i); +// Location end = route.getLocations().get(i+1); +// getDirections(start,end); +// } + + ArrayList allCoords = new ArrayList<>(); + for (Location location : route.getLocations()) { + allCoords.add(location.getCoordinatesAsDoubles()); + } + + String body = "{\"coordinates\":" + new Gson().toJson(allCoords) + "}"; + + + String requestUrl = BASE_URL + DIRECTIONS_MODE + "?api_key=" + API_KEY; + + Thread t = new Thread(() -> { + + RequestBody requestBody = RequestBody.create(body,JSON); + Request request = new Request.Builder() + .url(requestUrl) + .post(requestBody) + .build(); + + try (Response response = client.newCall(request).execute()) { + if (response.body() != null) { + String responseString = Objects.requireNonNull(response.body()).string(); + Log.d(TAG, "getDirections: got response: " + responseString); + + DirectionsResult result = new DirectionsResult(); + result.parseRoute(responseString); + Log.d(TAG, "getDirections: " + result.getSteps().size()); + + for (DirectionsListener listener : listeners) { + listener.onDirectionsAvailable(result); + } + } + + } catch (IOException e) { + Log.d(TAG, "getDirections: caught exception: " + e.getLocalizedMessage()); + } + }); + + t.start(); + + + } +