使用ArcGIS创建离线地图(.mmpk地图)

3
我的目标是创建一个安卓应用程序,当连接到互联网时从ArcGIS门户下载地图,然后进行离线使用。我想使用服务模式,这样应用程序以后就可以拥有同步功能。我按照ArcGIS的教程(点击此处)进行操作。
我目前遇到了下载地图的难题。我期望下载的地图文件是移动地图包(.mmpk),但实际上我的下载目录中包含一个package.info文件和一个包含geodatabase和.mmap文件的文件夹,如所示。根据我的理解,我需要一个.mmpk文件才能进行离线使用。
在按照教程步骤操作时,我成功完成了(1)创建离线地图任务(2)指定参数(3)检查离线功能。但是在第(4)生成并下载离线地图步骤中,我期望下载的地图文件将是移动地图包(.mmpk),但实际情况却不是这样的。在第(5)打开和使用离线地图步骤中,我能够查看手动传输到设备上的移动地图包(.mmpk)文件的离线地图。我也试图打开并使用下载的(.mmap)文件,但没有地图显示出来。
我的完整代码按步骤如下所示: (1)创建离线地图任务
    // Load map from a portal item
    final Portal portal = new Portal("http://www.arcgis.com");
    final PortalItem webmapItem = new PortalItem(portal, "acc027394bc84c2fb04d1ed317aac674");

    // Create map and add it to the view
    myMap = new ArcGISMap(webmapItem);
    mMapView = (MapView) findViewById(R.id.mapView);
    mMapView.setMap(myMap);

    // Create task and set parameters
    final OfflineMapTask offlineMapTask = new OfflineMapTask(myMap);

