Loading of more Than one mmpk file for single screen

1060
7
02-02-2020 07:39 AM
anshushrivastava
New Contributor II

Hello,

        I want to know how we can load more than one mmpk file for a single screen.Right now I am using this c++ in qt Creator 5.12.0 and ARCGIS 100.4 on RHEL 7.6.Go through this code if i am doing any mistake then please correct.

path1 = "/home/Gis/ChartEngine/Arcgis/Runtime/Data/MMpk/India.mmpk";
path2 = "/home/Gis/ChartEngine/Arcgis/Runtime/Data/MMpk/Pak.mmpk";
MobileMapPackage *m_mobileMapPackage1 = new MobileMapPackage(path1, this);
  connect(m_mobileMapPackage1, &MobileMapPackage::doneLoading, this, [this](Error error)   {    m_mapView->setMap(m_mobileMapPackage1->maps().at(0));    });
MobileMapPackage *m_mobileMapPackage2 = new MobileMapPackage(path1, this); 
  connect(m_mobileMapPackage2, &MobileMapPackage::doneLoading, this, [this](Error error)   {    m_mapView->setMap(m_mobileMapPackage2->maps().at(0));    });
m_mobileMapPackage->load();
m_mobileMapPackage2->load();

So when screen is coming , whatever is getting loaded last that one is only getting shown in screen.

My project requirement :-

I have to show india and pak in a single view by using mmpk file.Aditya PeriAlexandra GajewskiAndrew RossAllen ThompsonRebecca McKinleyJon Fiskness Hilary LeavellHuailin wangArcGIS IdeasException rendering offline FeatureLayerquery on ShapefileFeatureTable

0 Kudos
7 Replies
JamesBallard1
Esri Regular Contributor

Hi anshu shrivastava‌,

    Each MapView has only one Map. The preferable solution here would be to author the data so that all the operational layers and data are within the same Map to begin with, and then to load that Map into the MapView.

Are you able to re-author the data?

anshushrivastava
New Contributor II

Hi ,

    Thank you for reply , I am not able to re-author the data .It will be very appreciable if you can provide some example code ,for loading more than one mmpk file for single mapview.

0 Kudos
anshushrivastava
New Contributor II

Hi ,

    Thank you for reply , I am not able to re-author the data .It will be very appreciable if you can provide some example code ,for loading more than one mmpk file for single mapview.

0 Kudos
JamesBallard1
Esri Regular Contributor

anshu shrivastava‌,

   Ok, in that case there are a few options. I must say, this is not ideal as the Map should contain all its respective data and layers to begin with.

Option 1: unpack the mmpk to disk and create all the layers programmatically. When you unpack the mobile map package, it will (or may) contains tpk and possibly geodatabase files that can be used to load and create all the layers from those files.

MobileMapPackage Class | ArcGIS for Developers 

Option 2: "take" the layers from one map and place them in the other map. This will only work if one of the maps is destroyed. In this case, you will load both mobile map packages like in your sample, but for one of the maps you will change the workflow as follows:

path1 = "/home/Gis/ChartEngine/Arcgis/Runtime/Data/MMpk/India.mmpk";
path2 = "/home/Gis/ChartEngine/Arcgis/Runtime/Data/MMpk/Pak.mmpk";

MobileMapPackage *m_mobileMapPackage1 = new MobileMapPackage(path1, this); 
  connect(m_mobileMapPackage1, &MobileMapPackage::doneLoading, this, [this](Error)   {    
  m_mapView->setMap(m_mobileMapPackage1->maps().at(0));
  m_mobileMapPackage2->load();
});

MobileMapPackage *m_mobileMapPackage2 = new MobileMapPackage(path1, this); 
  connect(m_mobileMapPackage2, &MobileMapPackage::doneLoading, this, [this](Error)   {    
  auto* map2 = m_mobileMapPackage2->maps().at(0));
  QList<Layer*> layersFromMap2;
  for (auto* layerFromMap2 : *(map2->operationalLayers()))
  {
    layersFromMap2.append(layerFromMap2);
    layerFromMap2->setParent(this); // re-parent the layers
  }

  // delete the map
  delete map2;
  
  // add all the layers to the mapView's map
  auto* operationalLayers = m_mapView->map()->operationalLayers();
  for (auto* layer : layersFromMap2)
    operationalLayers->append(layer);
});

m_mobileMapPackage->load();

This is pseudo code and may have some errors, but this is the general workflow. Please let us know if this works.

In both cases, the ordering of the layers may not be preserved properly so you may need to adjust which order the layers are added in.

anshushrivastava
New Contributor II

Hi James ,

           We tried this pseudo code but still we are not able to load two mmpk data for single screen.Please go through this code if i am doing any mistak

