Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.maplibre.maplibregl;

import org.maplibre.android.module.http.HttpRequestUtil;
import io.flutter.plugin.common.MethodChannel;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.regex.Pattern;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import android.util.Log;

public class MapLibreCustomHttpInterceptor {
private static final String TAG = "MapLibreCustomHttpInterceptor";
public static final HashMap<String, String> CustomHeaders = new HashMap<>();
public static final List<String> Filter = new ArrayList<>();

public static void setCustomHeaders(Map<String, String> headers, List<String> filter, MethodChannel.Result result) {
CustomHeaders.clear();
Filter.clear();

for (Map.Entry<String, String> entry : headers.entrySet()) {
CustomHeaders.put(entry.getKey(), entry.getValue());
Log.d(TAG, "Setting " + entry.getKey() + " to " + entry.getValue());
}

for (String pattern : filter) {
Filter.add(pattern);
}

HttpRequestUtil.setOkHttpClient(getOkHttpClient().build());
result.success(null);
}

private static OkHttpClient.Builder getOkHttpClient() {
try {
return new OkHttpClient.Builder()
.addNetworkInterceptor(
chain -> {
Request.Builder builder = chain.request().newBuilder();
String url = chain.request().url().toString();

// Check if URL matches any filter pattern
boolean shouldApplyHeaders = Filter.isEmpty();
for (String pattern : Filter) {
if (Pattern.matches(pattern, url)) {
shouldApplyHeaders = true;
break;
}
}

if (shouldApplyHeaders) {
for (Map.Entry<String, String> header : CustomHeaders.entrySet()) {
if (header.getKey() == null || header.getKey().trim().isEmpty()) {
continue;
}
if (header.getValue() == null || header.getValue().trim().isEmpty()) {
builder.removeHeader(header.getKey());
} else {
builder.header(header.getKey(), header.getValue());
}
}
}

return chain.proceed(builder.build());
});
} catch (Exception e) {
Log.e(TAG, "Error creating HTTP client: " + e.getMessage());
throw new RuntimeException(e);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import org.maplibre.android.style.sources.VectorSource;
import org.maplibre.geojson.Feature;
import org.maplibre.geojson.FeatureCollection;
import org.maplibre.android.net.ConnectivityReceiver;

import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -923,6 +924,174 @@ public void onCancel() {
result.success(false);
break;
}
case "map#setMaximumFps":
{
final int fps = call.argument("fps");
if (mapView != null) {
mapView.setMaximumFps(fps);
}
result.success(null);
break;
}
case "map#forceOnlineMode":
{
// Force online mode by setting connectivity to true
if (mapView != null) {
ConnectivityReceiver.instance(mapView.getContext()).setConnected(true);
}
result.success(null);
break;
}
case "camera#ease":
{
final CameraUpdate cameraUpdate = Convert.toCameraUpdate(call.argument("cameraUpdate"), mapLibreMap, density);
final Integer duration = call.argument("duration");

final OnCameraMoveFinishedListener onCameraMoveFinishedListener =
new OnCameraMoveFinishedListener() {
@Override
public void onFinish() {
super.onFinish();
result.success(true);
}

@Override
public void onCancel() {
super.onCancel();
result.success(false);
}
};

if (cameraUpdate != null && duration != null && duration > 0) {
// camera transformation not handled yet
mapLibreMap.easeCamera(cameraUpdate, duration, false, onCameraMoveFinishedListener);
} else if (cameraUpdate != null) {
// camera transformation not handled yet
mapLibreMap.easeCamera(cameraUpdate, onCameraMoveFinishedListener);
} else {
result.success(false);
}
break;
}
case "map#queryCameraPosition":
{
result.success(Convert.toJson(mapLibreMap.getCameraPosition()));
break;
}
case "map#editGeoJsonSource":
{
boolean ret = false;
if (mapLibreMap != null) {
Style style = mapLibreMap.getStyle();
if (style != null) {
try {
GeoJsonSource source = style.getSourceAs(call.argument("id"));
if (source != null) {
source.setGeoJson((String)call.argument("data"));
ret = true;
}
} catch (Exception e) {}
}
}
Map<String, Boolean> reply = new HashMap<>();
reply.put("result", ret);
result.success(reply);
break;
}
case "map#editGeoJsonUrl":
{
boolean ret = false;
if (mapLibreMap != null) {
Style style = mapLibreMap.getStyle();
if (style != null) {
try {
GeoJsonSource source = style.getSourceAs(call.argument("id"));
if (source != null) {
source.setUrl((String)call.argument("url"));
ret = true;
}
} catch (Exception e) {}
}
}
Map<String, Boolean> reply = new HashMap<>();
reply.put("result", ret);
result.success(reply);
break;
}
case "map#setLayerFilter":
{
boolean ret = false;
if (mapLibreMap != null) {
Style style = mapLibreMap.getStyle();
if (style != null) {
try {
Layer layer = style.getLayer(call.argument("id"));
if (layer != null) {
String filter = call.argument("filter");
if (filter != null) {
Expression expression = Expression.raw(filter);
if (expression != null) {
if (layer instanceof LineLayer) {
((LineLayer)layer).setFilter(expression);
ret = true;
} else if (layer instanceof FillLayer) {
((FillLayer)layer).setFilter(expression);
ret = true;
} else if (layer instanceof SymbolLayer) {
((SymbolLayer)layer).setFilter(expression);
ret = true;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Map<String, Boolean> reply = new HashMap<>();
reply.put("result", ret);
result.success(reply);
break;
}
case "map#getStyle":
{
Map<String, Object> reply = new HashMap<>();
boolean ret = false;
if (mapLibreMap != null) {
Style style = mapLibreMap.getStyle();
if (style != null) {
try {
String json = style.getJson();
reply.put("json", json);
ret = true;
} catch (Exception e) {}
}
}
reply.put("result", ret);
result.success(reply);
break;
}
case "map#setCustomHeaders":
{
if (mapLibreMap != null) {
HashMap<String, String> headers = (HashMap<String, String>)call.argument("headers");
List<String> filter = (List<String>)call.argument("filter");
MapLibreCustomHttpInterceptor.setCustomHeaders(headers, filter, result);
} else {
result.success(null);
}
break;
}
case "map#getCustomHeaders":
{
if (mapLibreMap != null) {
result.success(MapLibreCustomHttpInterceptor.CustomHeaders);
} else {
result.success(null);
}
break;
}
case "map#invalidateAmbientCache":
{
OfflineManager fileSource = OfflineManager.Companion.getInstance(context);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Foundation
import MapLibre

public class MapLibreCustomHeaders {
private static var customHeaders: [String: String] = [:]
private static var filterPatterns: [String] = []

public static func setCustomHeaders(_ headers: [String: String], filter: [String]) {
customHeaders = headers
filterPatterns = filter

let sessionConfig = URLSessionConfiguration.default
sessionConfig.httpAdditionalHeaders = headers
MLNNetworkConfiguration.sharedManager.sessionConfiguration = sessionConfig
}

public static func getCustomHeaders() -> [String: String] {
return customHeaders
}

public static func getFilterPatterns() -> [String] {
return filterPatterns
}

public static func shouldApplyHeaders(to url: String) -> Bool {
if filterPatterns.isEmpty {
return true
}

for pattern in filterPatterns {
if url.range(of: pattern, options: .regularExpression) != nil {
return true
}
}

return false
}
}

Loading