Hello Experts,
We would need to show the Estimated time to complete the caching of map. This can be done if we have some reference on how much is already downloaded to the device and the total size of the map.
For the same, i have written code something like below, but not getting how can i calculate/get how much has been downloaded.
-(void) cacheBasemapParameters:(AGSExportTileCacheParameters *)params withSteps:(int) steps
{
[self deleteExistingTPKFile];
// Use a weak variable for self within the blocks
__weak EsriMapViewController *weakSelf = self;
// temp file
NSURL *tempFileDirectoryUrl = [[NSFileManager.defaultManager temporaryDirectory] URLByAppendingPathComponent:NSProcessInfo.processInfo.globallyUniqueString];
NSURL* docDirectoryURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
[NSFileManager.defaultManager createDirectoryAtURL:tempFileDirectoryUrl withIntermediateDirectories:YES attributes:nil error:nil];
NSString *extension = @".tpk";
if (self.tileCacheTask.mapServiceInfo.exportTileCacheCompactV2Allowed)
{
extension = @".tpkx";
}
NSURL *tempFileUrl = [docDirectoryURL URLByAppendingPathComponent:[@"myTileCache" stringByAppendingString:extension]];
// Kick-off operation
AGSExportTileCacheJob *job = [self.tileCacheTask exportTileCacheJobWithParameters:params downloadFileURL:tempFileUrl];
self.cacheJob = job;
[self.cacheJob startWithStatusHandler:^(AGSJobStatus status) {
//Print the job status
DLog(@"%d", status);
//NSArray *allMessages = [userInfo objectForKey:@"messages"];
//Display download progress if we are fetching result
/*if (status == 3) {
NSNumber* totalBytesDownloaded = userInfo[@"AGSDownloadProgressTotalBytesDownloaded"];
NSNumber* totalBytesExpected = userInfo[@"AGSDownloadProgressTotalBytesExpected"];
if(totalBytesDownloaded!=nil && totalBytesExpected!=nil){
double dPercentage = (double)([totalBytesDownloaded doubleValue]/[totalBytesExpected doubleValue]) * 100;
[weakSelf showProgressWithMessage:[NSString stringWithFormat:@"%@\n%.2f%% %@", statusMessageTitle, dPercentage, [weakSelf.dataSource textValueForKey:@"DownloadStatus"]]];
}
}else if ( allMessages.count) {
[weakSelf showProgressWithMessage:[self extractMostRecentMessage:allMessages]];
} */
} completion:^(AGSTileCache * _Nullable result, NSError * _Nullable error) {
if (error){
[weakSelf hideProgress];
//alert the user
[ViewUtils showSimpleAlertWithTitle:[self.dataSource textValueForKey:@"Error"]
message:[self.dataSource textValueForKey:@"BasemapDownloadError"]
cancelButtonTitle:[self.dataSource textValueForKey:@"Ok"]];
// no need to proceed further if basemaps cannot be downloaded.
}
else{
DLog(@"Successfully downloaded basemap");
// start downloading feature layers
if(weakSelf.featureLayersToCache.count > 0){
// delete all cached feature layers
[self deleteCachedGeodatabases];
[self.gdbFeatureLayerMap removeAllObjects];
}
[weakSelf cacheNextFeatureLayer];
}
}];
}
Any idea on how to get it done?
Thanks,
Ajitesh
Solved! Go to Solution.
Thanks Ting, for looking into it. Please find below my code snippet for the complete method for caching.
[self initCacheTaskForUrl:abo.basemapURL];
double minScale = self.mapView.mapScale;
//double maxScale = self.tileCacheTask.mapServiceInfo.maxScale;
double maxScale = self.mapView.map.basemap.baseLayers.firstObject.maxScale;
if (minScale < maxScale) {
minScale = maxScale;
}
if (isnan(maxScale)) {
maxScale = minScale;
}
AGSEnvelope *extent = [self.mapView visibleArea].extent;
[self.tileCacheTask exportTileCacheParametersWithAreaOfInterest:extent minScale:minScale maxScale:maxScale completion:^(AGSExportTileCacheParameters * _Nullable exportTileCacheParameters, NSError * _Nullable error) {
if (error) {
//TODO: display error
} else {
// AGSEstimateTileCacheSizeJob *job = [self.tileCacheTask estimateTileCacheSizeJobWithParameters:exportTileCacheParameters];
// [job startWithStatusHandler:^(AGSJobStatus status) {
// DLog(@"estimation status: %ld", (long)status);
// } completion:^( AGSEstimateTileCacheSizeResult * _Nullable result, NSError * _Nullable error) {
// DLog(@"estimated file size: %llu", result.fileSize);
// [self cacheBasemapParameters:exportTileCacheParameters withSteps:steps];
// }];
//EWU2-9, EWU2-12 Cache Progress indicator does not exist
NSString * statusMessageTitle = [NSString stringWithFormat:@"%@ %@",[self.dataSource textValueForKey:@"DownloadPrepare"], basemap];
_currentActivity = GISActivityCachingMaps;
[self showProgressWithMessage:statusMessageTitle];
[self deleteExistingTPKFile];
// Use a weak variable for self within the blocks
__weak EsriMapViewController *weakSelf = self;
// temp file
NSURL *tempFileDirectoryUrl = [[NSFileManager.defaultManager temporaryDirectory] URLByAppendingPathComponent:NSProcessInfo.processInfo.globallyUniqueString];
NSURL* docDirectoryURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
[NSFileManager.defaultManager createDirectoryAtURL:tempFileDirectoryUrl withIntermediateDirectories:YES attributes:nil error:nil];
NSString *extension = @".tpk";
if (self.tileCacheTask.mapServiceInfo.exportTileCacheCompactV2Allowed)
{
extension = @".tpkx";
}
NSURL *tempFileUrl = [docDirectoryURL URLByAppendingPathComponent:[@"myTileCache" stringByAppendingString:extension]];
//DLog(@"%d", status);
AGSEstimateTileCacheSizeJob *jobCacheSize = [self.tileCacheTask estimateTileCacheSizeJobWithParameters:exportTileCacheParameters];
self.estimateJob = jobCacheSize;
[jobCacheSize startWithStatusHandler:nil completion:^(AGSEstimateTileCacheSizeResult *result, NSError *error) {
if (result) {
DLog(@"Tile count: %lld", result.tileCount);
NSByteCountFormatter *formatter = [[NSByteCountFormatter alloc] init];
formatter.allowedUnits = NSByteCountFormatterUseAll;
formatter.countStyle = NSByteCountFormatterCountStyleFile;
formatter.includesUnit = YES;
formatter.adaptive = YES;
DLog(@"Tile count: %lld", [formatter stringFromByteCount:result.tileCount]);
DLog(@"File size: %@", [formatter stringFromByteCount:result.fileSize]);
NSNumber* totalBytesDownloaded = [formatter stringFromByteCount:result.tileCount];
NSNumber* totalBytesExpected = [formatter stringFromByteCount:result.fileSize];
// Convert NSNumber objects to strings
NSString* downloadedString = [totalBytesDownloaded stringValue];
NSString* expectedString = [totalBytesExpected stringValue];
// Create the desired format: 'totalBytesDownloaded/totalBytesExpected'
NSString* ratioString = [NSString stringWithFormat:@"%@/%@", downloadedString, expectedString];
//double dPercentage = (double)([totalBytesDownloaded doubleValue]/[totalBytesExpected doubleValue]) * 100;
[weakSelf showProgressWithMessage:[NSString stringWithFormat:@"%@\n %@ %@", statusMessageTitle, ratioString, [weakSelf.dataSource textValueForKey:@"DownloadStatus"]]];
//[self cacheBasemapParameters:exportTileCacheParameters withSteps:steps];
} else if (error) {
DLog(@"%@", error.localizedDescription);
}
}];
// Kick-off operation
AGSExportTileCacheJob *job = [self.tileCacheTask exportTileCacheJobWithParameters:exportTileCacheParameters downloadFileURL:tempFileUrl];
self.cacheJob = job;
[self.cacheJob startWithStatusHandler:^(AGSJobStatus status) {
} completion:^(AGSTileCache * _Nullable result, NSError * _Nullable error) {
if (error){
[weakSelf hideProgress];
//alert the user
[ViewUtils showSimpleAlertWithTitle:[self.dataSource textValueForKey:@"Error"]
message:[self.dataSource textValueForKey:@"BasemapDownloadError"]
cancelButtonTitle:[self.dataSource textValueForKey:@"Ok"]];
// no need to proceed further if basemaps cannot be downloaded.
}
else{
DLog(@"Successfully downloaded basemap");
// start downloading feature layers
if(weakSelf.featureLayersToCache.count > 0){
// delete all cached feature layers
[self deleteCachedGeodatabases];
[self.gdbFeatureLayerMap removeAllObjects];
}
[weakSelf cacheNextFeatureLayer];
}
}];
NSNumber* totalBytesDownloaded = [formatter stringFromByteCount:result.tileCount]; NSNumber* totalBytesExpected = [formatter stringFromByteCount:result.fileSize];
This is not correct. The estimate job only gives you the estimation of total amount of tiles to be downloaded, and the estimated file size from the server. It doesn't provide real time update for the progress.
What you have here is showing the static tileCount/fileSize, which doesn't have a real meaning.
For fraction completed of the AGSExportTileCacheJob, see my previous comment.
This worked, Thanks a lot Ting for the help.