如何基于OSMBonusPack集成Graphhopper路由优化API实现路径规划?
Hey there! I’ve worked through this exact integration before, so let’s break down how to get GraphHopper working with OSMBonusPack’s RoadManager properly. This will cover multi-point shortest paths and lay the groundwork for your future time-aware routing needs.
Step 1: Add Required Dependencies
First, make sure your project includes compatible dependencies. In your app-level build.gradle (or build.gradle.kts), add these lines (adjust versions to match your project’s osmdroid/OSMBonusPack setup):
// OSMDroid & OSMBonusPack implementation 'org.osmdroid:osmdroid-android:6.1.18' implementation 'com.github.MKergall:osmbonuspack:6.9.0' // GraphHopper Core (for offline/local routing) implementation 'com.graphhopper:graphhopper-core:7.0.0' // GraphHopper Android utilities implementation 'com.graphhopper:graphhopper-android:7.0.0' // For GraphHopper Cloud API (skip if using local routing) implementation 'com.graphhopper:graphhopper-web-api-client:7.0.0'
Step 2: Initialize GraphHopperRoadManager
OSMBonusPack provides a GraphHopperRoadManager wrapper that ties directly into GraphHopper’s routing logic. You have two setup options:
Option A: GraphHopper Cloud API (Easier for Prototyping)
If using the hosted cloud service, grab a free API key from GraphHopper first, then initialize the manager:
String graphHopperApiKey = "YOUR_PERSONAL_API_KEY"; String routingProfile = "car"; // Options: bike, foot, etc. GraphHopperRoadManager roadManager = new GraphHopperRoadManager(context, graphHopperApiKey); roadManager.setProfile(routingProfile);
Option B: Local/Offline Routing (For Offline Use Cases)
For offline routing, download an OSM PBF file (e.g., from Geofabrik) and place it in your app’s storage. Then initialize a local GraphHopper instance and attach it to the RoadManager:
// Path to your local OSM PBF file String osmFilePath = getFilesDir() + "/your-region.osm.pbf"; // Directory to store processed GraphHopper data String graphDir = getFilesDir() + "/graphhopper-cache"; // Initialize local GraphHopper instance GraphHopper hopper = new GraphHopper(); hopper.setOSMFile(osmFilePath); hopper.setGraphHopperLocation(graphDir); // Set up your routing profile (e.g., car with fastest weighting) hopper.setProfiles(new Profile(routingProfile).setVehicle("car").setWeighting("fastest")); // IMPORTANT: Run graph import/load on a background thread to avoid ANRs new AsyncTask<Void, Void, GraphHopper>() { @Override protected GraphHopper doInBackground(Void... voids) { hopper.importOrLoad(); return hopper; } @Override protected void onPostExecute(GraphHopper loadedHopper) { // Attach to OSMBonusPack's RoadManager once loaded GraphHopperRoadManager roadManager = new GraphHopperRoadManager(context, loadedHopper); // Proceed with routing requests here } }.execute();
Step 3: Request Multi-Point Shortest Path
Once your RoadManager is ready, collect your waypoints as GeoPoints and request the path. Always run routing on a background thread:
// Example list of waypoints (start → intermediates → end) List<GeoPoint> waypoints = new ArrayList<>(); waypoints.add(new GeoPoint(51.5074, -0.1278)); // London waypoints.add(new GeoPoint(52.5200, 13.4050)); // Berlin waypoints.add(new GeoPoint(48.8566, 2.3522)); // Paris new AsyncTask<Void, Void, Road>() { @Override protected Road doInBackground(Void... voids) { // Request multi-point path—GraphHopper handles the shortest path logic automatically return roadManager.getRoad(waypoints); } @Override protected void onPostExecute(Road road) { if (road.getStatus() == Road.STATUS_OK) { processAndDisplayRoute(road); } else { Toast.makeText(context, "Routing failed: " + road.getStatusMessage(), Toast.LENGTH_SHORT).show(); } } }.execute();
Step 4: Display the Route on Your Map
Use OSMBonusPack’s PolylineOverlay to render the path on your osmdroid map:
private void processAndDisplayRoute(Road road) { // Create a polyline overlay for the route PolylineOverlay routeOverlay = new PolylineOverlay(getResources().getColor(R.color.route_blue), 5, context); // Extract high-precision path points from the Road object ArrayList<GeoPoint> routePoints = road.getRouteHigh(); routeOverlay.setPoints(routePoints); // Add overlay to map and refresh map.getOverlays().add(routeOverlay); map.invalidate(); // Extract additional route details double totalDistanceKm = road.getLength() / 1000; long totalTimeMins = road.getDuration() / 60; Log.d("RouteInfo", String.format("Total: %.1fkm | %d mins", totalDistanceKm, totalTimeMins)); }
Prepping for Time-Aware Routing
GraphHopper supports time-dependent routing (traffic, time-of-day considerations) which aligns with your future needs:
- Cloud API: Add departure time parameters using
roadManager.addRequestOption("departure_time", "2024-06-01T08:30:00Z")(ISO 8601 format). - Local Routing: Use a time-aware weighting (e.g.,
setWeighting("traffic")) and ensure your OSM data includes traffic-related tags, or integrate a custom time-based edge weight dataset.
Common Pitfalls to Avoid
- Version Compatibility: Double-check that OSMBonusPack, osmdroid, and GraphHopper versions are compatible (refer to their GitHub repos for notes).
- Permissions: Add
<uses-permission android:name="android.permission.INTERNET"/>for cloud routing, and storage permissions for offline OSM files. - Background Threads: Never run graph import or routing on the main UI thread—always use async tasks, coroutines, or work managers.
内容的提问来源于stack exchange,提问作者user_9

