startForeground method
- {required DownloadableRegion<
List< region,Object> > - FMTCTileProviderSettings? tileProviderSettings,
- bool disableRecovery = false,
- DownloadBufferMode bufferMode = DownloadBufferMode.disabled,
- int? bufferLimit,
- BaseClient? httpClient}
Download a specified DownloadableRegion in the foreground, with a recovery session
To check the number of tiles that need to be downloaded before using this function, use check.
httpClient
defaults to a HttpPlusClient which supports HTTP/2 and falls
back to a standard IOClient/HttpClient for HTTP/1.1 servers. Timeout is
set to 5 seconds by default.
Streams a DownloadProgress
object containing statistics and information
about the download's progression status. This must be listened to.
bufferMode
and bufferLimit
control how this download will use
buffering. For information about buffering, and it's advantages and
disadvantages, see
this docs page.
Also see DownloadBufferMode's documentation.
- If
bufferMode
is DownloadBufferMode.disabled (default),bufferLimit
will be ignored - If
bufferMode
is DownloadBufferMode.tiles,bufferLimit
will default to 500 - If
bufferMode
is DownloadBufferMode.bytes,bufferLimit
will default to 2000000 (2 MB)
Implementation
Stream<DownloadProgress> startForeground({
required DownloadableRegion region,
FMTCTileProviderSettings? tileProviderSettings,
bool disableRecovery = false,
DownloadBufferMode bufferMode = DownloadBufferMode.disabled,
int? bufferLimit,
BaseClient? httpClient,
}) async* {
// Start recovery
_recoveryId = DateTime.now().millisecondsSinceEpoch;
if (!disableRecovery) {
await FMTC.instance.rootDirectory.recovery._start(
id: _recoveryId!,
storeName: _storeDirectory.storeName,
region: region,
);
}
// Count number of tiles
final maxTiles = await check(region);
// Get the tile provider
final FMTCTileProvider tileProvider =
_storeDirectory.getTileProvider(tileProviderSettings);
// Initialise HTTP client
_httpClient = httpClient ??
HttpPlusClient(
http1Client: IOClient(
HttpClient()
..connectionTimeout = const Duration(seconds: 5)
..userAgent = null,
),
connectionTimeout: const Duration(seconds: 5),
);
// Initialise the sea tile removal system
Uint8List? seaTileBytes;
if (region.seaTileRemoval) {
try {
seaTileBytes = (await _httpClient!.get(
Uri.parse(
tileProvider.getTileUrl(
const TileCoordinates(0, 0, 17),
region.options,
),
),
))
.bodyBytes;
} catch (e) {
seaTileBytes = null;
}
}
// Initialise variables
final List<String> failedTiles = [];
int bufferedTiles = 0;
int bufferedSize = 0;
int persistedTiles = 0;
int persistedSize = 0;
int seaTiles = 0;
int existingTiles = 0;
_tileProgressStreamController = StreamController();
_cancelRequestSignal = Completer();
_cancelCompleteSignal = Completer();
// Start progress management
final DateTime startTime = DateTime.now();
_progressManagement = InternalProgressTimingManagement()..start();
// Start writing isolates
await BulkTileWriter.start(
provider: tileProvider,
bufferMode: bufferMode,
bufferLimit: bufferLimit,
directory: FMTC.instance.rootDirectory.directory.absolute.path,
streamController: _tileProgressStreamController!,
);
// Start the bulk downloader
final Stream<TileProgress> downloadStream = await bulkDownloader(
streamController: _tileProgressStreamController!,
cancelRequestSignal: _cancelRequestSignal!,
cancelCompleteSignal: _cancelCompleteSignal!,
region: region,
provider: tileProvider,
seaTileBytes: seaTileBytes,
progressManagement: _progressManagement!,
client: _httpClient!,
);
// Listen to download progress, and report results
await for (final TileProgress evt in downloadStream) {
if (evt.failedUrl == null) {
if (!evt.wasCancelOperation) {
bufferedTiles++;
} else {
bufferedTiles = 0;
}
bufferedSize += evt.sizeBytes;
if (evt.bulkTileWriterResponse != null) {
persistedTiles = evt.bulkTileWriterResponse![0];
persistedSize = evt.bulkTileWriterResponse![1];
}
} else {
failedTiles.add(evt.failedUrl!);
}
if (evt.wasSeaTile) seaTiles += 1;
if (evt.wasExistingTile) existingTiles += 1;
final DownloadProgress prog = DownloadProgress._(
downloadID: _recoveryId!,
maxTiles: maxTiles,
successfulTiles: bufferedTiles,
persistedTiles: persistedTiles,
failedTiles: failedTiles,
successfulSize: bufferedSize / 1024,
persistedSize: persistedSize / 1024,
seaTiles: seaTiles,
existingTiles: existingTiles,
duration: DateTime.now().difference(startTime),
tileImage: evt.tileImage == null ? null : MemoryImage(evt.tileImage!),
bufferMode: bufferMode,
progressManagement: _progressManagement!,
);
yield prog;
if (prog.percentageProgress >= 100) break;
}
_internalCancel();
}