void CTacticalViewClass::LoadingOfmmpkfile(const QUrl &file,const QUrl &file2)
{
    QString dataPath = file.toString();
    QString dataPath2 = file2.toString();

    m_mobileMapPackage = new MobileMapPackage(dataPath, this);
    m_mobileMapPackage1 = new MobileMapPackage(dataPath2, this);

    connect(m_mobileMapPackage, &MobileMapPackage::doneLoading, this, [this](Error error)
    {
        if (error.isEmpty())
        {
            m_mapView->setMap(m_mobileMapPackage->maps().at(0));
            qDebug()<<"m_mapView->map()->operationalLayers()"<<m_mapView->map()->operationalLayers()->size()<<m_mobileMapPackage->maps().at(0)->operationalLayers()->size();
            m_mobileMapPackage1->load();
        }
    });
/*
 * tried but not working completely
    connect(m_mobileMapPackage1, &MobileMapPackage::doneLoading, this, [this](Error)   {

        auto* map2 = m_mobileMapPackage1->maps().at(0);
        qDebug()<<"Operational layer count ------>>"<<m_mobileMapPackage1->maps().at(0)->operationalLayers()->size()<<"map2"<<map2->operationalLayers()->size();

        QList<Layer*> layersFromMap2;
        LayerListModel* layerFromMap2;
        for (int i = 0;i<m_mobileMapPackage1->maps().at(0)->operationalLayers()->size();i++)
        {
            qDebug()<<"i - "<<i;
            layersFromMap2.append(m_mobileMapPackage1->maps().at(0)->operationalLayers()->at(i));
            layerFromMap2 = map2->operationalLayers();
            layerFromMap2->setParent(this); // re-parent the layers
        }
         qDebug()<<"layersFromMap2"<<layersFromMap2.size()<<"layerFromMap2 "<<layerFromMap2->size();
        // delete the map
              delete map2;

        //      // add all the layers to the mapView's map
         for (int i = 0;i<layersFromMap2.size();i++)
         {
             m_mapView->map()->operationalLayers()->append(layersFromMap2.at(i));
             qDebug()<<"operationalLayers "<<m_mapView->map()->operationalLayers()->size();

         }
              auto* operationalLayers = m_mapView->map()->operationalLayers();

              for (auto* layer : layersFromMap2)
                operationalLayers->append(layer);
              qDebug()<<"total layers "<<operationalLayers->size();
    });

0 Kudos
JamesBallard1
Esri Regular Contributor

anshu shrivastava‌,

   Unfortunately the team cannot help with debugging, but I can outline the workflow without code to indicate how it should be working.

1. Load both mmpk files.

2. Set the first mmpk's Map to the MapView.

3. For the second one, pull the layers out of the map and store them locally.

4. Re-parent the layers (very important) - without this step they will get deleted with the map they came from.

5. Delete the second map - this should free up the layers to be displayed in a different map. Layers cannot be part of two different maps at the same time - this is why the second map must be deleted.

6. Add the set of layers to the MapView's map (which is from the first mmpk loaded).

It does look like your code is following this pattern, but double check you've not missed something minor along the way.

Another potential solution (and I use that phrase loosely), is that the Map object is JsonSerializable. You could call map->toJson() to get the serialized text of each map. Within the text it will contain an operationalLayers tag with the serialized data for all the layers. You could use this information to build up a map from the first map's Json, but with the second map's operationalLayers text added to it. With that serialized data string, you could create a map from json, see Map::fromJson.

operationalLayers | ArcGIS for Developers 

Map Class | ArcGIS for Developers 

Let us know if this helps.

anshushrivastava
New Contributor II

Hi James ,

           We tried this pseudo code but still we are not able to load two mmpk data for single screen.Go through this code if i am doing any

mistak, Please inform.

path1 = "/home/Gis/ChartEngine/Arcgis/Runtime/Data/MMpk/India.mmpk";
path2 = "/home/Gis/ChartEngine/Arcgis/Runtime/Data/MMpk/Pak.mmpk";

void CTacticalViewClass::LoadingOfmmpkfile(const QUrl &file,const QUrl &file2)
{
    QString dataPath = file.toString();
    QString dataPath2 = file2.toString();

 

    m_mobileMapPackage = new MobileMapPackage(dataPath, this);
    m_mobileMapPackage1 = new MobileMapPackage(dataPath2, this);

 

    connect(m_mobileMapPackage, &MobileMapPackage::doneLoading, this, [this](Error error)
    {
        if (error.isEmpty())
        {
            m_mapView->setMap(m_mobileMapPackage->maps().at(0));
            m_mobileMapPackage1->load();
        }
    });
    connect(m_mobileMapPackage1, &MobileMapPackage::doneLoading, this, [this](Error)   {

 

        auto* map2 = m_mobileMapPackage1->maps().at(0);
        qDebug()<<"Operational layer count ------>>"<<m_mobileMapPackage1->maps().at(0)->operationalLayers()->size()<<"map2"<<map2->operationalLayers()->size();//here 3 operational layer is coming

 

        QList<Layer*> layersFromMap2;

//***** We made changes in for loop because we were getting error in for loop
        LayerListModel* layerFromMap2;
        for (int i = 0;i<m_mobileMapPackage1->maps().at(0)->operationalLayers()->size();i++)
        {

            layersFromMap2.append(m_mobileMapPackage1->maps().at(0)->operationalLayers()->at(i));
            layerFromMap2 = map2->operationalLayers();
            layerFromMap2->setParent(this); // re-parent the layers
        }
         qDebug()<<"layersFromMap2"<<layersFromMap2.size()<<"layerFromMap2 "<<layerFromMap2->size();
        // delete the map
              delete map2;

 ////********************** After deletion of map2 ,we are getting operational layers as zero

        //      // add all the layers to the mapView's map
              auto* operationalLayers = m_mapView->map()->operationalLayers();

 

              for (auto* layer : layersFromMap2)
                operationalLayers->append(layer);
              qDebug()<<"total layers "<<operationalLayers->size();
    });

    m_mobileMapPackage->load();

0 Kudos