(2) 指定参数

    // Create default parameters
    final ListenableFuture<GenerateOfflineMapParameters> parametersFuture = offlineMapTask.createDefaultGenerateOfflineMapParametersAsync(areaOfInterest);
    parametersFuture.addDoneListener(new Runnable() {
        @Override
        public void run() {
            try {
                final GenerateOfflineMapParameters parameters = parametersFuture.get();

                // Update the parameters if needed
                // Limit maximum scale to 5000 but take all the scales above (use 0 as a MinScale)
                parameters.setMaxScale(5000);

                parameters.setIncludeBasemap(false);

                // Set attachment options
                parameters.setAttachmentSyncDirection(GenerateGeodatabaseParameters.AttachmentSyncDirection.UPLOAD);
                parameters.setReturnLayerAttachmentOption(GenerateOfflineMapParameters.ReturnLayerAttachmentOption.EDITABLE_LAYERS);

                // Request the table schema only (existing features won't be included)
                parameters.setReturnSchemaOnlyForEditableLayers(true);

                // Update the title to contain the region
                parameters.getItemInfo().setTitle(parameters.getItemInfo().getTitle() + " (Central)");

                // Create new item info
                final OfflineMapItemInfo itemInfo = new OfflineMapItemInfo();

                // Override thumbnail with the new image based on the extent
                final ListenableFuture<Bitmap> exportImageFuture = mMapView.exportImageAsync();
                exportImageFuture.addDoneListener(new Runnable() {
                    @Override
                    public void run() {
                        try {

                            Bitmap mapImage = exportImageFuture.get();
                            // Scale to thumbnail size
                            Bitmap thumbnailImage = Bitmap.createScaledBitmap(mapImage, 200, 133, false);
                            // Convert to byte[]
                            ByteArrayOutputStream stream = new ByteArrayOutputStream();
                            thumbnailImage.compress(Bitmap.CompressFormat.JPEG, 50, stream);
                            byte[] thumbnailBytes = stream.toByteArray();
                            stream.close();

                            // Set values to the itemInfo
                            itemInfo.setThumbnailData(thumbnailBytes);
                            itemInfo.setTitle("Water network (Central)");
                            itemInfo.setSnippet(webmapItem.getSnippet()); // Copy from the source map
                            itemInfo.setDescription(webmapItem.getDescription()); // Copy from the source map
                            itemInfo.setAccessInformation(webmapItem.getAccessInformation()); // Copy from the source map
                            itemInfo.getTags().add("Water network");
                            itemInfo.getTags().add("Data validation");

                            // Set metadata to parameters
                            parameters.setItemInfo(itemInfo);

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });

(3)检查离线功能



                final ListenableFuture<OfflineMapCapabilities> offlineMapCapabilitiesFuture =
                        offlineMapTask.getOfflineMapCapabilitiesAsync(parameters);
                offlineMapCapabilitiesFuture.addDoneListener(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            OfflineMapCapabilities offlineMapCapabilities = offlineMapCapabilitiesFuture.get();
                            if (offlineMapCapabilities.hasErrors()) {
                                // Handle possible errors with layers
                                for (java.util.Map.Entry<Layer, OfflineCapability> layerCapability :
                                        offlineMapCapabilities.getLayerCapabilities().entrySet()) {
                                    if (!layerCapability.getValue().isSupportsOffline()) {
                                        showMessage(layerCapability.getKey().getName() + " cannot be taken offline.");
                                        showMessage("Error : " + layerCapability.getValue().getError().getMessage());
                                    }
                                }

                                // Handle possible errors with tables
                                for (java.util.Map.Entry<FeatureTable, OfflineCapability> tableCapability :
                                        offlineMapCapabilities.getTableCapabilities().entrySet()) {
                                    if (!tableCapability.getValue().isSupportsOffline()) {
                                        showMessage(tableCapability.getKey().getTableName() + " cannot be taken offline.");
                                        showMessage("Error : " + tableCapability.getValue().getError().getMessage());
                                    }
                                }
                            } else {
                                // All layers and tables can be taken offline!
                                showMessage("All layers are good to go!");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });

生成并下载离线地图。
                String mExportPath = String.valueOf(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)) + File.separator + "New";
                showMessage(mExportPath);

                // Create and start a job to generate the offline map
                final GenerateOfflineMapJob generateOfflineJob =
                        offlineMapTask.generateOfflineMap(parameters, mExportPath);

                // Show that job started
                final ProgressBar progressBarOffline = (ProgressBar) findViewById(R.id.progressBarOffline);
                progressBarOffline.setVisibility(View.VISIBLE);

                generateOfflineJob.start();
                generateOfflineJob.addJobDoneListener(new Runnable() {
                    @Override
                    public void run() {

                        // Generate the offline map and download it
                        GenerateOfflineMapResult result = generateOfflineJob.getResult();

                        if (!result.hasErrors()) {

                            showMessage("no error");
                            mobileMapPackage = result.getMobileMapPackage();
                            // Job is finished and all content was generated
                            showMessage("Map " + mobileMapPackage.getItem().getTitle() +
                                    " saved to " + mobileMapPackage.getPath());

                            // Show offline map in a MapView
                            mMapView.setMap(result.getOfflineMap());

                            // Show that job completed
                            progressBarOffline.setVisibility(View.INVISIBLE);
                        } else {

                            showMessage("error");
                            // Job is finished but some of the layers/tables had errors
                            if (result.getLayerErrors().size() > 0) {
                                for (java.util.Map.Entry<Layer, ArcGISRuntimeException> layerError : result.getLayerErrors().entrySet()) {
                                    showMessage("Error occurred when taking " + layerError.getKey().getName() + " offline.");
                                    showMessage("Error : " + layerError.getValue().getMessage());
                                }
                            }
                            if (result.getTableErrors().size() > 0) {
                                for (java.util.Map.Entry<FeatureTable, ArcGISRuntimeException> tableError : result.getTableErrors().entrySet()) {
                                    showMessage("Error occurred when taking " + tableError.getKey().getTableName() + " offline.");
                                    showMessage("Error : " + tableError.getValue().getMessage());
                                }
                            }
                            // Show that job completed
                            progressBarOffline.setVisibility(View.INVISIBLE);
                        }
                    }
                });

(5) 打开并使用离线地图

// Create the mobile map package
    final MobileMapPackage mapPackage = new MobileMapPackage(mobileMapPackage.getPath());
    // Load the mobile map package asynchronously
    mapPackage.loadAsync();

    // Add done listener which will invoke when mobile map package has loaded
    mapPackage.addDoneLoadingListener(new Runnable() {
        @Override
        public void run() {
            // Check load status and that the mobile map package has maps
            if(mapPackage.getLoadStatus() == LoadStatus.LOADED && mapPackage.getMaps().size() > 0){
                // Cdd the map from the mobile map package to the MapView
                mMapView.setMap(mapPackage.getMaps().get(0));
            }else{
                // Log an issue if the mobile map package fails to load
                showMessage(mapPackage.getLoadError().getMessage());
            }
        }
    });

我的代码中的showMessage()显示Toast。

public void showMessage(String message) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}

我担心我的.mmpk的期望值是错误的,或者在某个步骤上出现了错误,因为我仍然没有完全理解整个过程。这是我第一次在Android中使用ArcGIS地图。我找不到太多可以尝试的示例代码,所以非常感谢能够帮忙的人。
谢谢!
2个回答

2
该任务创建了一个已解压的移动地图包,其工作方式与.mmpk文件相同。打开它的方式如下:

final MobileMapPackage mapPackage = new MobileMapPackage("/data/com.geoinfo.asmasyakirah.arcgis/files/Documents/New");

(如果您无法在那里访问它,则可能需要在Environment.getExternalStorageDirectory()而不是Environment.DIRECTORY_DOCUMENTS中生成移动地图包。)

根据MobileMapPackage构造函数的文档

从给定路径创建一个新的MobileMapPackage,该路径包含.mmpk文件或已解压的移动地图包

如果您确实需要将其作为.mmpk文件使用,请使用Android API制作zip文件并将其命名为.mmpk,而不是.zip。


谢谢,您提供的“爆炸式移动地图包”描述帮助我理解了我正在正确的道路上(哈哈)以获得所需的输出。我将来可能会使用它。在收到您的答案之前,我尝试了其他替代方法;下载并使用.geodatabase文件。好事是它可以工作。只是在指定参数时决定Envelope(感兴趣的区域)时出现了一些错误,导致我的图层在下载后不可见。现在已经修复了。对于我的mmpk部分,我尝试压缩下载的文件并将其重命名为.mmpk。我可以读取地图,但图层是不可见的。很快会再次尝试,谢谢! - asmasyakirah

0

虽然有点晚了,但我花了几天时间研究了这个问题,并发现了一些可能对你们有帮助的东西:

我通过这个类创建了我的mapData:https://github.com/Esri/arcgis-runtime-samples-java/blob/master/src/main/java/com/esri/samples/map/generate_offline_map/GenerateOfflineMapSample.java

正如你所看到的,它创建了一个包含package.info和p13(其中包含geodatabase文件和mmap文件)的文件夹。

当我尝试离线加载这些数据时,没有出现任何错误,但图层是空的,我只能看到地图上的卡车。

实际上,在更多的尝试之后,我不得不检查除了geodatabase和mmap文件之外,是否可以找到.tpk文件(TilePackaged)

这个文件从来没有出现过(可能是由于在线下载期间的网络问题),也没有任何警告。

现在有了这个tpk文件,所有的项目都清晰地显示出来,比如“水网”。

简而言之:请检查在线准备过程中是否已经下载了tpk文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接