I have created osmdroid map view on which I display custom WMS, that's works. Next I need draw dinamically on this map route between 2 points which I get from custom service in GeoJSON format. GeoJSON looks like this: http://pastebin.com/GJWYNkAq
Calling service over OkHttp Client:
Request request = new Request.Builder()
.url("http://xxx.xxx.xxx.x:7915/GeoService.svc/GetRoute?" + "source=" + encodedSourceAddress + "&target=" + encodedTargetAddress)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful())
throw new IOException("Unexpected code " + response);
String result = response.body().string();
Log.d("RESULT", result);
viewRoute(result); //json is received ok, I debugged it
}
});
I used for this Osmbonuspack library in this method:
public void viewRoute(String geoJson) {
KmlDocument kmlDocument = new KmlDocument();
kmlDocument.parseGeoJSON(geoJson); //application is crashed here
FolderOverlay myOverLay = (FolderOverlay) kmlDocument.mKmlRoot.buildOverlay(map, null, null, kmlDocument);
map.getOverlays().add(myOverLay);
map.invalidate();
}
When I run app, after launching is crashed with this error:
03-09 13:01:51.521 3968-3992/bachelor.vsb.martin.osmdroidclient E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher Process: bachelor.vsb.martin.osmdroidclient, PID: 3968 java.lang.ClassCastException: com.google.gson.JsonNull cannot be cast to com.google.gson.JsonObject at com.google.gson.JsonObject.getAsJsonObject(JsonObject.java:191) at org.osmdroid.bonuspack.kml.KmlPlacemark.(KmlPlacemark.java:89) at org.osmdroid.bonuspack.kml.KmlFeature.parseGeoJSON(KmlFeature.java:237) at org.osmdroid.bonuspack.kml.KmlFolder.(KmlFolder.java:62) at org.osmdroid.bonuspack.kml.KmlFeature.parseGeoJSON(KmlFeature.java:235) at org.osmdroid.bonuspack.kml.KmlDocument.parseGeoJSON(KmlDocument.java:1097) at org.osmdroid.bonuspack.kml.KmlDocument.parseGeoJSON(KmlDocument.java:1112) at bachelor.vsb.martin.osmdroidclient.MainActivity.viewRoute(MainActivity.java:137) at bachelor.vsb.martin.osmdroidclient.MainActivity$1.onResponse(MainActivity.java:127) at okhttp3.RealCall$AsyncCall.execute(RealCall.java:135) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:761)
I am using osmdroid 5.6.4, and osmbonuspack 6.2
It looks like a bug in that library. The current implementation at the master branch is implemented like this:
89: JsonObject geometry = json.getAsJsonObject("geometry");
90: if (geometry != null) {
Yes, getAsJsonObject
can return null
for not existing keys, but Gson uses JsonNull
as the null
value marker (and it makes sense) if the given JSON path value is known to be null
. The only path that has the null
in your JSON is $.features[6].geometry
, so I'm assuming this one is the only cause. What you can do here is raising a new issue at their GitHub issues desk to add an appropriate JsonNull
check in order not to fail at the type cast. A simulated case:
final JsonObject geometry = (JsonObject) geoJsonObject.getAsJsonObject()
.get("features")
.getAsJsonArray()
.get(6)
.getAsJsonObject()
.get("geometry"); // actually JsonNull for $.features[6].geometry
What you can do here so far is:
geometry
JsonPath
elements, so probably just replacing that path value won't work).feature
object (this probably would be more appropriate, but it would cause some data loss).An example for the first option:
final JsonObject geoJsonObject = gson.fromJson(geoJson, JsonObject.class);
fixGeoJsonObject(geoJsonObject);
kmlDocument.parseGeoJSON(geoJsonObject); // passing the "fixed" object
where fixGeoJsonObject
is as follows:
private static void fixGeoJsonObject(final JsonObject geoJsonObject) {
final JsonArray features = geoJsonObject
.get("features")
.getAsJsonArray();
final int length = features.size();
for ( int i = 0; i < length; i++ ) {
final JsonObject feature = features.get(i)
.getAsJsonObject();
final JsonElement geometry = feature.get("geometry");
if ( geometry.isJsonNull() ) {
feature.remove("geometry"); // losing some data...
}
}
}
or for the second option:
private static void fixGeoJsonObject(final JsonObject geoJsonObject) {
final JsonArray features = geoJsonObject
.get("features")
.getAsJsonArray();
for ( int i = 0; i < features.size(); i++ ) {
final JsonObject feature = features.get(i)
.getAsJsonObject();
final JsonElement geometry = feature.get("geometry");
if ( geometry.isJsonNull() ) {
features.remove(i); // losing even more data...
}
}
}
This should fix the ClassCastException
you're getting, but I have no clue how it would affect the library you're using.