使用 osmbonuspack 库在 osmdroid 地图上绘制路线
Draw route on osmdroid map with osmbonuspack library
我已经创建了 osmdroid 地图视图,我在上面显示了自定义 WMS,这是可行的。接下来,我需要在我从 GeoJSON 格式的自定义服务获得的 2 个点之间动态绘制这条地图路线。 GeoJSON 看起来像这样:http://pastebin.com/GJWYNkAq
通过 OkHttp 客户端调用服务:
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
}
});
我在这个方法中使用了这个 Osmbonuspack 库:
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();
}
当我 运行 应用程序启动后崩溃并出现此错误:
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.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)
我正在使用 osmdroid 5.6.4 和 osmbonuspack 6.2
它看起来像是那个库中的错误。 current在master分支的实现是这样实现的:
89: JsonObject geometry = json.getAsJsonObject("geometry");
90: if (geometry != null) {
是的,getAsJsonObject
可以 return null
用于不存在的键,但是 Gson 使用 JsonNull
作为 null
值标记(这很有意义) 如果给定的 JSON 路径值已知为 null
。在您的 JSON 中具有 null
的唯一路径是 $.features[6].geometry
,所以我假设这是唯一的原因。您在这里可以做的是在他们的 GitHub 问题台提出一个新问题,以添加适当的 JsonNull
检查,以免在类型转换时失败。模拟案例:
final JsonObject geometry = (JsonObject) geoJsonObject.getAsJsonObject()
.get("features")
.getAsJsonArray()
.get(6)
.getAsJsonObject()
.get("geometry"); // actually JsonNull for $.features[6].geometry
到目前为止你可以在这里做的是:
- 要么从树中删除该路径(我没有分析该库是否可以与 empty/incomplete
geometry
JsonPath
元素一起使用,所以可能只是替换该路径值没用)。
- 或者删除整个第 7 个
feature
对象(这可能更合适,但会导致一些数据丢失)。
第一个选项的示例:
final JsonObject geoJsonObject = gson.fromJson(geoJson, JsonObject.class);
fixGeoJsonObject(geoJsonObject);
kmlDocument.parseGeoJSON(geoJsonObject); // passing the "fixed" object
其中fixGeoJsonObject
如下:
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...
}
}
}
或第二个选项:
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...
}
}
}
这应该可以解决您得到的 ClassCastException
,但我不知道它会如何影响您正在使用的库。
编辑 1:
我已经创建了 osmdroid 地图视图,我在上面显示了自定义 WMS,这是可行的。接下来,我需要在我从 GeoJSON 格式的自定义服务获得的 2 个点之间动态绘制这条地图路线。 GeoJSON 看起来像这样:http://pastebin.com/GJWYNkAq
通过 OkHttp 客户端调用服务:
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
}
});
我在这个方法中使用了这个 Osmbonuspack 库:
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();
}
当我 运行 应用程序启动后崩溃并出现此错误:
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.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)
我正在使用 osmdroid 5.6.4 和 osmbonuspack 6.2
它看起来像是那个库中的错误。 current在master分支的实现是这样实现的:
89: JsonObject geometry = json.getAsJsonObject("geometry");
90: if (geometry != null) {
是的,getAsJsonObject
可以 return null
用于不存在的键,但是 Gson 使用 JsonNull
作为 null
值标记(这很有意义) 如果给定的 JSON 路径值已知为 null
。在您的 JSON 中具有 null
的唯一路径是 $.features[6].geometry
,所以我假设这是唯一的原因。您在这里可以做的是在他们的 GitHub 问题台提出一个新问题,以添加适当的 JsonNull
检查,以免在类型转换时失败。模拟案例:
final JsonObject geometry = (JsonObject) geoJsonObject.getAsJsonObject()
.get("features")
.getAsJsonArray()
.get(6)
.getAsJsonObject()
.get("geometry"); // actually JsonNull for $.features[6].geometry
到目前为止你可以在这里做的是:
- 要么从树中删除该路径(我没有分析该库是否可以与 empty/incomplete
geometry
JsonPath
元素一起使用,所以可能只是替换该路径值没用)。 - 或者删除整个第 7 个
feature
对象(这可能更合适,但会导致一些数据丢失)。
第一个选项的示例:
final JsonObject geoJsonObject = gson.fromJson(geoJson, JsonObject.class);
fixGeoJsonObject(geoJsonObject);
kmlDocument.parseGeoJSON(geoJsonObject); // passing the "fixed" object
其中fixGeoJsonObject
如下:
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...
}
}
}
或第二个选项:
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...
}
}
}
这应该可以解决您得到的 ClassCastException
,但我不知道它会如何影响您正在使用的库。