Hi!
I would like to save a predefined area of interest of a MapView that can be loaded when there is no network connection. I tried following the ArcGIS Samples for "ExportTiles" but it keeps failing. I am not sure what the correct solution would be, but perhaps someone could provide the steps I should follow to export the map tiles.
Thank you!
Nick
Solved! Go to Solution.
You would need to register it (probably in your main.cpp) for QML - something like this:
qmlRegisterUncreatableType<AuthenticationManager>("Esri.MyApp", 1, 0, "AuthenticationManager", "AuthenticationManager is uncreateable");
Yes I have done this. Maybe I am defining the AuthenticationView incorrectly in the QML?
My setup is structured similar to this:
MyApp {
id: myapp // other propertiesAuthenticationView {anchors.fill: parentauthenticationManager: myapp.authManager} // Other QML Items (MapView, Rectangles, etc) }
Where authManager is the READ function of a Q_PROPERTY defined in my myapp.cpp file to return AuthenticationManager::instance()
Its hard to tell without seeing all of the code - but it looks to me as though the property has not notified QML that the authManager is ready yet. Do you have a signal that you emit in the c'tor of your type to show that the property (the singleton) has changed? Or is the property marked CONSTANT?
The property is marked as CONSTANT like how the sample does it. Do I need to connect a signal in the QML for when the singleton has changed?
You shouldn't need to I don't think. Maybe you can try printing console.log(myApp.authManager) when the apps Component.onComplete event occurs to see what it displays?
Luke,
So it seems that I am able to catch the AuthenticationChallenge with the code below (which in my case is consistently the need for a username/password), but when I provide credentials (my username/password for my ArcGIS Developer account) I receive an error saying "unable to generate token". I am trying to get access to the portal "https://tiledbasemaps.arcgis.com" (the group of basemaps for export that you provided), but am consistently unable to get access.
My underlying need is to be able to press a button on the UI that will call a method to export the current view of the map to a .tpk file which can then be loaded another time. I believe the tiledbasemaps group has the right data for this, but I can't seem to figure out how to provide the right credentials to access them. My thought is to create a Portal linked to my developer account and to log in that way so that the map already has the correct credentials, but this doesn't seem to be working.
Any advice for a different approach or how to generate a valid token from within the Runtime?
Thank you,
Nick
I have a setup within the myapp.cpp file to identify and handle the different types of challenges without the QML view (this block was made following the topic article you mentioned above). But it refuses to accept my login credentials and gives an error message saying "Token required" Any thoughts why that would be happening? QMetaObject::Connection connection = connect(AuthenticationManager::instance(), &AuthenticationManager::authenticationChallenge, this, [this](AuthenticationChallenge* challenge){
switch(challenge->authenticationChallengeType()){
case AuthenticationChallengeType::UsernamePassword:
challenge->continueWithUsernamePassword(userName, password);
std::cout << "Needs username and password" << std::endl;
break;
case AuthenticationChallengeType::OAuth:
// continueWithOAuthAuthorizationCode
std::cout << "Needs OAuth" << std::endl;
break;
case AuthenticationChallengeType::ClientCertificate:
// continueWithClientCertificate
std::cout << "Needs client certificate" << std::endl;
break;
case AuthenticationChallengeType::SslHandshake:
// continueWithSslHandshake
std::cout << "Needs SSL handshake" << std::endl;
break;
case AuthenticationChallengeType::Unknown:
std::cout << "Unknown challenge" << std::endl;
break;
}
});
The cause of the AuthenticationChallenge I believe is this:
QUrl serviceUrl_ = QUrl("https://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Imagery/MapServer");
p_ExportTask_ = new ExportTileCacheTask(serviceUrl_, this);
connect(p_ExportTask_, &ExportTileCacheTask::doneLoading, this, [this](Error error){
if(!error.isEmpty()){
std::cout << "Load error: " << error.message().toStdString() << std::endl;
}
}); p_ExportTask_->load();
Hi Nicholas - I think there may be an issue with logging in using the workflow you describe (I will log an issue to look into that). Here is some workaround code that will first authenticates using a portal - this works for me, so hopefully it should solve your problem.
void ExportTiles::componentComplete()
{
QQuickItem::componentComplete();
// create Portal and load
Portal* portal = new Portal(QUrl("https://arcgis.com"), true, this);
connect(portal, &Portal::doneLoading, this, [this](Error e)
{
if (!e.isEmpty())
qDebug() << e.message() << e.additionalMessage();
else
qDebug() << "portal loaded";
});
//portal->load(); // this will trigger an authentication challenge for AGOL credentials
// find QML MapView component
m_mapView = findChild<MapQuickView*>("mapView");
// create a tiled basemap
ArcGISTiledLayer* tiledLayer = new ArcGISTiledLayer(m_serviceUrl, this);
Basemap* basemap = new Basemap(tiledLayer, this);
// create a new map instance
m_map = new Map(basemap, this);
// set an initial viewpoint
Envelope env(11257744, 1682070, 11259005, 1683016, SpatialReference(3857));
Viewpoint viewpoint(env);
m_map->setInitialViewpoint(viewpoint);
// set map on the map view
m_mapView->setMap(m_map);
// create the task with the url and load it
m_exportTileCacheTask = new ExportTileCacheTask(m_exportUrl, this);
connect(m_exportTileCacheTask, &ExportTileCacheTask::doneLoading, this, [this](Error error)
{
if (!error.isEmpty())
{
emit updateStatus("Export failed");
emit hideWindow(5000, false);
}
});
connect(m_mapView, &MapQuickView::viewpointChanged, this, [this]()
{
qDebug() << m_mapView->currentViewpoint(ViewpointType::BoundingGeometry).targetGeometry().toJson();
});
}
The rest of your code should work as is hopefully - please let me know if this is working for you!
Luke
Luke,
Thank you for the sample code. I have integrated that into what I have but still no luck. Just to be clear, your code should try to create the basemap, then throw an AuthenticationChallenge which would then be picked up by the AuthenticationView in the QML where you can log in and the basemap would then load, correct?
As of now, my issue is that the AuthenticationView will not create properly, and it keeps giving me the same two errors:
file:///C:/Program Files (x86)/ArcGIS SDKs/Qt100.1/sdk/toolkit/Import/Esri/ArcGISRuntime/Toolkit/Dia...: QML Connections: Cannot assign to non-existent property "onAuthenticationChallenge"
file:///C:/Program Files (x86)/ArcGIS SDKs/Qt100.1/sdk/toolkit/Import/Esri/ArcGISRuntime/Toolkit/Dia...: Unable to assign [undefined] to QObject*
If this issue with the AuthenticationView is solved, I should be able to enter in my ArcGIS Developer credentials and the map would load, correct?
Thanks for all the help!
Nick