Imported from liodali/osm_flutter (
AGENTS.md). Install upstream withnpx skills add liodali/osm_flutter. Copyright stays with the author.
OSM Flutter — Agent Guide
Overview
Flutter plugin for OpenStreetMap supporting Android, iOS, and Web. Uses a federated plugin architecture with 3 packages.
| Package | Role | Current Version |
|---|---|---|
flutter_osm_plugin |
Main plugin, re-exports interface + platform-specific implementations | 1.4.5 |
flutter_osm_interface |
Platform interface (abstract classes, types, channel definitions) | 1.4.0 |
flutter_osm_web |
Web platform implementation (HTML/JS interop) | 1.4.4 |
Architecture
Federated Plugin Pattern
flutter_osm_plugin (main)
├── depends on flutter_osm_interface ^1.4.0
├── depends on flutter_osm_web ^1.4.4
├── android/ → native Android (Kotlin)
├── ios/ → native iOS (Swift)
└── lib/ → shared Dart + widget layer
flutter_osm_interface
└── lib/src/ → OSMPlatform abstract, types, events, method channel
flutter_osm_web
└── depends on flutter_osm_interface ^1.4.0
└── lib/src/ → Web implementation via HtmlElementView + JS interop
Key Abstractions
OSMPlatform(flutter_osm_interface) — base platform interface usingplugin_platform_interfaceMobileOSMPlatformextendsOSMPlatform— adds mobile-only methods (markers, roads, tracking, shapes)MethodChannelOSM— default Android/iOS implementation viaMethodChannelWebOsmController/OsmWebPlatform— web implementation via JS interop
Directory Structure
osm_flutter/
├── android/ # Native Android (Kotlin)
│ └── src/main/kotlin/... # FlutterOsmPlugin, OSM views, lifecycle
├── ios/ # Native iOS (Swift)
│ └── flutter_osm_plugin/ # Swift plugin, map views
├── lib/
│ ├── flutter_osm_plugin.dart # Library exports
│ └── src/
│ ├── controller/
│ │ ├── map_controller.dart # Main MapController (mobile)
│ │ ├── picker_map_controller.dart
│ │ ├── simple_map_controller.dart
│ │ └── osm/ # OSMController state holder
│ ├── widgets/
│ │ ├── mobile_osm_flutter.dart # Mobile map widget
│ │ ├── picker_location.dart
│ │ ├── custom_picker_location.dart
│ │ ├── static_osm.dart
│ │ ├── copyright_osm_widget.dart
│ │ ├── stub.dart # Web/mobile stubs
│ │ └── platform/ # Platform-specific widget shims
│ ├── common/ # Utilities, exceptions
│ └── osm_flutter.dart # Main OSMFlutter widget
├── flutter_osm_interface/
│ └── lib/src/
│ ├── osm_interface.dart # OSMPlatform + MobileOSMPlatform
│ ├── channel/
│ │ └── osm_method_channel.dart # MethodChannelOSM
│ ├── types/ # GeoPoint, RoadInfo, BoundingBox, etc.
│ ├── common/ # OSMEvent, utilities, exceptions
│ ├── map_controller/ # BaseMapController, IBaseMapController
│ ├── osm_controller/ # Abstract OSMController
│ └── mixin/ # Android lifecycle, OSM mixins
├── flutter_osm_web/
│ └── lib/src/
│ ├── web_platform.dart # OsmWebPlatform registration
│ ├── osm_web.dart # OsmWebWidget (HtmlElementView)
│ ├── controller/
│ │ └── web_osm_controller.dart # WebOsmController
│ ├── channel/
│ │ └── method_channel_web.dart # Web method channel
│ ├── interop/ # JS interop bindings
│ ├── asset/ # map.html, map.js, osm_interop.js
│ └── mixin_web.dart # Web-specific controller mixin
└── example/ # Demo app
├── android/
│ └── app/build.gradle.kts # compileSdk 36, minSdk 32
├── ios/
└── lib/ # Example UI
Native Implementation Notes
Android
- Language: Kotlin
- Map Engine: Native OSM views (osmdroid or similar)
- Compile SDK: 36
- Min SDK: 32
- Key Classes:
FlutterOsmPlugin,OsmFactory, lifecycle management - Build: Kotlin Gradle Plugin (KGP), Java 17
iOS
- Language: Swift
- Map Engine: Native iOS map views
- Min iOS: 13
- Package Manager: SPM (Swift Package Manager) support added in v1.4.4
- Key Classes: Swift plugin, map view controllers
Web
- Rendering:
HtmlElementViewembedding an HTML/JS map - Interop:
dart:js_interop/package:webfor JS bridge - Assets:
map.html,map.js,osm_interop.jsloaded from package assets - Removed:
package_info_plusdependency (v1.4.4)
Key Technical Rules
- Never use
dart:iofor platform checks. UsedefaultTargetPlatformfrompackage:flutter/foundation.dartinstead (Android/iOS/web-safe). - Web compatibility: Any widget using
Platform.isAndroidorPlatform.isIOSwill crash on web. Always guard withdefaultTargetPlatformorkIsWeb. - Federated plugin changes: When modifying platform APIs, update
flutter_osm_interfacefirst, thenflutter_osm_web, then the main plugin. - Path vs published deps: During development, packages use
path:dependencies. For release, switch to caret (^) constraints. - Asset loading: Web assets (JS/HTML) are loaded from
packages/flutter_osm_web/src/asset/via Flutter asset system.
Release Scripts
| Script | Purpose |
|---|---|
update_versions.py |
Update dependency versions in pubspecs (no publish) |
check_pubspec_release.py |
Check pub.dev versions, optionally publish inner packages, then update root deps |
pre_release.py |
Git tag-based release trigger (uses tags like flutter_osm_interface-v1.4.0) |
update_versions.py usage
python3 update_versions.py --mode all # update web + root pubspecs
python3 update_versions.py --mode osm # update only root pubspec
python3 update_versions.py --mode web # update only web pubspec
python3 update_versions.py --mode all --version-type upperbound # use >=min <max
Modes:
web— updatesflutter_osm_web's dependency onflutter_osm_interfaceosm— updates rootpubspec.yamldependencies (smart: skips if up-to-date, converts path to version)all— both
Version types:
caret(default) —^1.4.0upperbound—">=1.4.0 <1.5.0"
check_pubspec_release.py usage
python3 check_pubspec_release.py # check versions, fail if missing
python3 check_pubspec_release.py --publish # publish missing packages, then update deps
GitHub Actions Workflows
| Workflow | Trigger | Purpose |
|---|---|---|
publish.yaml |
vX.Y.Z tag |
Publish main plugin to pub.dev |
build_packages.yaml |
flutter_osm_interface-vX.Y.Z / flutter_osm_web-vX.Y.Z tags |
Publish inner packages |
base_publish_pcks.yaml |
Reusable | OIDC-based pub.dev publishing |
deploy_example_android.yaml |
app-vX.Y.Z tag or manual |
Build AAB + deploy to Google Play |
Deploy Example Android
- Trigger:
git tag app-v1.2.3 && git push origin app-v1.2.3→ auto-deploys to internal track - Manual: Any track (
internal,alpha,beta,production) - Secrets required:
KEYSTORE_BASE64,KEYSTORE_PASSWORD,KEY_PASSWORD,KEY_ALIAS,GOOGLE_PLAY_SERVICE_ACCOUNT_JSON
Example App
- Package:
hamza.dali.flutter_osm_plugin_example - Compile SDK: 36
- Min SDK: 32
- NDK: 28.2.13676358
- Signing: Reads
android/key.propertiesfor release signing - Build:
flutter build appbundle --release(inexample/)
Common Tasks
Adding a new platform method
- Add method signature to
OSMPlatformorMobileOSMPlatforminflutter_osm_interface - Implement in
MethodChannelOSM(Android/iOS) - Implement in
WebOsmController/OsmWebPlatform(web) - Expose via
MapControllerin main plugin
Updating versions for release
# 1. Update inner package versions in their pubspec.yaml files manually
# 2. Run version updater
python3 update_versions.py --mode all
# 3. Check & publish
python3 check_pubspec_release.py --publish
# 4. Update main plugin version, then publish
flutter pub publish -f
Building example release
cd example
flutter build appbundle --release
# Output: build/app/outputs/bundle/release/app-release.aab
Dependencies
Main Plugin
flutter_osm_interface: ^1.4.0flutter_osm_web: ^1.4.4dio: ^5.9.2,routing_client_dart: ^0.5.5,google_polyline_algorithm: ^3.1.0permission_manager: ^2.0.9,url_launcher: ^6.3.2
Interface
plugin_platform_interface: ^2.1.8stream_transform: ^2.1.0google_polyline_algorithm: ^3.1.0dio: ^5.8.0+1
Web
web: ^1.1.1stream_transform: ^2.1.0routing_client_dart: ^0.5.5dio: ^5.9.0flutter_osm_interface: ^1.4.0