Select to view content in your preferred language

Estimating Map downloadable size while Caching the map

1105
12
Jump to solution
04-10-2024 05:35 AM
AjiteshUpadhyaya
Emerging Contributor

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 

0 Kudos
12 Replies
AjiteshUpadhyaya
Emerging Contributor

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];
                }
            }];
0 Kudos
Ting
by Esri Contributor
Esri Contributor
                    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.

0 Kudos
AjiteshUpadhyaya
Emerging Contributor

This worked, Thanks a lot Ting for the help.