Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR introduces a self contained "cross platform" plugin system for maplibre.
At its core, the CrossPlatformPlugin system simply punches a tiny hole through the iOS and Android platforms, allowing plugins to access mbgl::Map and other core objects directly. Each plugin is itself an mbgl::MapObserver allowing them to respond to map events (like onCameraChange, onStyleImageMissing etc), essentially behaving like a platform MapView.
This combo allows complex map features to be built targeting the native core that will run on both iOS and Android while not breaking any of the current API contracts or contributing to any binary size increase to the main library. This means that plugins can live right alongside existing iOS and Android platform APIs and be integrated into existing mobile apps as is.
NOTE: The plugin system is not opinionated about:
While the plugin system is itself very simple, integration into build systems, tooling and creating ios/android platform glue is not. To that end I have provided two plugin examples which are integrated into the android and ios test apps.
Example Plugins
On iOS, the plugins are built using the bazel system, while on android they make use of cmake. I am not an expert in any of these systems and the build setup is for demonstration only. At meta we use BUCK, which is bazel like and enables advanced features like so merging on Android, and mixed objc/swift which works well for this kind of system.
On Android, plugins are built via CMake and are inserted directly into the Maplibre.so to avoid issues with symbol visibility and complex merging. Maplibre Android defaults to private visibility which would make merging .so from 3rd parties difficult.
Basic Plugin using Objc++ and Maplibre's JNI system for glue
This plugin shows how to setup the plugin c++ core and one approach to "hand rolling" platform bindings. On iOS we can simply use Objc++ and get swift integration via objc interop. On Android, I've provided a convenience hook into Maplibre's own JNI setup.
This plugin simply calls into the camera and zooms to sf bay area.
Advanced Plugin using HereMaps Gluecodium for platfrom glue
Gluecodium is a system developed by HereMaps to generate C++ code and language bindings in Swift/Java/Kotlin and Dart. You program your interface via an IDL called Lime and it will generate native c++ interfaces and platform glue to bind it.
platform/plugins/arrow-polyline-example-plugin/api/ArrowPolylineExample.lime shows our interface definitions and all the code under /generated is what gluecodium outputs.
With a system like gluecodium, you can write your plugins in C++ and expose APIs via the lime interface (like functions, structures, classes etc). This gives a stable API to the platforms and keeps the implementation in C++. However the tradeoff is going to be binary size and complexity of your build system.
I've attached screen recordings of a small plugin that draws polyline arrows with arrow pixel respecting arrow heads. This makes use of the Camera MapObserver callback and of mbgl::Style.
https://github.com/user-attachments/assets/399c8753-3228-4fce-91e5-0acab487888b
https://github.com/user-attachments/assets/b7302914-a2e1-4144-b3eb-2cb335f7d8d1