diff --git a/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml b/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml
index e12347751..7cdedd553 100644
--- a/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml
@@ -769,6 +769,18 @@
+
+
+
+
+ // --8<-- [start:loadStyle]
+ map.setStyle("https://demotiles.maplibre.org/pmtiles/raster/style-imagery.json") { style ->
+ map.cameraPosition = CameraPosition.Builder()
+ .target(LatLng(47.5, 12.0))
+ .zoom(9.0)
+ .build()
+ // --8<-- [end:loadStyle]
+ addPlaces(style)
+ }
+ }
+ }
+
+ private fun addPlaces(style: Style) {
+ // --8<-- [start:addSource]
+ val overtureSource = VectorSource(
+ "overture-places",
+ "pmtiles://https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/2026-01-21/places.pmtiles"
+ )
+ style.addSource(overtureSource)
+ val overtureLayer = CircleLayer("overture-layer", "overture-places")
+ overtureLayer.setSourceLayer("place")
+ overtureLayer.setProperties(
+ PropertyFactory.circleColor(Color.parseColor("#f5c800")),
+ PropertyFactory.circleRadius(4f),
+ PropertyFactory.circleOpacity(0.6f)
+ )
+ style.addLayer(overtureLayer)
+ // --8<-- [end:addSource]
+
+ val foursquareSource = VectorSource(
+ "foursquare-places",
+ "pmtiles://https://oliverwipfli.ch/data/foursquare-os-places-10M-2024-11-20.pmtiles"
+ )
+ style.addSource(foursquareSource)
+ val foursquareLayer = CircleLayer("foursquare-layer", "foursquare-places")
+ foursquareLayer.setSourceLayer("place")
+ foursquareLayer.setProperties(
+ PropertyFactory.circleColor(Color.parseColor("#2dd9fe")),
+ PropertyFactory.circleRadius(4f),
+ PropertyFactory.circleOpacity(0.6f)
+ )
+ style.addLayer(foursquareLayer)
+ }
+
+ @Suppress("unused")
+ private fun addLocalRasterSource(style: Style) {
+ // --8<-- [start:loadFromFile]
+ val path = getExternalFilesDir(null)?.absolutePath + "/watercolor.pmtiles"
+ val source = RasterSource(
+ "watercolor",
+ "pmtiles://file://$path",
+ 256
+ )
+ style.addSource(source)
+ style.addLayer(RasterLayer("watercolor", "watercolor"))
+ // --8<-- [end:loadFromFile]
+ }
+
+ override fun onStart() { super.onStart(); mapView.onStart() }
+ override fun onResume() { super.onResume(); mapView.onResume() }
+ override fun onPause() { super.onPause(); mapView.onPause() }
+ override fun onStop() { super.onStop(); mapView.onStop() }
+ override fun onLowMemory() { super.onLowMemory(); mapView.onLowMemory() }
+ override fun onDestroy() { super.onDestroy(); mapView.onDestroy() }
+}
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/res/layout/activity_pmtiles.xml b/platform/android/MapLibreAndroidTestApp/src/main/res/layout/activity_pmtiles.xml
new file mode 100644
index 000000000..9ac9f0bcc
--- /dev/null
+++ b/platform/android/MapLibreAndroidTestApp/src/main/res/layout/activity_pmtiles.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml b/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml
index 53faf92ba..663c890ca 100644
--- a/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml
+++ b/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml
@@ -85,6 +85,7 @@
Example Custom Geometry Source
Load a map without providing a style URI or JSON
Load MVT data
+ Load PMTiles data
Suzhou using Droid Sans for Chinese glyphs
Example raster-dem source and hillshade layer
Use HeatmapLayer to visualise earthquakes
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml b/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml
index c8c5a6e8c..30fbaf929 100644
--- a/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml
+++ b/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml
@@ -81,6 +81,7 @@
Grid Source
No Style URI/JSON
Vector Tile source
+ PMTiles
Local CJK glyph generation
Hillshade
Heatmap layer
diff --git a/platform/android/buildSrc/src/main/kotlin/Versions.kt b/platform/android/buildSrc/src/main/kotlin/Versions.kt
index 294872c09..047ca2342 100644
--- a/platform/android/buildSrc/src/main/kotlin/Versions.kt
+++ b/platform/android/buildSrc/src/main/kotlin/Versions.kt
@@ -1,4 +1,4 @@
object Versions {
- const val ndkVersion = "28.1.13356709"
+ const val ndkVersion = "28.2.13676358"
const val cmakeVersion = "3.24.0+"
}
diff --git a/platform/android/docs/data/PMTiles.md b/platform/android/docs/data/PMTiles.md
index 1800c8ce7..23ec857a6 100644
--- a/platform/android/docs/data/PMTiles.md
+++ b/platform/android/docs/data/PMTiles.md
@@ -1,17 +1,44 @@
# PMTiles
-Starting MapLibre Android 11.7.0, using [PMTiles](https://docs.protomaps.com/pmtiles/) as a data source is supported. You can prefix your vector tile source with `pmtiles://` to load a PMTiles file. The rest of the URL continue with be `https://` to load a remote PMTiles file, `asset://` to load an asset or `file://` to load a local PMTiles file.
+{{ activity_source_note("PMTilesActivity.kt") }}
-> Note: PMTiles sources do not currently support offline pack downloads.
+Starting MapLibre Android 11.7.0, [PMTiles](https://docs.protomaps.com/pmtiles/) archives are supported as tile sources. Prefix any tile source URL with `pmtiles://` to read from a PMTiles archive:
-Oliver Wipfli has made a style available that combines a [Protomaps]() basemap togehter with Foursquare's POI dataset. It is available in the [wipfli/foursquare-os-places-pmtiles](https://github.com/wipfli/foursquare-os-places-pmtiles) repository on GitHub. The style to use is
+- `pmtiles://https://` — stream tiles from a remote file
+- `pmtiles://file://` — read a file from device storage (use `getExternalFilesDir` or `filesDir` for the path)
-```
-https://raw.githubusercontent.com/wipfli/foursquare-os-places-pmtiles/refs/heads/main/style.json
+The `pmtiles://` prefix works with any [tile source type](https://maplibre.org/maplibre-style-spec/sources/) (e.g. `vector`, `raster`, `raster-dem`, etc.), from a style JSON or dynamically.
+
+Unlike MapLibre GL JS, which resolves relative URLs against the style's base URL, MapLibre Native requires the URL inside `pmtiles://` to be fully specified (e.g. `pmtiles://https://example.com/tiles.pmtiles`, not `pmtiles://tiles.pmtiles`).
+
+> Note: PMTiles sources do not support offline pack downloads or caching.
+
+## Loading a style that uses PMTiles sources
+
+Load a style JSON that references `pmtiles://` sources. The example below loads a satellite imagery basemap of the Central Alps and sets the initial camera position:
+
+```kotlin
+--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/sources/PMTilesActivity.kt:loadStyle"
```
-The neat thing about this style is that it only uses PMTiles vector sources. PMTiles can be hosted with a relatively simple file server (or file hosting service) instead of a more complex specialized tile server.
+## Adding a PMTiles source directly
-
-  }}){ width="300" }
-
+Add `vector` sources from PMTiles archives to an already-loaded style. The example overlays two places datasets — [Overture Maps](https://overturemaps.org/) (yellow) and [Foursquare OS Places](https://opensource.foursquare.com/os-places/) (blue) — both using `CircleLayer`. The `setSourceLayer` call names the layer within the archive to render:
+
+```kotlin
+--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/sources/PMTilesActivity.kt:addSource"
+```
+
+The same pattern works for `raster` archives using `RasterSource` and `RasterLayer`.
+
+> Note: `raster-dem` sources added programmatically cannot specify `encoding` via the current Android API. Define `raster-dem` sources with terrarium encoding in the style JSON instead, where the `encoding` field is fully supported.
+
+## Loading a local PMTiles file
+
+For files on device storage, use `file://` with an absolute path. The example below uses `getExternalFilesDir(null)` to locate a file downloaded to the app's external files directory:
+
+```kotlin
+--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/sources/PMTilesActivity.kt:loadFromFile"
+```
+
+> Note: `pmtiles://asset://` (files in `src/main/assets/`) is not currently supported. `AssetManagerFileSource` does not implement byte-range reads, which PMTiles requires to read its header and metadata. Use `file://` from device storage instead. See the [open issue](https://github.com/maplibre/maplibre-native/issues/4360) for status.
diff --git a/platform/ios/MapLibre.docc/ActionJournalExample.md b/platform/ios/MapLibre.docc/ActionJournalExample.md
index 8d33785b3..07f677b74 100644
--- a/platform/ios/MapLibre.docc/ActionJournalExample.md
+++ b/platform/ios/MapLibre.docc/ActionJournalExample.md
@@ -65,6 +65,7 @@ Enabling the action journal.
```swift
let options = MLNMapOptions()
options.actionJournalOptions.enabled = true
+ options.actionJournalOptions.renderingStatsReportInterval = 10
options.styleURL = AMERICANA_STYLE
mapView = MLNMapView(frame: view.bounds, options: options)
```
diff --git a/platform/ios/MapLibre.docc/CustomStyleLayerExample.md b/platform/ios/MapLibre.docc/CustomStyleLayerExample.md
index 7a7c8337d..6b3fcae89 100644
--- a/platform/ios/MapLibre.docc/CustomStyleLayerExample.md
+++ b/platform/ios/MapLibre.docc/CustomStyleLayerExample.md
@@ -89,10 +89,15 @@ class CustomStyleLayer: MLNCustomStyleLayer {
}
"""
- var error: NSError?
let device = resource.device
- let library = try? device?.makeLibrary(source: shaderSource, options: nil)
- assert(library != nil, "Error compiling shaders: \(String(describing: error))")
+ var library: MTLLibrary? = nil
+ var shaderError: Error? = nil
+ do {
+ library = try device?.makeLibrary(source: shaderSource, options: nil)
+ } catch {
+ shaderError = error
+ }
+ assert(library != nil, "Error compiling shaders: \(String(describing: shaderError))")
let vertexFunction = library?.makeFunction(name: "vertexShader")
let fragmentFunction = library?.makeFunction(name: "fragmentShader")
diff --git a/platform/ios/MapLibre.docc/ExampleStyles.md b/platform/ios/MapLibre.docc/ExampleStyles.md
index b0f2dc03d..09026765a 100644
--- a/platform/ios/MapLibre.docc/ExampleStyles.md
+++ b/platform/ios/MapLibre.docc/ExampleStyles.md
@@ -5,8 +5,9 @@ The following styles are used in the examples:
```swift
-let AMERICANA_STYLE = URL(string:
- "https://americanamap.org/style.json")
-
+let DEMOTILES_STYLE = URL(string: "https://demotiles.maplibre.org/style.json")
+let AMERICANA_STYLE = URL(string: "https://americanamap.org/style.json")
+let OPENFREEMAP_LIBERTY_STYLE = URL(string: "https://tiles.openfreemap.org/styles/liberty")
+let OPENFREEMAP_BRIGHT_STYLE = URL(string: "https://tiles.openfreemap.org/styles/bright")
let VERSATILES_COLORFUL_STYLE = URL(string: "https://tiles.versatiles.org/assets/styles/colorful.json")
```
diff --git a/platform/ios/MapLibre.docc/LocationPrivacyExample.md b/platform/ios/MapLibre.docc/LocationPrivacyExample.md
index 32a1981f9..99f8cb906 100644
--- a/platform/ios/MapLibre.docc/LocationPrivacyExample.md
+++ b/platform/ios/MapLibre.docc/LocationPrivacyExample.md
@@ -64,7 +64,7 @@ class PrivacyExampleCoordinator: NSObject, MLNMapViewDelegate {
super.init()
}
- @MainActor func mapView(_: MLNMapView, didChangeLocationManagerAuthorization manager: MLNLocationManager) {
+ func mapView(_: MLNMapView, didChangeLocationManagerAuthorization manager: MLNLocationManager) {
guard let accuracySetting = manager.accuracyAuthorization else {
return
}
diff --git a/platform/ios/MapLibre.docc/ObserverExample.md b/platform/ios/MapLibre.docc/ObserverExample.md
index f5fdc148c..b9782b2e3 100644
--- a/platform/ios/MapLibre.docc/ObserverExample.md
+++ b/platform/ios/MapLibre.docc/ObserverExample.md
@@ -13,9 +13,7 @@ Observe frame rendering statistics with ``MLNMapViewDelegate/mapViewDidFinishRen
```swift
-func mapViewDidFinishRenderingFrame(_: MLNMapView, fullyRendered: Bool, renderingStats: MLNRenderingStats) {
-
- }
+func mapViewDidFinishRenderingFrame(_: MLNMapView, fullyRendered _: Bool, renderingStats _: MLNRenderingStats) {}
```
See also: ``MLNMapViewDelegate/mapViewDidFinishRenderingFrame:fullyRendered:`` and ``MLNMapViewDelegate/mapViewDidFinishRenderingFrame:fullyRendered:frameEncodingTime:frameRenderingTime:``
diff --git a/platform/ios/MapLibre.docc/PMTiles.md b/platform/ios/MapLibre.docc/PMTiles.md
index f5b4585ff..c6b04f8e8 100644
--- a/platform/ios/MapLibre.docc/PMTiles.md
+++ b/platform/ios/MapLibre.docc/PMTiles.md
@@ -2,16 +2,133 @@
Working with PMTiles
-Starting MapLibre iOS 6.10.0, using [PMTiles](https://docs.protomaps.com/pmtiles/) as a data source is supported. You can prefix your vector tile source with `pmtiles://` to load a PMTiles file. The rest of the URL continue with be `https://` to load a remote PMTiles file, `asset://` to load an asset or `file://` to load a local PMTiles file.
+Starting MapLibre iOS 6.10.0, [PMTiles](https://docs.protomaps.com/pmtiles/) archives are supported as tile sources. Prefix any tile source URL with `pmtiles://` to read from a PMTiles archive:
-> Note: PMTiles sources do not currently support offline pack downloads.
+- `pmtiles://https://` — stream tiles from a remote file
+- `pmtiles://file://` — read a file from the device filesystem, including the app bundle
-Oliver Wipfli has made a style available that combines a [Protomaps]() basemap togehter with Foursquare's POI dataset. It is available in the [wipfli/foursquare-os-places-pmtiles](https://github.com/wipfli/foursquare-os-places-pmtiles) repository on GitHub. The style to use is
+The `pmtiles://` prefix works with any [tile source type](https://maplibre.org/maplibre-style-spec/sources/) (e.g. `vector`, `raster`, `raster-dem`, etc.), from a style JSON or dynamically.
-```
-https://raw.githubusercontent.com/wipfli/foursquare-os-places-pmtiles/refs/heads/main/style.json
+> Note: PMTiles sources do not support offline pack downloads or caching.
+
+## Loading a style that uses PMTiles sources
+
+Load a style JSON that references `pmtiles://` sources. The example below loads a satellite imagery basemap of the Central Alps and sets the initial camera position:
+
+
+
+```swift
+class PMTilesStyleURL: UIViewController {
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ let mapView = MLNMapView(
+ frame: view.bounds,
+ styleURL: URL(string: "https://demotiles.maplibre.org/pmtiles/raster/style-imagery.json")!
+ )
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.setCenter(CLLocationCoordinate2D(latitude: 47.5, longitude: 12.0), zoomLevel: 9, animated: false)
+ view.addSubview(mapView)
+ }
+}
```
-The neat thing about this style is that it only uses PMTiles vector sources. PMTiles can be hosted with a relatively simple file server (or file hosting service) instead of a more complex specialized tile server.
+## Adding a PMTiles source directly
-
+Add `vector` sources from PMTiles archives to an already-loaded style. The example overlays two places datasets — [Overture Maps](https://overturemaps.org/) (yellow) and [Foursquare OS Places](https://opensource.foursquare.com/os-places/) (blue) — both using `MLNCircleStyleLayer`. The `sourceLayerIdentifier` names the layer within the archive to render:
+
+
+
+```swift
+class PMTilesAddSource: UIViewController, MLNMapViewDelegate {
+ var mapView: MLNMapView!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ mapView = MLNMapView(frame: view.bounds)
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.delegate = self
+ view.addSubview(mapView)
+ }
+
+ func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
+ let overtureURL = URL(string: "pmtiles://https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/2026-01-21/places.pmtiles")!
+ let overtureSource = MLNVectorTileSource(identifier: "overture-places", configurationURL: overtureURL)
+ style.addSource(overtureSource)
+ let overtureLayer = MLNCircleStyleLayer(identifier: "overture-layer", source: overtureSource)
+ overtureLayer.sourceLayerIdentifier = "place"
+ overtureLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.96, green: 0.78, blue: 0.0, alpha: 1))
+ overtureLayer.circleRadius = NSExpression(forConstantValue: 4)
+ overtureLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
+ style.addLayer(overtureLayer)
+
+ let foursquareURL = URL(string: "pmtiles://https://oliverwipfli.ch/data/foursquare-os-places-10M-2024-11-20.pmtiles")!
+ let foursquareSource = MLNVectorTileSource(identifier: "foursquare-places", configurationURL: foursquareURL)
+ style.addSource(foursquareSource)
+ let foursquareLayer = MLNCircleStyleLayer(identifier: "foursquare-layer", source: foursquareSource)
+ foursquareLayer.sourceLayerIdentifier = "place"
+ foursquareLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.18, green: 0.85, blue: 1.0, alpha: 1))
+ foursquareLayer.circleRadius = NSExpression(forConstantValue: 4)
+ foursquareLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
+ style.addLayer(foursquareLayer)
+ }
+}
+```
+
+The same pattern works for `raster` archives using `MLNRasterTileSource` and `MLNRasterStyleLayer`:
+
+
+
+```swift
+class PMTilesRasterSource: UIViewController, MLNMapViewDelegate {
+ var mapView: MLNMapView!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ mapView = MLNMapView(frame: view.bounds)
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.delegate = self
+ view.addSubview(mapView)
+ }
+
+ func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
+ let url = URL(string: "pmtiles://https://demotiles.maplibre.org/pmtiles/raster/imagery.pmtiles")!
+ let source = MLNRasterTileSource(identifier: "imagery", configurationURL: url, tileSize: 256)
+ style.addSource(source)
+ let layer = MLNRasterStyleLayer(identifier: "imagery", source: source)
+ style.addLayer(layer)
+ }
+}
+```
+
+> Note: `raster-dem` sources added programmatically cannot specify `encoding` via the current iOS API. Define `raster-dem` sources with terrarium encoding in the style JSON instead, where the `encoding` field is fully supported.
+
+## Loading a local PMTiles file
+
+Bundle a `.pmtiles` file in your app target and reference it using its bundle URL. iOS app bundle files are accessible via `file://`, so no special handling is needed:
+
+
+
+```swift
+class PMTilesLocalFile: UIViewController, MLNMapViewDelegate {
+ var mapView: MLNMapView!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ mapView = MLNMapView(frame: view.bounds)
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.delegate = self
+ view.addSubview(mapView)
+ }
+
+ func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
+ guard let fileURL = Bundle.main.url(forResource: "world", withExtension: "pmtiles") else { return }
+ let url = URL(string: "pmtiles://\(fileURL.absoluteString)")!
+ let source = MLNVectorTileSource(identifier: "world", configurationURL: url)
+ style.addSource(source)
+ let layer = MLNFillStyleLayer(identifier: "countries", source: source)
+ layer.sourceLayerIdentifier = "countries"
+ layer.fillColor = NSExpression(forConstantValue: UIColor(red: 0.67, green: 0.83, blue: 0.87, alpha: 1))
+ style.addLayer(layer)
+ }
+}
+```
diff --git a/platform/ios/app-swift/Sources/PMTilesExample.swift b/platform/ios/app-swift/Sources/PMTilesExample.swift
new file mode 100644
index 000000000..33207e968
--- /dev/null
+++ b/platform/ios/app-swift/Sources/PMTilesExample.swift
@@ -0,0 +1,125 @@
+import MapLibre
+import SwiftUI
+import UIKit
+
+// #-example-code(PMTilesStyleURL)
+class PMTilesStyleURL: UIViewController {
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ let mapView = MLNMapView(
+ frame: view.bounds,
+ styleURL: URL(string: "https://demotiles.maplibre.org/pmtiles/raster/style-imagery.json")!
+ )
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.setCenter(CLLocationCoordinate2D(latitude: 47.5, longitude: 12.0), zoomLevel: 9, animated: false)
+ view.addSubview(mapView)
+ }
+}
+
+// #-end-example-code
+
+// #-example-code(PMTilesAddSource)
+class PMTilesAddSource: UIViewController, MLNMapViewDelegate {
+ var mapView: MLNMapView!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ mapView = MLNMapView(frame: view.bounds)
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.delegate = self
+ view.addSubview(mapView)
+ }
+
+ func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
+ let overtureURL = URL(string: "pmtiles://https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/2026-01-21/places.pmtiles")!
+ let overtureSource = MLNVectorTileSource(identifier: "overture-places", configurationURL: overtureURL)
+ style.addSource(overtureSource)
+ let overtureLayer = MLNCircleStyleLayer(identifier: "overture-layer", source: overtureSource)
+ overtureLayer.sourceLayerIdentifier = "place"
+ overtureLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.96, green: 0.78, blue: 0.0, alpha: 1))
+ overtureLayer.circleRadius = NSExpression(forConstantValue: 4)
+ overtureLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
+ style.addLayer(overtureLayer)
+
+ let foursquareURL = URL(string: "pmtiles://https://oliverwipfli.ch/data/foursquare-os-places-10M-2024-11-20.pmtiles")!
+ let foursquareSource = MLNVectorTileSource(identifier: "foursquare-places", configurationURL: foursquareURL)
+ style.addSource(foursquareSource)
+ let foursquareLayer = MLNCircleStyleLayer(identifier: "foursquare-layer", source: foursquareSource)
+ foursquareLayer.sourceLayerIdentifier = "place"
+ foursquareLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.18, green: 0.85, blue: 1.0, alpha: 1))
+ foursquareLayer.circleRadius = NSExpression(forConstantValue: 4)
+ foursquareLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
+ style.addLayer(foursquareLayer)
+ }
+}
+
+// #-end-example-code
+
+// #-example-code(PMTilesRasterSource)
+class PMTilesRasterSource: UIViewController, MLNMapViewDelegate {
+ var mapView: MLNMapView!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ mapView = MLNMapView(frame: view.bounds)
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.delegate = self
+ view.addSubview(mapView)
+ }
+
+ func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
+ let url = URL(string: "pmtiles://https://demotiles.maplibre.org/pmtiles/raster/imagery.pmtiles")!
+ let source = MLNRasterTileSource(identifier: "imagery", configurationURL: url, tileSize: 256)
+ style.addSource(source)
+ let layer = MLNRasterStyleLayer(identifier: "imagery", source: source)
+ style.addLayer(layer)
+ }
+}
+
+// #-end-example-code
+
+// #-example-code(PMTilesLocalFile)
+class PMTilesLocalFile: UIViewController, MLNMapViewDelegate {
+ var mapView: MLNMapView!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ mapView = MLNMapView(frame: view.bounds)
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.delegate = self
+ view.addSubview(mapView)
+ }
+
+ func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
+ guard let fileURL = Bundle.main.url(forResource: "world", withExtension: "pmtiles") else { return }
+ let url = URL(string: "pmtiles://\(fileURL.absoluteString)")!
+ let source = MLNVectorTileSource(identifier: "world", configurationURL: url)
+ style.addSource(source)
+ let layer = MLNFillStyleLayer(identifier: "countries", source: source)
+ layer.sourceLayerIdentifier = "countries"
+ layer.fillColor = NSExpression(forConstantValue: UIColor(red: 0.67, green: 0.83, blue: 0.87, alpha: 1))
+ style.addLayer(layer)
+ }
+}
+
+// #-end-example-code
+
+struct PMTilesStyleURLRepresentable: UIViewControllerRepresentable {
+ func makeUIViewController(context _: Context) -> PMTilesStyleURL { PMTilesStyleURL() }
+ func updateUIViewController(_: PMTilesStyleURL, context _: Context) {}
+}
+
+struct PMTilesAddSourceRepresentable: UIViewControllerRepresentable {
+ func makeUIViewController(context _: Context) -> PMTilesAddSource { PMTilesAddSource() }
+ func updateUIViewController(_: PMTilesAddSource, context _: Context) {}
+}
+
+struct PMTilesRasterSourceRepresentable: UIViewControllerRepresentable {
+ func makeUIViewController(context _: Context) -> PMTilesRasterSource { PMTilesRasterSource() }
+ func updateUIViewController(_: PMTilesRasterSource, context _: Context) {}
+}
+
+struct PMTilesLocalFileRepresentable: UIViewControllerRepresentable {
+ func makeUIViewController(context _: Context) -> PMTilesLocalFile { PMTilesLocalFile() }
+ func updateUIViewController(_: PMTilesLocalFile, context _: Context) {}
+}
diff --git a/render-test/android/app/build.gradle.kts b/render-test/android/app/build.gradle.kts
index aca56f883..a01878a8c 100644
--- a/render-test/android/app/build.gradle.kts
+++ b/render-test/android/app/build.gradle.kts
@@ -4,7 +4,7 @@ plugins {
}
android {
- ndkVersion = "28.1.13356709"
+ ndkVersion = "28.2.13676358"
sourceSets {
getByName("test") {