flutter_map
flutter_map copied to clipboard
[FEATURE] Fallback tile URLs in-case of HTTP error
Describe The Problem I'm try to catch an error callback when the tile failed, so, the idea is when the first tile url map failed, called another, but this method errorTileCallback doesn't call, so, don't find in examples an example, maybe someone know somehow? Thanks
Additional Information TileLayerOptions getMapBoxStyle(Function refresh, {Key key}) => TileLayerOptions( key: key, urlTemplate: globalTileMap, errorTileCallback: (tile, error) { globalTileMap = 'https://tiles.picap.app/styles/osm-bright/{z}/{x}/{y}.png'; refresh.call(); }, backgroundColor: PiColors.backgroundTileMap);
I haven't tested the errorTileCallback code....but maybe it depends how it failed ? For example, if there just isn't a response from a server, would it know ? It may taking a bit of digging and debugging the tile_layer.dart in the layers folder to try and get an idea of what's happening.
Hi there @juanlabrador, Did @ibrierley's suggestion help? Happy to help more if required :)
Hi guys, thanks for answer, well, the simple example its put a bad url, the tile when faile its return 403 error, I mean, the tile does't show map, so, in that cases, the idea is use another tile url like support, but I don't know where catch this 403 error
At the moment, fallback URLs aren't supported - if that's what you mean. But it sounds like an interesting and useful idea! Converting to feature request...
Note that for the time being, feature requests have an indefinite wait time, as we have quite a backlog of issues and bugs to get to. Many thanks for your suggestion!
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
Hi @JaffaKetchup, I think I've been able to add a fallbackUrl to the FMNetworkImageProvider
, it would require to specify NetworkTileProvider()
as the tile provider of TileLayer
but the result is as @juanlabrador would've wanted.
If an error occured it will retry to fetch tiles with the fallback url instead.
Code Sample
TileLayer(
urlTemplate: 'https://fake-tile-provider.org/{z}/{x}/{y}.png',
fallbackUrl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: const ['a', 'b', 'c'],
userAgentPackageName: 'dev.fleaflet.flutter_map.example',
tileProvider: NetworkTileProvider(),
),
Implementation
class FMNetworkImageProvider extends ImageProvider<FMNetworkImageProvider> {
// ...
/// The fallback URL from which the image will be fetched.
final String? fallbackUrl;
// ...
FMNetworkImageProvider(
this.url, {
required this.fallbackUrl,
RetryClient? retryClient,
this.headers = const {},
}) : retryClient = retryClient ?? RetryClient(Client());
// ...
Future<ImageInfo> _loadWithRetry(
FMNetworkImageProvider key,
DecoderCallback decode, [
bool useFallback = false,
]) async {
assert(key == this);
assert(useFallback == false || fallbackUrl != null);
try {
final uri = Uri.parse(useFallback ? fallbackUrl! : url);
final response = await retryClient.get(uri, headers: headers);
if (response.statusCode != 200) {
throw NetworkImageLoadException(
statusCode: response.statusCode, uri: uri);
}
final codec = await decode(response.bodyBytes);
final image = (await codec.getNextFrame()).image;
return ImageInfo(image: image);
} catch (e) {
if (!useFallback && fallbackUrl != null) {
return _loadWithRetry(key, decode, true);
}
rethrow;
}
}
}
Would you be interested in a PR ? (I've already created a full sample added to the example app)
Hi @TesteurManiak,
This looks great, and we would appreciate any PR you can make :)
Just a question, why does it require NetworkTileProvider()
? I think it should work for all providers if possible.
Many thanks.
Thanks for the quick response, I think I can make it work for all providers, it was just easier for NetworkTileProvider
as it was already relying on a RetryClient
.
I'll make a PR as soon as I've finished the remaining improvements.