diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index 92c277418..6f824e764 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -10,6 +10,7 @@
### ✨ Features and improvements
+- Add support for custom `ModuleProvider` implementations (#[2231](https://github.com/maplibre/maplibre-native/pull/2231))
- Allow setting padding when camera is tracking (#[2165](https://github.com/maplibre/maplibre-native/pull/2165)).
- Add support for the [`slice` expression](https://maplibre.org/maplibre-style-spec/expressions/#slice) ([#1113](https://github.com/maplibre/maplibre-native/pull/1133))
- Add support for the [`index-of` expression](https://maplibre.org/maplibre-style-spec/expressions/#index-of) ([#1113](https://github.com/maplibre/maplibre-native/pull/1113))
diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/MapLibre.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/MapLibre.java
index 4ed7255b8..76b044a6f 100644
--- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/MapLibre.java
+++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/MapLibre.java
@@ -231,6 +231,14 @@ public final class MapLibre {
return moduleProvider;
}
+ /**
+ * Set the module provider. Call this as soon as possible.
+ * @param provider The ModuleProvider instance to set
+ */
+ public static void setModuleProvider(ModuleProvider provider) {
+ moduleProvider = provider;
+ }
+
/**
* Runtime validation of MapLibre creation.
*/
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml b/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml
index 54132f347..2506de637 100644
--- a/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml
@@ -843,6 +843,18 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity" />
+
+
+
+
(R.id.mapView) as MapView
+ mapView.onCreate(savedInstanceState)
+ mapView.getMapAsync(
+ OnMapReadyCallback { maplibreMap: MapLibreMap ->
+ maplibreMap.setStyle(Style.Builder().fromUri("https://demotiles.maplibre.org/style.json"))
+ }
+ )
+ }
+
+ 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 onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ mapView.onSaveInstanceState(outState)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+
+ // Example of how to reset the module provider
+ MapLibre.setModuleProvider(ModuleProviderImpl())
+ mapView.onDestroy()
+ }
+
+ override fun onLowMemory() {
+ super.onLowMemory()
+ mapView.onLowMemory()
+ }
+}
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ExampleCustomModuleProviderImpl.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ExampleCustomModuleProviderImpl.kt
new file mode 100644
index 000000000..8e230483f
--- /dev/null
+++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ExampleCustomModuleProviderImpl.kt
@@ -0,0 +1,21 @@
+package org.maplibre.android.testapp.utils
+
+import org.maplibre.android.LibraryLoaderProvider
+import org.maplibre.android.ModuleProvider
+import org.maplibre.android.http.HttpRequest
+import org.maplibre.android.module.loader.LibraryLoaderProviderImpl
+import org.maplibre.android.testapp.utils.ExampleHttpRequestImpl
+
+/*
+ * An example implementation of the ModuleProvider. This is useful primarily for providing
+ * a custom implementation of HttpRequest used by the core.
+ */
+class ExampleCustomModuleProviderImpl : ModuleProvider {
+ override fun createHttpRequest(): HttpRequest {
+ return ExampleHttpRequestImpl()
+ }
+
+ override fun createLibraryLoaderProvider(): LibraryLoaderProvider {
+ return LibraryLoaderProviderImpl()
+ }
+}
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ExampleHttpRequestImpl.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ExampleHttpRequestImpl.kt
new file mode 100644
index 000000000..a9d284069
--- /dev/null
+++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ExampleHttpRequestImpl.kt
@@ -0,0 +1,40 @@
+package org.maplibre.android.testapp.utils
+
+import org.maplibre.android.http.HttpResponder
+import org.maplibre.android.http.HttpRequest
+import org.maplibre.android.module.http.HttpRequestImpl
+
+/*
+ * An example implementation of HttpRequest for use with a custom implementation of
+ * the ModuleProvider. This allows you to provide your own transport mechanism for HTTP
+ * requests made by the library.
+ */
+class ExampleHttpRequestImpl : HttpRequest {
+ override fun executeRequest(httpRequest: HttpResponder, nativePtr: Long, resourceUrl: String,
+ etag: String, modified: String, offlineUsage: Boolean)
+ {
+ // Load all json documents and any pbf ending with a 0.
+ if (resourceUrl.endsWith(".json") || resourceUrl.endsWith("0.pbf")) {
+ impl.executeRequest(httpRequest, nativePtr, resourceUrl, etag, modified, offlineUsage)
+ } else {
+ // All other requests get an instant 404!
+ httpRequest.onResponse(
+ /* responseCode */ 404,
+ /* eTag */ etag,
+ /* lastModified */ "",
+ /* cacheControl */ "",
+ /* expires */ "",
+ /* retryAfter */ "",
+ /* xRateLimitReset */ "",
+ /* body */ byteArrayOf(0x0)
+ )
+ }
+ }
+
+ override fun cancelRequest() {
+ impl.cancelRequest()
+ }
+
+ // The default implementation using okhttp
+ private var impl: HttpRequestImpl = HttpRequestImpl()
+}
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml b/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml
index 6ac420127..6ad36b830 100644
--- a/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml
+++ b/platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml
@@ -58,6 +58,7 @@
Show bus stops and route in Singapore
Verify that updating the GeoJsonSource across style changes allows for smooth transitions
Transform urls on the fly
+ Provides a custom HTTP implementation for fetching network resources
Control the cache management with FileSource API
Limit viewport to Iceland
Shows how to add 3D extruded shapes
diff --git a/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml b/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml
index dc4d597ae..3a7becde3 100644
--- a/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml
+++ b/platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml
@@ -54,6 +54,7 @@
Visibility Map
Dialog with map
Url transform
+ Custom HTTPRequestImpl
Cache management
Restrict camera to a bounds
Fill extrusions