Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,7 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_properties.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_factory.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_file_source.hpp
)


Expand Down
1 change: 1 addition & 0 deletions bazel/core.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ MLN_LAYER_PLUGIN_HEADERS = [
"src/mbgl/plugin/plugin_layer_impl.hpp",
"src/mbgl/plugin/plugin_layer_render.hpp",
"src/mbgl/plugin/plugin_layer_properties.hpp",
"src/mbgl/plugin/plugin_file_source.hpp",
]

MLN_LAYER_PLUGIN_SOURCE = [
Expand Down
3 changes: 2 additions & 1 deletion include/mbgl/storage/file_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ enum FileSourceType : uint8_t {
Network,
Mbtiles,
Pmtiles,
ResourceLoader ///< %Resource loader acts as a proxy and has logic
ResourceLoader, ///< %Resource loader acts as a proxy and has logic
/// for request delegation to Asset, Cache, and other
/// file sources.
Custom // These are the plugin file resource types
};

// TODO: Rename to ResourceProvider to avoid confusion with
Expand Down
6 changes: 6 additions & 0 deletions include/mbgl/storage/file_source_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ class FileSourceManager {
// a FileSourceType invocation has no effect.
virtual FileSourceFactory unRegisterFileSourceFactory(FileSourceType) noexcept;

// Registers a custom file source
virtual void registerCustomFileSource(std::shared_ptr<FileSource>) noexcept;

// Returns an array of custom file sources
virtual std::vector<std::shared_ptr<FileSource>> getCustomFileSources() noexcept;

protected:
FileSourceManager();
class Impl;
Expand Down
2 changes: 2 additions & 0 deletions platform/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ objc_library(
"//platform/darwin:app/CustomStyleLayerExample.m",
"//platform/darwin:app/PluginLayerExample.h",
"//platform/darwin:app/PluginLayerExample.mm",
"//platform/darwin:app/PluginProtocolExample.h",
"//platform/darwin:app/PluginProtocolExample.mm",
"//platform/darwin:app/PluginLayerExampleMetalRendering.h",
"//platform/darwin:app/PluginLayerExampleMetalRendering.mm",
"//platform/ios:ios_app_srcs",
Expand Down
6 changes: 6 additions & 0 deletions platform/android/MapLibreAndroid/src/cpp/jni_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "native_map_options.hpp"
#include "rendering_stats.hpp"
#include "util/tile_server_options.hpp"
#include "plugin/plugin_file_source.hpp"
#ifndef MBGL_MODULE_OFFLINE_DISABLE
#include "offline/offline_manager.hpp"
#include "offline/offline_region.hpp"
Expand Down Expand Up @@ -107,6 +108,11 @@ void registerNatives(JavaVM* vm) {
Polygon::registerNative(env);
Polyline::registerNative(env);

// Plugins
PluginProtocolHandlerResource::registerNative(env);
PluginProtocolHandlerResponse::registerNative(env);
PluginFileSource::registerNative(env);

// Map
MapRenderer::registerNative(env);
MapRendererRunnable::registerNative(env);
Expand Down
102 changes: 101 additions & 1 deletion platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <mbgl/style/image.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/renderer/query.hpp>
#include <mbgl/plugin/plugin_file_source.hpp>
#include <mbgl/storage/file_source_manager.hpp>

// Java -> C++ conversion
#include "style/android_conversion.hpp"
Expand Down Expand Up @@ -1328,6 +1330,103 @@ void NativeMapView::setFrustumOffset(JNIEnv& env, const jni::Object<RectF>& padd
map->setFrustumOffset(offset);
}

// Plugins
void NativeMapView::addPluginFileSource(JNIEnv &jniEnv,
const jni::Object<PluginFileSource>& pluginFileSource) {

// TODO: Unclear if any of these options are needed for plugins
mbgl::ResourceOptions resourceOptions;

// TODO: Unclear if any of the properties on clientOptions need to be set
mbgl::ClientOptions clientOptions;

android::UniqueEnv _env = android::AttachEnv();

// Set when the source is added to a map.
jni::Global<jni::Object<PluginFileSource>> pluginPeer = jni::NewGlobal(*_env, pluginFileSource);
std::shared_ptr<PluginFileSourceContainer> fileSourceContainer = std::make_shared<PluginFileSourceContainer>();
fileSourceContainer->_fileSource = std::move(pluginPeer);
_pluginFileSources.push_back(fileSourceContainer);

std::shared_ptr<mbgl::PluginFileSource> pluginSource = std::make_shared<mbgl::PluginFileSource>(resourceOptions, clientOptions);
pluginSource->setOnRequestResourceFunction([fileSourceContainer](const mbgl::Resource &resource) -> mbgl::Response {
mbgl::Response tempResponse;

android::UniqueEnv env = android::AttachEnv();
static auto& javaClass = jni::Class<PluginFileSource>::Singleton(*env);
static auto requestResource = javaClass.GetMethod<jni::Object<PluginProtocolHandlerResponse>(jni::Object<PluginProtocolHandlerResource>)>(*env, "requestResource");
auto javaResource = PluginFileSource::createJavaResource(*env, resource);
auto tempResult = fileSourceContainer->_fileSource.Call(*env, requestResource, javaResource);
PluginProtocolHandlerResponse::Update(*env,
tempResult,
tempResponse);

return tempResponse;
});
pluginSource->setOnCanRequestFunction([fileSourceContainer](const mbgl::Resource &resource) -> bool {
android::UniqueEnv env = android::AttachEnv();
static auto& javaClass = jni::Class<PluginFileSource>::Singleton(*env);
static auto canRequestResource = javaClass.GetMethod<jboolean(jni::Object<PluginProtocolHandlerResource>)>(*env, "canRequestResource");
auto javaResource = PluginFileSource::createJavaResource(*env, resource);
auto tempResult = fileSourceContainer->_fileSource.Call(*env, canRequestResource, javaResource);
return tempResult;


/*
if (!renderingStats) {
renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env));
}

RenderingStats::Update(*_env, renderingStats, status.renderingStats);

weakReference.Call(*_env,
onDidFinishRenderingFrame,
(jboolean)(status.mode != MapObserver::RenderMode::Partial),
renderingStats);
*/
/*
static auto resourceURLField = javaClass.GetField<jni::Object<PluginProtocolHandlerResource>>(env, "resource");
auto str = jni::Make<jni::String>(env, resource.url); // wrap the jstring
javaObject.Set(env, resourceURLField, str);

fileSourceContainer->_fileSource.Set(env, )
*/




});
auto fileSourceManager = mbgl::FileSourceManager::get();
fileSourceManager->registerCustomFileSource(pluginSource);


/*
android::UniqueEnv _env = android::AttachEnv();
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
static auto onDidFinishRenderingFrame = javaClass.GetMethod<void(jboolean, jni::Object<RenderingStats>)>(
*_env, "onDidFinishRenderingFrame");
auto weakReference = javaPeer.get(*_env);
if (weakReference) {
if (!renderingStats) {
renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env));
}

RenderingStats::Update(*_env, renderingStats, status.renderingStats);

weakReference.Call(*_env,
onDidFinishRenderingFrame,
(jboolean)(status.mode != MapObserver::RenderMode::Partial),
renderingStats);
}

*/



}



// Static methods //

void NativeMapView::registerNative(jni::JNIEnv& env) {
Expand Down Expand Up @@ -1451,7 +1550,8 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"),
METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"),
METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"),
METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset"));
METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset"),
METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource"));
}

void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {};
Expand Down
9 changes: 8 additions & 1 deletion platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "style/light.hpp"
#include "native_map_options.hpp"
#include "bitmap.hpp"

#include "plugin/plugin_file_source.hpp"
#include <exception>
#include <string>
#include <jni.h>
Expand Down Expand Up @@ -327,6 +327,10 @@ class NativeMapView : public MapObserver {

void setFrustumOffset(JNIEnv&, const jni::Object<RectF>&);

// Plugins
void addPluginFileSource(JNIEnv &,
const jni::Object<mbgl::android::PluginFileSource>&);

// Shader compilation
void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override;
void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override;
Expand Down Expand Up @@ -368,6 +372,9 @@ class NativeMapView : public MapObserver {

// Ensure these are initialised last
std::unique_ptr<mbgl::Map> map;

// List of plugin file source
std::vector<std::shared_ptr<mbgl::android::PluginFileSourceContainer>> _pluginFileSources;
};

} // namespace android
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@

#include "plugin_file_source.hpp"

using namespace mbgl::android;

// Putting these here (should probably move out to a more dedicated JNI place within
// the native repo at some point, but this means we don't have to update
// the jni.hpp dependency
namespace jni {

struct ByteBufferTag
{
static constexpr auto Name() { return "java/nio/ByteBuffer"; }
};

template <>
struct TagTraits< ByteBufferTag >
{
using SuperType = Object<ObjectTag>;
using UntaggedType = jobject;
};

}

void PluginFileSource::registerNative(jni::JNIEnv& env) {
jni::Class<PluginFileSource>::Singleton(env);
}

jni::Global<jni::Object<PluginProtocolHandlerResource>> PluginFileSource::createJavaResource(jni::JNIEnv& env,
const mbgl::Resource &resource) {
jni::Global<jni::Object<PluginProtocolHandlerResource>> tempResult = jni::NewGlobal(env, PluginProtocolHandlerResource::Create(env));
PluginProtocolHandlerResource::Update(env, tempResult, resource);
return tempResult;
}

void PluginProtocolHandlerResource::registerNative(jni::JNIEnv& env) {
jni::Class<PluginProtocolHandlerResource>::Singleton(env);
}

jni::Local<jni::Object<PluginProtocolHandlerResource>> PluginProtocolHandlerResource::Create(jni::JNIEnv& env) {
auto& javaClass = jni::Class<PluginProtocolHandlerResource>::Singleton(env);
auto constructor = javaClass.GetConstructor(env);
return javaClass.New(env, constructor);
}

void PluginProtocolHandlerResource::Update(jni::JNIEnv& env,
jni::Object<PluginProtocolHandlerResource>& javaObject,
const mbgl::Resource &resource) {

static auto &javaClass = jni::Class<PluginProtocolHandlerResource>::Singleton(env);

static auto resourceKindField = javaClass.GetField<jni::jint>(env, "kind");
javaObject.Set(env, resourceKindField, static_cast<jni::jint>(resource.kind));

static auto resourceURLField = javaClass.GetField<jni::String>(env, "resourceURL");
auto str = jni::Make<jni::String>(env, resource.url); // wrap the jstring
javaObject.Set(env, resourceURLField, str);

}


void PluginProtocolHandlerResponse::registerNative(jni::JNIEnv& env) {
jni::Class<PluginProtocolHandlerResponse>::Singleton(env);
}

jni::Local<jni::Object<PluginProtocolHandlerResponse>> PluginProtocolHandlerResponse::Create(jni::JNIEnv&env) {
auto& javaClass = jni::Class<PluginProtocolHandlerResponse>::Singleton(env);
auto constructor = javaClass.GetConstructor(env);
return javaClass.New(env, constructor);
}

void PluginProtocolHandlerResponse::Update(jni::JNIEnv & env,
[[maybe_unused]] jni::Object<PluginProtocolHandlerResponse>& javaObject,
[[maybe_unused]] mbgl::Response &response) {
static auto &javaClass = jni::Class<PluginProtocolHandlerResponse>::Singleton(env);
static auto dataField = javaClass.GetField<jni::Object<jni::ByteBufferTag>>(env, "data");
auto objectValue = javaObject.Get(env, dataField);
auto objectRef = jobject(objectValue.get());
void* bufPtr = env.GetDirectBufferAddress(objectRef);
jsize length = env.GetDirectBufferCapacity(objectRef);
response.data = std::make_shared<std::string>((const char*)bufPtr, length);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <jni/jni.hpp>
#include <mbgl/plugin/plugin_file_source.hpp>

namespace mbgl {
namespace android {

class PluginProtocolHandlerResource {
public:
static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResource"; };
static void registerNative(jni::JNIEnv&);

static jni::Local<jni::Object<PluginProtocolHandlerResource>> Create(jni::JNIEnv&);
static void Update(jni::JNIEnv&, jni::Object<PluginProtocolHandlerResource>&, const mbgl::Resource &);
};

class PluginProtocolHandlerResponse {
public:
static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResponse"; };
static void registerNative(jni::JNIEnv&);

static jni::Local<jni::Object<PluginProtocolHandlerResponse>> Create(jni::JNIEnv&);
static void Update(jni::JNIEnv&,
jni::Object<PluginProtocolHandlerResponse>&,
mbgl::Response &);

};

class PluginFileSource {
public:
static constexpr auto Name() { return "org/maplibre/android/plugin/PluginFileSource"; };

//static mbgl::PluginFileSource getFileSource(jni::JNIEnv&, const jni::Object<PluginFileSource>&);

static jni::Global<jni::Object<PluginProtocolHandlerResource>> createJavaResource(jni::JNIEnv& env,
const mbgl::Resource &resource);

static void registerNative(jni::JNIEnv&);
};

class PluginFileSourceContainer {
public:
jni::Global<jni::Object<PluginFileSource>> _fileSource;
};

}
}


Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.maplibre.android.gestures.RotateGestureDetector;
import org.maplibre.android.gestures.ShoveGestureDetector;
import org.maplibre.android.gestures.StandardScaleGestureDetector;
import org.maplibre.android.plugin.PluginProtocolHandler;
import org.maplibre.geojson.Feature;
import org.maplibre.geojson.Geometry;
import org.maplibre.android.MapStrictMode;
Expand Down Expand Up @@ -2706,4 +2707,19 @@ private void notifyDeveloperAnimationListeners() {
listener.onDeveloperAnimationStarted();
}
}



/**
* Adds a custom protocol handler to the map view
*/
ArrayList<PluginProtocolHandler> pluginProtocolHandlers = new ArrayList<PluginProtocolHandler>();
public void addPluginProtocolHandler(PluginProtocolHandler protocolHandler) {
pluginProtocolHandlers.add(protocolHandler);
nativeMapView.addPluginProtocolHandler(protocolHandler);

// nativeMapView.addPolygon()
}


}
Loading
Loading