Only the first placemark of KML files being rendered

997
3
04-21-2019 02:26 PM
LunaariPeterson
New Contributor

I've spent way too long on this to not seek help. I'm retrieving KML files from SPC Shapefile/KML Links. Every time I draw these files, only the geometry held within the first placemark of the file is added to the KML layer. For reference, these KML files have the following structure:

   Document / Folder (one or two) / Placemarks (multiple)

This is frustrating because through some exploration, I can find the geometry from each KML placemark at the android runtime, but I still can't plot it as a layer. It is also important to note that the first placemark of all the root folders will be drawn. So if there are 2 folders each containing 5 placemarks, I'll get 2 layers added, not 10 like I would prefer.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        //SetLicense removed for privacy        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        mMapView = findViewById(R.id.mapView);
        setupMap();

        Button outlookButton = findViewById(R.id.otlkBtn);

        outlookButton.setOnClickListener(v -> {
            getKmlData("https://www.spc.noaa.gov/products/outlook/day1otlk_cat.kml");

        });
    }

    private void setupMap() {
        if (mMapView != null) {
            // Get Map Style
            String myLayerId = "9b7f5bb66660427eae788a0a9097c8a8";
            Portal portalService = new Portal("https://www.arcgis.com", false);
            PortalItem portalItemLayer = new PortalItem(portalService, myLayerId);

            ArcGISVectorTiledLayer myCustomTileLayer = new 
            ArcGISVectorTiledLayer(portalItemLayer);
            ArcGISMap map = new ArcGISMap(new Basemap(myCustomTileLayer));
            mMapView.setMap(map);
            mMapView.setAttributionTextVisible(false);
            setupLocationDisplay();
        }
    }


    private void getKmlData(String url) {
        KmlDataset kmlDataset = new KmlDataset(url);
        KmlLayer kmlLayer = new KmlLayer(kmlDataset);
        
        //
        for (KmlNode node : kmlDataset.getRootNodes()) {
            for (KmlNode subnode : ((KmlDocument) node).getChildNodes()) {
                if(subnode instanceof KmlFolder) {
                    for (KmlNode subsubnode : ((KmlFolder) subnode).getChildNodes()) {
                        subsubnode.setVisible(true);
                        if (subsubnode instanceof KmlPlacemark) {
                            System.out.println(subsubnode.getSnippet());
                            System.out.println(subsubnode.getName());
                            subsubnode.setVisible(true);
                            mMapView.getMap().getOperationalLayers().add(KmlLayer);
                        }
                    }
                }
            }
        }
        mMapView.getMap().getOperationalLayers().add(kmlLayer);
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The result is this:

When the desired output should look like this:

As you can see, only the Marginal Risk layer is drawn. The data for the Marginal Risk layer is held in the first placemark in the following file. The General Thunderstorm data is the larger polygon and is contained in the second placemark.

Any help would be greatly appreciated. I've switched back and forth between several APIs regarding this anomaly.

0 Kudos
3 Replies
ChanganShi
Esri Contributor

We are investigating the issue you reported, Thanks.

Could you give a test, manually download the KML data, put somewhere on your device, then create the KmlLayer from the local path, like

getKmlData("/mnt/sdcard/kmldata/day1otlk_cat.kml");

In the function, only add the KmlLayer once : 

private void getKmlData(String url) {
  KmlDataset kmlDataset = new KmlDataset(url);
  final KmlLayer kmlLayer = new KmlLayer(kmlDataset);

  kmlLayer.addDoneLoadingListener(()-> {
    if (kmlLayer.getLoadStatus() == LoadStatus.LOADED) {
      mMapView.getMap().getOperationalLayers().add(kmlLayer);
    }
    Log.d("KML", "loading status:"+kmlLayer.getLoadStatus());
  });
}
LunaariPeterson
New Contributor

So I've tried waiting until the KML is loaded before, sorry I forgot to mention that in the OP. The addDoneLoadingListener doesn't fire unless I add the kmlLayer to the mMapView.getMap() first. I added a log event after

final KmlLayer kmlLayer = new KmlLayer(kmlDataset);

and here's the Log that was generated: (Note im also logging the kml file directory for my own sanity)

2019-04-25 20:25:46.443 6713-6713/com.example.spvis D/KML: getKmlDataNew triggered
2019-04-25 20:25:46.452 6713-6713/com.example.spvis D/KML: /storage/emulated/0/kmldata/day1otlk_cat.kml

The following log occurs after I put 

mMapView.getMap().getOperationalLayers().add(kmlLayer);

before the loading listener.

2019-04-25 20:28:58.427 6713-6713/com.example.spvis D/KML: getKmlDataNew triggered
2019-04-25 20:28:58.434 6713-6713/com.example.spvis D/KML: /storage/emulated/0/kmldata/day1otlk_cat.kml
2019-04-25 20:28:58.492 6713-6713/com.example.spvis D/KML: loading status:FAILED_TO_LOAD

I hope this helps. Let me know if you want me to do anything else. I'm willing to upload files if that's what it takes to get this issue fixed. I've resorted to parsing the NOAA WUUS01 strings off of their website in the meantime.

Cheers!

0 Kudos
ChanganShi
Esri Contributor

Could you print out the error message why the layer fails to load by :

mKmlLayer.getLoadError().getMessage()

Also What's the version of your SDK?

Could you try to update the file, create the KmlLayer from the local data path? I think it makes a difference. Your issue is still under investigation

0 Kudos