Android Studio(Java)中如何加载MMPK内的路网数据实现路径规划?
Hey there! Let's walk through how to load that road network from your .mmpk and get it ready for routing in your Android Java app using ArcGIS Runtime SDK. I’ll break this down step by step based on what you’ve started with.
First, Confirm Your Setup
Make sure your project has the ArcGIS Runtime SDK for Android integrated. Add this dependency to your app-level build.gradle (use a compatible version for your project):
implementation 'com.esri.arcgisruntime:arcgis-android:100.15.0'
Step 1: Handle Required Permissions
You’ve started adding permissions, but you’ll need dynamic requests for storage (to read the .mmpk) and location (for routing with real-world positions). Add this code to your Activity:
private static final int PERMISSION_REQUEST_CODE = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Request necessary permissions if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_CODE); } else { // Permissions granted, start loading MMPK loadMobileMapPackage(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { loadMobileMapPackage(); } else { Toast.makeText(this, "Permissions are required to load the map and perform routing", Toast.LENGTH_SHORT).show(); } } }
Step 2: Load the Mobile Map Package (.mmpk)
First, copy the .mmpk from your assets folder to local storage (since assets files can’t be directly accessed by the SDK). Then load it and extract the embedded geodatabase:
private void loadMobileMapPackage() { // Define the path to store the MMPK locally String mmpkFilePath = getFilesDir() + "/your_road_map.mmpk"; File mmpkFile = new File(mmpkFilePath); // Copy MMPK from assets to local storage if it doesn't exist if (!mmpkFile.exists()) { try (InputStream is = getAssets().open("your_road_map.mmpk"); FileOutputStream fos = new FileOutputStream(mmpkFile)) { byte[] buffer = new byte[1024]; int length; while ((length = is.read(buffer)) > 0) { fos.write(buffer, 0, length); } } catch (IOException e) { Log.e("MMPK_LOAD", "Failed to copy MMPK from assets: " + e.getMessage()); return; } } // Load the MMPK asynchronously MobileMapPackage mobileMapPackage = new MobileMapPackage(mmpkFilePath); mobileMapPackage.addDoneLoadingListener(() -> { if (mobileMapPackage.getLoadStatus() == LoadStatus.LOADED) { Geodatabase geodatabase = mobileMapPackage.getGeodatabase(); if (geodatabase != null) { // Extract the road network dataset from the geodatabase extractRoadNetwork(geodatabase); } else { Log.e("MMPK_LOAD", "No geodatabase found in the MMPK"); } } else { Log.e("MMPK_LOAD", "Failed to load MMPK: " + mobileMapPackage.getLoadError().getMessage()); } }); mobileMapPackage.loadAsync(); }
Step 3: Extract the Road Network & Prepare Routing
Your MMPK’s geodatabase should contain either a network dataset (optimized for routing) or a feature class with road attributes. Here’s how to access it and set up route analysis:
private void extractRoadNetwork(Geodatabase geodatabase) { // Replace "RoadNetworkDataset" with your actual network dataset name String targetDatasetName = "RoadNetworkDataset"; for (GeodatabaseDataset dataset : geodatabase.getGeodatasets()) { if (dataset.getName().equals(targetDatasetName)) { if (dataset instanceof NetworkDataset) { NetworkDataset roadNetwork = (NetworkDataset) dataset; // Initialize RouteTask with the network dataset setupRoutingWithNetworkDataset(roadNetwork); break; } else if (dataset instanceof FeatureDataset) { // Fallback: Use a road feature class if no network dataset exists FeatureDataset roadFeatureDataset = (FeatureDataset) dataset; FeatureClass roadFeatureClass = roadFeatureDataset.getFeatureClass(); ArcGISFeatureTable roadTable = new GeodatabaseFeatureTable(roadFeatureClass); setupRoutingWithFeatureTable(roadTable); break; } } } } // For routing with a pre-built network dataset (recommended) private void setupRoutingWithNetworkDataset(NetworkDataset networkDataset) { RouteTask routeTask = RouteTask.createWithNetworkDataset(networkDataset); routeTask.addDoneLoadingListener(() -> { if (routeTask.getLoadStatus() == LoadStatus.LOADED) { // Get default routing parameters routeTask.createDefaultParametersAsync().addDoneListener(() -> { RouteParameters params = routeTask.createDefaultParametersAsync().getResult(); if (params != null) { // Set your start/end points (replace with actual coordinates or user location) Point start = new Point(-118.2437, 34.0522, SpatialReferences.getWgs84()); Point end = new Point(-118.2455, 34.0545, SpatialReferences.getWgs84()); params.setStops(new ArrayList<>(Arrays.asList( new Graphic(start), new Graphic(end) ))); // Solve the route routeTask.solveAsync(params).addDoneListener(() -> { RouteResult result = routeTask.solveAsync(params).getResult(); if (result != null && !result.getRoutes().isEmpty()) { Route route = result.getRoutes().get(0); Log.d("ROUTING", "Route found! Total length: " + route.getTotalLength()); // Add the route graphic to your map view here // mapView.getGraphicsOverlay().getGraphics().add(new Graphic(route.getRouteGeometry())); } else { Log.e("ROUTING", "No valid route found between points"); } }); } }); } else { Log.e("ROUTE_TASK", "Failed to load RouteTask: " + routeTask.getLoadError().getMessage()); } }); routeTask.loadAsync(); } // Fallback for routing with a basic road feature class private void setupRoutingWithFeatureTable(ArcGISFeatureTable roadTable) { RouteTask routeTask = RouteTask.createWithFeatureTable(roadTable); // Follow similar steps as above to set parameters and solve the route }
Key Notes to Remember
- Network Dataset vs. Feature Class: A network dataset is purpose-built for routing (includes turn restrictions, impedance values like time/distance) — use this if your MMPK has one. If not, ensure your road feature class has attributes like length or speed to calculate routes.
- Map View Integration: Don’t forget to add a
MapViewto your layout and load the map from the MMPK if you want to visualize the route. - Error Handling: Add more robust error handling for edge cases (e.g., MMPK file corruption, invalid network dataset).
内容的提问来源于stack exchange,提问作者Wing Sze Li

