十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

GraphHopper client-hc 使用指南:Java 与 Android 手工编写的 Directions API 客户端

GraphHopper client-hc 使用指南:Java 与 Android 手工编写的 Directions API 客户端 GraphHopper client-hc 使用指南Java 与 Android 手工编写的 Directions API 客户端【免费下载链接】graphhopperOpen source routing engine for OpenStreetMap. Use it as Java library or standalone web server.项目地址: https://gitcode.com/GitHub_Trending/gr/graphhopper本指南围绕 GraphHopper 仓库中的client-hc模块client-hc/README.md系统讲解如何用 Java 或 Android 调用 GraphHopper Directions API 的路由Routing、矩阵Matrix、地理编码Geocoding等接口。读完本文你将掌握client-hc的 Maven 引入方式、Routing 与 Matrix API 的完整调用流程、关键配置参数与底层实现原理以及 Android 平台上的使用注意事项。为什么需要 client-hc手工客户端的设计动机client-hc是 GraphHopper 官方维护的手工编写hand-crafted的 API 客户端覆盖 Directions API 的多个组成部分例如 Matrix API 和 Routing API。与自动生成的autogenerated客户端相比手工客户端的主要优势是内存效率更高——例如在请求大型矩阵时它能显著减少内存占用这一点在 client-hc/README.md 中作为核心卖点被明确强调。从 pom.xml 可以看到该模块的 Maven 坐标为com.graphhopper:directions-api-client-hc版本与仓库根 POM 保持一致当前为12.0-SNAPSHOT它依赖graphhopper-web-api承载GHRequest、GHResponse、ResponsePath等公共数据模型以及 OkHttp 作为 HTTP 传输层。引入依赖要在你的 Maven 项目中引入client-hc请在pom.xml中加入如下依赖[CURRENT-VERSION]请替换为实际的发布版本号dependency groupIdcom.graphhopper/groupId artifactIddirections-api-client-hc/artifactId version[CURRENT-VERSION]/version /dependency从 pom.xml 可以看出该模块packaging为jar可直接作为普通 Java 库使用Android 项目同样可以通过标准依赖机制引入。Routing API用 GraphHopperWeb 规划路线Routing路径规划是client-hc最常用的能力核心入口类是GraphHopperWeb见 GraphHopperWeb.java。其无参构造默认指向https://graphhopper.com/api/1/route服务端点。完整示例仓库中的 Examples.java 提供了一个可直接运行的实战样例核心流程如下// Hint: create this thread safe instance only once in your application to allow the underlying library to cache the costly initial https handshake GraphHopperWeb gh new GraphHopperWeb(); // insert your key here gh.setKey(apiKey); // change timeout, default is 5 seconds gh.setDownloader(new OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(5, TimeUnit.SECONDS) .build()); // specify at least two coordinates GHRequest req new GHRequest(). addPoint(new GHPoint(49.6724, 11.3494)). addPoint(new GHPoint(49.6550, 11.4180)); // Set profile like car, bike, foot, ... req.setProfile(bike); // Optionally enable/disable elevation in output PointList, default is false req.putHint(elevation, false); // Optionally enable/disable turn instruction information, defaults is true req.putHint(instructions, true); // Optionally enable/disable path geometry information, default is true req.putHint(calc_points, true); // note: turn off instructions and calcPoints if you just need the distance or time // information to make calculation and transmission faster // Optionally set specific locale for instruction information, supports already over 25 languages, // defaults to English req.setLocale(Locale.GERMAN); // Optionally add path details req.setPathDetails(Arrays.asList( Parameters.Details.STREET_NAME, Parameters.Details.AVERAGE_SPEED, Parameters.Details.EDGE_ID )); GHResponse fullRes gh.route(req); if (fullRes.hasErrors()) throw new RuntimeException(fullRes.getErrors().toString()); // get best path (you will get more than one path here if you requested algorithmalternative_route) ResponsePath res fullRes.getBest(); // get path geometry information (latitude, longitude and optionally elevation) PointList pl res.getPoints(); // distance of the full path, in meter double distance res.getDistance(); // time of the full path, in milliseconds long millis res.getTime(); // get information per turn instruction InstructionList il res.getInstructions(); for (Instruction i : il) { // to get the translated turn instructions you call: // System.out.println(i.getTurnDescription(null)); // Note, that you can control the language only in via the request setLocale method and cannot change it only the client side } // get path details ListPathDetail pathDetails res.getPathDetails().get(Parameters.Details.STREET_NAME);关键参数说明参数默认值作用profile空出行方式如car、bike、foot等通过req.setProfile(...)设置elevationfalse是否在返回的PointList中包含海拔高程信息instructionstrue是否返回转向指令turn instructionscalc_pointstrue是否返回路径几何点若只需要距离或时间建议同时关闭 instructions 与 calcPoints以加快计算与传输locale英文指令语言支持 25 种以上语言通过req.setLocale(Locale.GERMAN)设置客户端级配置除了请求级参数GraphHopperWeb还提供客户端级设置方法源码见 GraphHopperWeb.javasetKey(String key)设置 API Key不允许为null或空字符串否则抛出异常setDownloader(OkHttpClient)自定义 HTTP 客户端默认连接与读取超时均为 5 秒setPostRequest(boolean)默认true使用POST /route设为false则改用GET /routesetCalcPoints(boolean)与setInstructions(boolean)客户端级开关请求级putHint会覆盖客户端默认值setElevation(boolean)客户端级高程开关setOptimize(String)传true时对途经点顺序按整体最优路线进行优化底层求解旅行商问题注意这类请求耗时更长、消耗更多额度setMaxUnzippedLength(int)控制请求体压缩策略默认 1000。一个值得注意的细节是POST 模式是默认选项源码中requestToJson会通过ObjectMapper将GHRequest序列化为 JSON 请求体坐标以[lon, lat]顺序写入并附带X-GH-Client-Version头便于服务端识别客户端版本而 GET 模式会把参数拼接到 URL 中。另外自定义模型CustomModel只能用于 POST 请求若在 GET 模式下携带 CustomModel 会直接抛出IllegalArgumentException。Matrix API用 GraphHopperMatrixWeb 计算点对矩阵矩阵 API 用于批量计算多个起终点之间的时间、距离或权重核心入口类是GraphHopperMatrixWeb见 GraphHopperMatrixWeb.java。同步请求小矩阵默认构造使用同步请求器GHMatrixSyncRequester适合中小规模矩阵。完整示例同样来自 Examples.java// Hint: create this thread safe instance only once in your application to allow the underlying library to cache the costly initial https handshake GraphHopperMatrixWeb matrixClient new GraphHopperMatrixWeb(); // for very large matrices you need: // GraphHopperMatrixWeb matrixClient new GraphHopperMatrixWeb(new GHMatrixBatchRequester()); matrixClient.setKey(apiKey); GHMRequest ghmRequest new GHMRequest(); ghmRequest.setOutArrays(Arrays.asList(distances, times)); ghmRequest.setProfile(car); // Option 1: init points for a symmetric matrix ListGHPoint allPoints Arrays.asList(new GHPoint(49.6724, 11.3494), new GHPoint(49.6550, 11.4180)); ghmRequest.setPoints(allPoints); MatrixResponse responseSymm matrixClient.route(ghmRequest); if (responseSymm.hasErrors()) throw new RuntimeException(responseSymm.getErrors().toString()); // get time from first to second point: // System.out.println(responseSymm.getTime(0, 1)); // Option 2: for an asymmetric matrix do: ghmRequest new GHMRequest(); ghmRequest.setOutArrays(Arrays.asList(distances, times)); ghmRequest.setProfile(car); ghmRequest.setFromPoints(Arrays.asList(new GHPoint(49.6724, 11.3494))); // or init e.g. a one-to-many matrix: ghmRequest.setToPoints(Arrays.asList(new GHPoint(49.6724, 11.3494), new GHPoint(49.6550, 11.4180))); MatrixResponse responseAsymm matrixClient.route(ghmRequest); if (responseAsymm.hasErrors()) throw new RuntimeException(responseAsymm.getErrors().toString()); // get time from first to second point: // System.out.println(responseAsymm.getTime(0, 1));请求模型 GHMRequest 的字段与约束从 GHMRequest.java 的源码可以看到setPoints(ListGHPoint)设置点集生成对称矩阵N×NsetFromPoints(...)/setToPoints(...)设置起/终点集生成非对称矩阵M×N也支持 one-to-many 形态setOutArrays(...)输出数组可选值包括weights、times、distancessetFailFast(boolean)默认false。为false时矩阵计算即使某些点不连通也会继续未连通的点对会被置为对应类型的最大值时间Long.MAX_VALUE、距离Double.MAX_VALUE、权重Double.MAX_VALUE同时不连通点对的索引会进入MatrixResponse.getDisconnectedPoints()无法解析的点进入getInvalidFromPoints()/getInvalidToPoints()setPointHints/setFromPointHints/setToPointHints/setCurbsides/setSnapPreventions精细化控制点吸附与路边停靠行为putHint(String, Object)通过JsonAnySetter把未知属性写入 hints 映射并随请求序列化。注意 GHMatrixAbstractRequester.java 中有明确的约束检查profile与fail_fast必须通过专用 setter 设置而不能放入 hintspoints与fromPoints/toPoints不能同时设置若只使用fromPoints则toPoints不能为null。若out_arrays中没有任何一种weights/distances/times能被解析客户端会返回 Cannot find usable entity like weights, distances or times in JSON 错误。响应模型 MatrixResponseMatrixResponse见 MatrixResponse.java是矩阵结果的统一载体getTime(from, to)返回from → to的耗时单位毫秒不连通时返回Long.MAX_VALUEgetDistance(from, to)返回距离单位米不连通时返回Double.MAX_VALUEgetWeight(from, to)返回任意单位的成本costsisConnected(from, to)便捷判断是否连通hasErrors()/getErrors()错误检查存在错误时读取数据会抛出IllegalStateExceptiongetHeader(key, default)读取响应头如速率限制信息x-ratelimit-remaininggetStatusCode()/getDisconnectedPoints()/getInvalidFromPoints()/getInvalidToPoints()状态码与问题点索引。另外MatrixResponse构造时会校验矩阵尺寸必须大于 0且times/distances/weights至少启用一种否则抛出异常。批量请求超大矩阵当矩阵规模很大时应切换到批量请求器GraphHopperMatrixWeb matrixClient new GraphHopperMatrixWeb(new GHMatrixBatchRequester());GHMatrixBatchRequester见 GHMatrixBatchRequester.java采用异步任务模式先POST /calculate提交任务获取job_id随后循环GET /solution/{id}轮询任务状态processing/waiting/finished每次轮询之间默认休眠 1000ms最多迭代 100 次。两个内部参数可调setMaxIterations(int)最大轮询次数仅在处理超大矩阵时需要增大setSleepAfterGET(long)轮询间隔毫秒数。遇到SocketTimeoutException时客户端会自动重试一次 GET。若轮询次数耗尽仍未完成会抛出 Maximum number of iterations reached 异常提示只有超大矩阵才需要调大该参数。其他 APIGeocoding、Route Optimization 与 Isochrone根据 client-hc/README.mdclient-hc可用于 Directions API 的多个组成部分Geocoding API入口类为GraphHopperGeocoding见 GraphHopperGeocoding.java默认服务端点为https://graphhopper.com/api/1/geocode。它同时支持正向地理编码地址 → 坐标与反向地理编码坐标 → 地址。请求通过 GHGeocodingRequest.java 构建提供new GHGeocodingRequest(String query, String locale, int limit)正向与new GHGeocodingRequest(GHPoint point, String locale, int limit)反向等便捷构造buildUrl方法会将reverse、q、point、limit、locale、provider、key拼进 URL。Routing API上文已详述的GraphHopperWeb。Matrix API上文已详述的GraphHopperMatrixWeb。Route Optimization API 与 Isochrone APIREADME 说明 Route Optimization API 的客户端源码由 GraphHopper 的 OpenAPI 规范自动生成在 directions-api-clients 仓库中该仓库标注有 deprecated noticeclient-hc本身不维护这部分。Android 使用注意事项client-hc可运行在 Android 平台但 README 给出了明确警告It is important to use this client not on the main thread of Android as it could block the app.即Android 上不要在主线程调用该客户端因为网络请求会阻塞 UI 线程并导致应用卡顿相关历史问题见 directions-api-java-client issue 7。正确的做法是把调用放到后台线程如协程、AsyncTask、线程池或 WorkManager中执行。Android 替代方案README 还提到OSM 社区维护的 OSMBonusPack 同样提供了 GraphHopper 的 Android 客户端实现它还支持在线地图瓦片并已被 Geopaparazzi、OSMNavigator 等项目实际采用。如果你需要与地图瓦片渲染深度集成的方案可以评估 OSMBonusPack如果你希望使用 GraphHopper 官方手工维护、内存更高效的客户端则直接使用client-hc。源码级深入请求链路与内部机制路由请求的两条通路GraphHopperWeb.route(GHRequest)是统一入口源码见 GraphHopperWeb.java。它根据postRequest标志二选一POST 通路createPostRequest将请求序列化为 JSONURL 上仅附带key参数请求头携带X-GH-Client-Version当请求体小于maxUnzippedLength默认 1000时显式声明Content-Encoding: identity避免不必要的 gzip 压缩GzipRequestInterceptor由默认的 OkHttpClient 构建时注入。GET 通路createGetRequest把profile、point、type、instructions、points_encodedtrue、points_encoded_multiplier1000000、calc_points、algorithm、locale、elevation、optimize以及 path details、point hints、curbsides、headings、snap preventions 等全部拼进 URL。GET 模式有一个内置校验开启 instructions 却关闭 calc_points 会抛出异常因为指令必须依赖几何点。响应解析使用ResponsePathDeserializerHelper.createResponsePath把 JSON 中的paths数组还原为多个ResponsePath当请求algorithmalternative_route时会返回多条备选路径并把响应头与 JSON 中的hints一并存入GHResponse方便读取限流等元信息。矩阵请求的两级模型矩阵请求采用门面 策略结构GraphHopperMatrixWeb是门面负责注入 API Key真正执行请求的是GHMatrixAbstractRequester的两个子类——同步的GHMatrixSyncRequester与批量的GHMatrixBatchRequester。这种设计让调用方可以透明地在两种执行策略间切换而无需改动业务代码。测试验证client-hc模块附带完整的单元测试。例如 GraphHopperWebTest.java 通过参数化测试同时验证 POST 与 GET 两种模式并断言生成的 GET URL 中profile、instructions、points_encoded等参数的拼接顺序与取值GHMatrixBatchTest、GHMatrixSyncTest见 client-hc/src/test/java/com/graphhopper/api则分别覆盖批量与同步矩阵请求器的行为。这些测试可用于验证你对客户端行为的理解是否符合预期。小结client-hc是 GraphHopper 官方为 Java 与 Android 开发者准备的高效 Directions API 客户端RoutingGraphHopperWebGHRequest支持 profile、高程、指令、路径详情、多语言等丰富配置MatrixGraphHopperMatrixWebGHMRequest支持对称/非对称矩阵、同步/批量两种执行策略以及fail_fast容错模式GeocodingGraphHopperGeocoding支持正反向地理编码Android避免主线程调用也可评估 OSMBonusPack 作为替代方案。无论是服务端 Java 应用还是 Android 客户端掌握本文的调用模式与源码行为即可快速、高效地接入 GraphHopper Directions API。进一步可参考仓库中的 Examples.java 与 client-hc/README.md 获取最新示例。【免费下载链接】graphhopperOpen source routing engine for OpenStreetMap. Use it as Java library or standalone web server.项目地址: https://gitcode.com/GitHub_Trending/gr/graphhopper创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表