- Introduced new MapLayerType for vector MBTiles. - Enhanced MapLayer class to handle vector-specific properties. - Implemented MBTilesService for managing MBTiles files, including import and deletion functionalities. - Updated MapManagementScreen to allow importing and managing MBTiles files. - Added UI components for displaying and interacting with MBTiles layers. - Integrated vector tile rendering in MapTab, supporting dynamic theme loading. - Updated pubspec.yaml to include necessary dependencies for MBTiles and vector tiles.
6.1 KiB
Vector Map Tiles Implementation - Technical Notes
Successfully Implemented! ✅
The vector map tiles with MBTiles support has been successfully implemented and the app builds without errors.
Final Package Versions
vector_map_tiles: ^9.0.0-beta.8 # flutter_map 8.x compatible!
vector_map_tiles_mbtiles: 1.2.1 # from git repository (latest)
vector_tile_renderer: ^6.0.0
mbtiles: ^0.4.2
file_picker: ^8.3.7
http: 1.5.0
Why Git Dependency?
The published version of vector_map_tiles_mbtiles on pub.dev doesn't support vector_map_tiles v9 beta yet. The git version from the flutter_map_plugins repository is compatible:
vector_map_tiles_mbtiles:
git:
url: https://github.com/josxha/flutter_map_plugins.git
path: vector_map_tiles_mbtiles
API Compatibility Issues Resolved
1. Name Collision: Theme
Problem: Both Flutter Material and vector_tile_renderer export a Theme class.
Solution: Import vector_tile_renderer with alias:
import 'package:vector_tile_renderer/vector_tile_renderer.dart' as vtr;
// Usage
vtr.Theme? _vectorTheme;
final theme = vtr.ThemeReader().read(styleJson);
2. Name Collision: TileLayer
Problem: Both flutter_map and vector_tile_renderer export TileLayer.
Solution: Import flutter_map with alias for explicit TileLayer usage:
import 'package:flutter_map/flutter_map.dart' as flutter_map;
import 'package:flutter_map/flutter_map.dart'; // Keep non-aliased for other classes
// Usage
flutter_map.TileLayer(...)
3. MBTiles API Changes
Problem: The mbtiles package v0.4.2 changed from Map-based to object-based API.
Old API (v0.3.x):
final metadata = await mbtiles.getMetadata();
final name = metadata['name']; // Map access
final minZoom = metadata['minzoom'];
New API (v0.4.2):
final metadata = await mbtiles.getMetadata();
final name = metadata.name; // Object property
final minZoom = metadata.minZoom?.toInt(); // Returns double?
Key Changes:
getMetadata()returnsMbTilesMetadataobject, notMap<String, dynamic>- Properties like
minZoom,maxZoomare nowdouble?instead ofint? boundsis nowMbTilesBoundsobject with no direct property accesstypeis nowTileLayerType?enum instead ofString?- Some properties removed:
attribution,center,json
Our Solution:
final metadata = await mbtiles.getMetadata();
// Convert types appropriately
return MbtilesMetadata(
name: metadata.name ?? _getFileNameWithoutExtension(file),
description: metadata.description,
version: metadata.version?.toString(), // double? to String?
attribution: null, // Not available in new API
bounds: metadata.bounds.toString(), // Object to String
center: null, // Not available in new API
minZoom: metadata.minZoom?.toInt(), // double? to int?
maxZoom: metadata.maxZoom?.toInt(), // double? to int?
format: metadata.format,
type: metadata.type?.name, // TileLayerType? to String?
json: null, // Not available in new API
file: file,
fileSize: fileSize,
);
4. Type Mismatch: maximumZoom
Problem: VectorTileLayer.maximumZoom expects double, not int.
Solution: Remove .toInt() call:
VectorTileLayer(
theme: _vectorTheme!,
tileProviders: TileProviders({...}),
maximumZoom: _currentLayer.maxZoom, // Already double
)
File Structure
lib/
├── services/
│ ├── mbtiles_service.dart (280 lines) - NEW
│ └── tile_cache_service.dart (+20 lines)
├── models/
│ └── map_layer.dart (+40 lines)
├── screens/
│ ├── map_tab.dart (+50 lines)
│ └── map_management_screen.dart (+180 lines)
└── l10n/
└── app_en.arb (+80 lines)
Total: ~650 new lines of code
Build Status
- ✅ iOS: Build successful (28.7MB)
- ⏳ Android: Not tested yet
- ⏳ Runtime: Not tested with actual MBTiles file
Testing Checklist
Before Runtime Testing
- Code compiles without errors
- All imports resolved
- API compatibility verified
- Import MBTiles file
- Switch to vector layer
- Verify style loading
- Verify vector rendering
- Test offline mode
- Test file deletion
Known Limitations
- Missing Metadata:
attribution,center, andjsonfields are not available in mbtiles v0.4.2 - Bounds Format: Bounds are stored as string representation of MbTilesBounds object
- Schema Detection: Limited to checking description and name for "shortbread" or "openmaptiles" keywords
Recommendations for Production
- Add Error Handling: Wrap vector tile rendering in try-catch to fall back to raster
- Cache Styles: Persist downloaded styles to avoid re-downloading
- Validate MBTiles: Add file format validation before import
- Add Tests: Unit tests for MbtilesService, integration tests for rendering
- Performance Monitoring: Track render times and memory usage
Quick Start for Testing
- Download Test File:
wget https://geodata.maptiler.download/extracts/osm/v3.11/2020-02-10/europe/osm-2020-02-10-v3.11_europe_slovenia.mbtiles
- Run App:
flutter run
- Import File:
- Settings → Map Management
- Tap "Import MBTiles File"
- Select downloaded file
- Switch Layer:
- Map tab → Layers button
- Select "Slovenia" (or imported name)
- Wait for style download
- Verify:
- Check map renders vector tiles
- Test zooming (over-zoom should work)
- Test panning
- Toggle airplane mode (should still work)
Support
For issues related to:
- Package compatibility: Check flutter_map_plugins repository
- MBTiles format: See MBTiles specification
- Vector styles: Check versatiles.org documentation
- App-specific issues: See CLAUDE.md and VECTOR_MAPS.md