Error downloading basemap using AGSOfflineMapTask

1134
4
11-04-2020 05:10 AM
SimonMitchell
New Contributor

I am using AGSOfflineMapTask (iOS SDK) to try and download the full contents of a map. The map is using a basemap generated from a portal item ID defined here: https://www.arcgis.com/home/item.html?id=3e1a00aeae81496587988075fe529f71 

When calling getOfflineMapCapabilities none of the layers or basemap are returning that they are not downloadable, and therefore I believe I should be able to download the open street map basemap, however when I try to create an offline map job and call `start` a login screen is shown to the user, and downloading of the basemap fails with an error:

 

Error Domain=NSCocoaErrorDomain Code=3072 "User canceled error" UserInfo={NSLocalizedDescription=User canceled error, NSUnderlyingError=0x60000018b450 {Error Domain=com.esri.arcgis.runtime.services.error Code=499 "Token Required"

Is there anything that can be done to allow download of this layer?

Tags (3)
0 Kudos
4 Replies
Nicholas-Furness
Esri Regular Contributor

That error is saying that you have not provided credentials to download the basemap. To download Esri basemaps you need to provide a login. You can provide a free developer account login if you need to.

When you create the AGSGenerateOfflineMapJob, you can provide a AGSCredential on the credential property.

Hope that helps.

0 Kudos
SimonMitchell
New Contributor

Thanks for the quick response Nicholas, so just to confirm:

1. Setting the license key isn't enough here?
2. Using a free developer account is okay for a production release of the app where a significant amount of users could be downloading the basemap on a semi-regular basis?

I've just attempted this Nicholas Furness‌ and unfortunately the login details I have used don't seem to be resolving this issue. One thing to note is that I have a license key provided by the client, but the username and password I am using (We haven't asked them for this yet) is for my personal account. Do the username/login need to be from the same account as the license key?
 
If I login using the alert prompt that shows to try and authenticate me then it works flawlessly... Is there somewhere else that I also need to provide the credential? I am doing so by setting it on the task returned by the generateOfflineMapJob call as suggested.

Edit: It seems I may have resolved this... I have also set the credential on the AGSPortal used to initially create the basemap when rendering the online version of the map, is that expected behaviour that it needs to be set in both places? If so, I'm happy that this has been resolved!

extension AGSBasemap {
    
    convenience init(itemId: String) {
        let portal = AGSPortal.arcGISOnline(withLoginRequired: false)
        portal.credential = HaitiMap.credential // Setting credential here too!
        let item = AGSPortalItem(portal: portal, itemID: itemId)
        let vectorTileLayer = AGSArcGISVectorTiledLayer(item: item)
        self.init(baseLayer: vectorTileLayer)
    }
}
0 Kudos
Nicholas-Furness
Esri Regular Contributor

Hi Simon.

1. Setting the license key isn't enough here?

Quite so. The license enables (or disables) functionality in Runtime, but does not impact authentication. That's where the username/password or other type of credential comes in. That's what determines whether and how you can access a resource.

2. Using a free developer account is okay for a production release of the app where a significant amount of users could be downloading the basemap on a semi-regular basis?

Yes, it is. But if you're earning any revenue off the app (through App Store sales or ads, for example) then you need to make sure you have a paid Builder Plan for what we call a commercial deployment. If it's a free app, you can stick with the free Essentials Plan. See Deploy your app—ArcGIS Runtime SDK for iOS | ArcGIS for Developers  for more info.

Back to authentication: If you're just authenticating to access the basemap services, you can use App Logins (Client ID + Client Secret). In fact, you should. It's something of an anti pattern to embed your username and password into the app. The short of it is you create an Application at ArcGIS for Developers, and that gives you a ClientID + Client Secret. You can use those to get a Token from ArcGIS Online, and that can be used to download the Basemaps without ever prompting the user for a login. The AuthenticationManager can make this seamless (see the Gist below). See these resources for some more info:

I have also set the credential on the AGSPortal

Interesting. I'll run that past some folks on the offline team here and see if that's expected. It's quite possible that it is and I've just made an assumption I shouldn't have!

0 Kudos
SimonMitchell
New Contributor

Thanks for the above again!

Quite so. The license enables (or disables) functionality in Runtime, but does not impact authentication. That's where the username/password or other type of credential comes in. That's what determines whether and how you can access a resource.

Makes sense in terms of the license key, thanks for explaining that.

Yes, it is. But if you're earning any revenue off the app (through App Store sales or ads, for example) then you need to make sure you have a paid Builder Plan for what we call a commercial deployment. If it's a free app, you can stick with the free Essentials Plan. See Deploy your app—ArcGIS Runtime SDK for iOS | ArcGIS for Developers  for more info.

Thank you for that, this is for a client (The global disaster preparedness centre) to go in as a new feature to their First Aid app so it isn't for profit and never will be, that's good to know!

Back to authentication: If you're just authenticating to access the basemap services, you can use App Logins (Client ID + Client Secret). In fact, you should. I have also set the credential on the AGSPortal

And thanks yet again! Those links were really helpful, and that seems like a far more robust solution than setting the credential object all over the place, 100% didn't want to be using username/password and will definitely consider abstracting the client id and secret too!

Hope you have a nice weekend!

0 Kudos