Move JNI bindings code from mapbox-gl-native to this repo. (#301)
This commit is contained in:
206
MapboxGLAndroidSDK/src/cpp/CMakeLists.txt
Normal file
206
MapboxGLAndroidSDK/src/cpp/CMakeLists.txt
Normal file
@@ -0,0 +1,206 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
add_subdirectory(../../../vendor/mapbox-gl-native ../../../vendor/mapbox-gl-native)
|
||||
|
||||
add_library(
|
||||
mapbox-gl SHARED
|
||||
${PROJECT_SOURCE_DIR}/main.cpp
|
||||
${PROJECT_SOURCE_DIR}/jni_native.cpp
|
||||
${PROJECT_SOURCE_DIR}/jni_native.hpp
|
||||
${PROJECT_SOURCE_DIR}/file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/file_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/http_file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/collator.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/collator_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/number_format.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/number_format_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/logger.cpp
|
||||
${PROJECT_SOURCE_DIR}/logger.hpp
|
||||
${PROJECT_SOURCE_DIR}/logging_android.cpp
|
||||
${PROJECT_SOURCE_DIR}/text/local_glyph_rasterizer.cpp
|
||||
${PROJECT_SOURCE_DIR}/text/local_glyph_rasterizer_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_backend.cpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_backend.hpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_frontend.cpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_frontend.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/marker.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/marker.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/multi_point.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polyline.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polyline.hpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager_file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager_file_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/connectivity_listener.cpp
|
||||
${PROJECT_SOURCE_DIR}/connectivity_listener.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/color.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/color.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/constant.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/constant.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/conversion.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature_collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature_collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry_collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry_collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/line_string.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/line_string.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_line_string.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_line_string.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_point.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_point.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/point.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/point.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_bounds.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_bounds.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_quad.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_quad.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/projected_meters.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/projected_meters.hpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/pointf.cpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/pointf.hpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/rectf.cpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/rectf.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_array.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_array.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_element.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_element.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_object.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_object.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_primitive.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_primitive.hpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.cpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.cpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.hpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.cpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.cpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.hpp
|
||||
${PROJECT_SOURCE_DIR}/mapbox.cpp
|
||||
${PROJECT_SOURCE_DIR}/mapbox.hpp
|
||||
${PROJECT_SOURCE_DIR}/map/camera_position.cpp
|
||||
${PROJECT_SOURCE_DIR}/map/camera_position.hpp
|
||||
${PROJECT_SOURCE_DIR}/map/image.cpp
|
||||
${PROJECT_SOURCE_DIR}/map/image.hpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer.cpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer.hpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer_runnable.cpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer_runnable.hpp
|
||||
${PROJECT_SOURCE_DIR}/native_map_view.cpp
|
||||
${PROJECT_SOURCE_DIR}/native_map_view.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_definition.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_definition.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_error.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_error.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_status.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_status.hpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshot.cpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshot.hpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshotter.cpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshotter.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/android_conversion.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/filter.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/filter.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/position.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/position.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/property_expression.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/property_value.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/transition_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/url_or_tileset.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/url_or_tileset.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted_section.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted_section.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/background_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/background_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/heatmap_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/heatmap_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/hillshade_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/hillshade_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/line_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/line_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/raster_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/raster_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/symbol_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/symbol_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/light.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/light.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/position.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/position.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/custom_geometry_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/custom_geometry_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/geojson_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/geojson_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/image_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/image_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_dem_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_dem_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/unknown_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/unknown_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/vector_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/vector_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/transition_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.hpp
|
||||
)
|
||||
|
||||
|
||||
target_include_directories(
|
||||
mapbox-gl
|
||||
PRIVATE
|
||||
${PROJECT_SOURCE_DIR}
|
||||
../../../vendor/mapbox-gl-native/src
|
||||
../../../vendor/mapbox-gl-native/platform/android/src
|
||||
../../../vendor/mapbox-gl-native/platform/default/include
|
||||
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
mapbox-gl
|
||||
PRIVATE
|
||||
mbgl-compiler-options
|
||||
Mapbox::Base::jni.hpp
|
||||
mbgl-core
|
||||
mbgl-vendor-unique_resource
|
||||
|
||||
)
|
||||
|
||||
install(TARGETS mapbox-gl LIBRARY DESTINATION lib)
|
||||
67
MapboxGLAndroidSDK/src/cpp/android_renderer_backend.cpp
Executable file
67
MapboxGLAndroidSDK/src/cpp/android_renderer_backend.cpp
Executable file
@@ -0,0 +1,67 @@
|
||||
#include "android_renderer_backend.hpp"
|
||||
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/gl/renderable_resource.hpp>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidGLRenderableResource final : public mbgl::gl::RenderableResource {
|
||||
public:
|
||||
AndroidGLRenderableResource(AndroidRendererBackend& backend_) : backend(backend_) {
|
||||
}
|
||||
|
||||
void bind() override {
|
||||
assert(gfx::BackendScope::exists());
|
||||
backend.setFramebufferBinding(0);
|
||||
backend.setViewport(0, 0, backend.getSize());
|
||||
}
|
||||
|
||||
private:
|
||||
AndroidRendererBackend& backend;
|
||||
};
|
||||
|
||||
AndroidRendererBackend::AndroidRendererBackend()
|
||||
: gl::RendererBackend(gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable({ 64, 64 }, std::make_unique<AndroidGLRenderableResource>(*this)) {
|
||||
}
|
||||
|
||||
AndroidRendererBackend::~AndroidRendererBackend() = default;
|
||||
|
||||
gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) {
|
||||
assert(gfx::BackendScope::exists());
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::updateViewPort() {
|
||||
assert(gfx::BackendScope::exists());
|
||||
setViewport(0, 0, size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::resizeFramebuffer(int width, int height) {
|
||||
size = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
|
||||
}
|
||||
|
||||
PremultipliedImage AndroidRendererBackend::readFramebuffer() {
|
||||
assert(gfx::BackendScope::exists());
|
||||
return gl::RendererBackend::readFramebuffer(size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::updateAssumedState() {
|
||||
assumeFramebufferBinding(0);
|
||||
assumeViewport(0, 0, size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::markContextLost() {
|
||||
if (context) {
|
||||
getContext<gl::Context>().setCleanupOnDestruction(false);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namspace mbgl
|
||||
43
MapboxGLAndroidSDK/src/cpp/android_renderer_backend.hpp
Executable file
43
MapboxGLAndroidSDK/src/cpp/android_renderer_backend.hpp
Executable file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/gl/renderer_backend.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererBackend : public gl::RendererBackend, public mbgl::gfx::Renderable {
|
||||
public:
|
||||
AndroidRendererBackend();
|
||||
~AndroidRendererBackend() override;
|
||||
|
||||
void updateViewPort();
|
||||
|
||||
// Ensures the current context is not cleaned up when destroyed
|
||||
void markContextLost();
|
||||
|
||||
void resizeFramebuffer(int width, int height);
|
||||
PremultipliedImage readFramebuffer();
|
||||
|
||||
// mbgl::gfx::RendererBackend implementation
|
||||
public:
|
||||
mbgl::gfx::Renderable& getDefaultRenderable() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void activate() override {
|
||||
// no-op
|
||||
}
|
||||
void deactivate() override {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// mbgl::gl::RendererBackend implementation
|
||||
protected:
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
|
||||
void updateAssumedState() override;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
143
MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.cpp
Normal file
143
MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "android_renderer_frontend.hpp"
|
||||
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/renderer/renderer_observer.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include "android_renderer_backend.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// Forwards RendererObserver signals to the given
|
||||
// Delegate RendererObserver on the given RunLoop
|
||||
class ForwardingRendererObserver : public RendererObserver {
|
||||
public:
|
||||
ForwardingRendererObserver(util::RunLoop& mapRunLoop, RendererObserver& delegate_)
|
||||
: mailbox(std::make_shared<Mailbox>(mapRunLoop))
|
||||
, delegate(delegate_, mailbox) {
|
||||
}
|
||||
|
||||
~ForwardingRendererObserver() {
|
||||
mailbox->close();
|
||||
}
|
||||
|
||||
void onInvalidate() override {
|
||||
delegate.invoke(&RendererObserver::onInvalidate);
|
||||
}
|
||||
|
||||
void onResourceError(std::exception_ptr err) override {
|
||||
delegate.invoke(&RendererObserver::onResourceError, err);
|
||||
}
|
||||
|
||||
void onWillStartRenderingMap() override {
|
||||
delegate.invoke(&RendererObserver::onWillStartRenderingMap);
|
||||
}
|
||||
|
||||
void onWillStartRenderingFrame() override {
|
||||
delegate.invoke(&RendererObserver::onWillStartRenderingFrame);
|
||||
}
|
||||
|
||||
void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded, bool placementChanged) override {
|
||||
delegate.invoke(&RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded, placementChanged);
|
||||
}
|
||||
|
||||
void onDidFinishRenderingMap() override {
|
||||
delegate.invoke(&RendererObserver::onDidFinishRenderingMap);
|
||||
}
|
||||
|
||||
void onStyleImageMissing(const std::string& id, StyleImageMissingCallback done) override {
|
||||
delegate.invoke(&RendererObserver::onStyleImageMissing, id, done);
|
||||
}
|
||||
|
||||
void onRemoveUnusedStyleImages(const std::vector<std::string>& ids) override {
|
||||
delegate.invoke(&RendererObserver::onRemoveUnusedStyleImages, ids);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Mailbox> mailbox;
|
||||
ActorRef<RendererObserver> delegate;
|
||||
};
|
||||
|
||||
AndroidRendererFrontend::AndroidRendererFrontend(MapRenderer& mapRenderer_)
|
||||
: mapRenderer(mapRenderer_)
|
||||
, mapRunLoop(util::RunLoop::Get())
|
||||
, updateAsyncTask(std::make_unique<util::AsyncTask>([this]() {
|
||||
mapRenderer.update(std::move(updateParams));
|
||||
mapRenderer.requestRender();
|
||||
})) {
|
||||
}
|
||||
|
||||
AndroidRendererFrontend::~AndroidRendererFrontend() = default;
|
||||
|
||||
void AndroidRendererFrontend::reset() {
|
||||
mapRenderer.reset();
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::setObserver(RendererObserver& observer) {
|
||||
assert (util::RunLoop::Get());
|
||||
// Don't call the Renderer directly, but use MapRenderer#setObserver to make sure
|
||||
// the Renderer may be re-initialised without losing the RendererObserver reference.
|
||||
mapRenderer.setObserver(std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer));
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
|
||||
updateParams = std::move(params);
|
||||
updateAsyncTask->send();
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::reduceMemoryUse() {
|
||||
mapRenderer.actor().invoke(&Renderer::reduceMemoryUse);
|
||||
}
|
||||
|
||||
std::vector<Feature> AndroidRendererFrontend::querySourceFeatures(const std::string& sourceID,
|
||||
const SourceQueryOptions& options) const {
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(&Renderer::querySourceFeatures, sourceID, options).get();
|
||||
}
|
||||
|
||||
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenBox& box,
|
||||
const RenderedQueryOptions& options) const {
|
||||
|
||||
// Select the right overloaded method
|
||||
std::vector<Feature> (Renderer::*fn)(const ScreenBox&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures;
|
||||
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(fn, box, options).get();
|
||||
}
|
||||
|
||||
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenCoordinate& point,
|
||||
const RenderedQueryOptions& options) const {
|
||||
|
||||
// Select the right overloaded method
|
||||
std::vector<Feature> (Renderer::*fn)(const ScreenCoordinate&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures;
|
||||
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(fn, point, options).get();
|
||||
}
|
||||
|
||||
AnnotationIDs AndroidRendererFrontend::queryPointAnnotations(const ScreenBox& box) const {
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(&Renderer::queryPointAnnotations, box).get();
|
||||
}
|
||||
|
||||
AnnotationIDs AndroidRendererFrontend::queryShapeAnnotations(const ScreenBox& box) const {
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(&Renderer::queryShapeAnnotations, box).get();
|
||||
}
|
||||
|
||||
FeatureExtensionValue AndroidRendererFrontend::queryFeatureExtensions(const std::string& sourceID,
|
||||
const Feature& feature,
|
||||
const std::string& extension,
|
||||
const std::string& extensionField,
|
||||
const optional<std::map<std::string, mbgl::Value>>& args) const {
|
||||
return mapRenderer.actor().ask(&Renderer::queryFeatureExtensions, sourceID, feature, extension, extensionField, args).get();
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
|
||||
68
MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.hpp
Normal file
68
MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/actor.hpp>
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
#include <mbgl/renderer/renderer_frontend.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include "map_renderer.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class RenderedQueryOptions;
|
||||
class SourceQueryOptions;
|
||||
|
||||
namespace util {
|
||||
|
||||
class AsyncTask;
|
||||
|
||||
} // namespace util
|
||||
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererFrontend : public RendererFrontend {
|
||||
public:
|
||||
|
||||
AndroidRendererFrontend(MapRenderer&);
|
||||
~AndroidRendererFrontend() override;
|
||||
|
||||
void reset() override;
|
||||
void setObserver(RendererObserver&) override;
|
||||
|
||||
void update(std::shared_ptr<UpdateParameters>) override;
|
||||
|
||||
// Feature querying
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions&) const;
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions&) const;
|
||||
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
|
||||
AnnotationIDs queryPointAnnotations(const ScreenBox& box) const;
|
||||
AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
|
||||
|
||||
|
||||
// Feature extension query
|
||||
FeatureExtensionValue
|
||||
queryFeatureExtensions(const std::string& sourceID,
|
||||
const Feature& feature,
|
||||
const std::string& extension,
|
||||
const std::string& extensionField,
|
||||
const optional<std::map<std::string, mbgl::Value>>& args) const;
|
||||
|
||||
// Memory
|
||||
void reduceMemoryUse();
|
||||
|
||||
private:
|
||||
MapRenderer& mapRenderer;
|
||||
util::RunLoop* mapRunLoop;
|
||||
std::unique_ptr<util::AsyncTask> updateAsyncTask;
|
||||
std::shared_ptr<UpdateParameters> updateParams;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
23
MapboxGLAndroidSDK/src/cpp/annotation/marker.cpp
Normal file
23
MapboxGLAndroidSDK/src/cpp/annotation/marker.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "marker.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
|
||||
static auto& javaClass = jni::Class<Marker>::Singleton(env);
|
||||
static auto positionField = javaClass.GetField<jni::Object<LatLng>>(env, "position");
|
||||
return LatLng::getGeometry(env, marker.Get(env, positionField));
|
||||
}
|
||||
|
||||
std::string Marker::getIconId(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
|
||||
static auto& javaClass = jni::Class<Marker>::Singleton(env);
|
||||
static auto iconIdField = javaClass.GetField<jni::String>(env, "iconId");
|
||||
return jni::Make<std::string>(env, marker.Get(env, iconIdField));
|
||||
}
|
||||
|
||||
void Marker::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Marker>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
28
MapboxGLAndroidSDK/src/cpp/annotation/marker.hpp
Normal file
28
MapboxGLAndroidSDK/src/cpp/annotation/marker.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Marker : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; };
|
||||
|
||||
static mbgl::Point<double> getPosition(jni::JNIEnv&, const jni::Object<Marker>&);
|
||||
|
||||
static std::string getIconId(jni::JNIEnv&, const jni::Object<Marker>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
34
MapboxGLAndroidSDK/src/cpp/annotation/multi_point.hpp
Normal file
34
MapboxGLAndroidSDK/src/cpp/annotation/multi_point.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class MultiPoint : protected mbgl::util::noncopyable {
|
||||
|
||||
protected:
|
||||
|
||||
template <class Geometry>
|
||||
static Geometry toGeometry(JNIEnv& env, const jni::Object<java::util::List>& pointsList) {
|
||||
auto jarray = java::util::List::toArray<LatLng>(env, pointsList);
|
||||
|
||||
std::size_t size = jarray.Length(env);
|
||||
|
||||
Geometry geometry;
|
||||
geometry.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
geometry.push_back(LatLng::getGeometry(env, jarray.Get(env, i)));
|
||||
}
|
||||
|
||||
return geometry;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
40
MapboxGLAndroidSDK/src/cpp/annotation/polygon.cpp
Normal file
40
MapboxGLAndroidSDK/src/cpp/annotation/polygon.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "polygon.hpp"
|
||||
|
||||
#include "../conversion/color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, const jni::Object<Polygon>& polygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
|
||||
static auto holes = javaClass.GetField<jni::Object<java::util::List>>(env, "holes");
|
||||
static auto alpha = javaClass.GetField<float>(env, "alpha");
|
||||
static auto fillColor = javaClass.GetField<int>(env, "fillColor");
|
||||
static auto strokeColor = javaClass.GetField<int>(env, "strokeColor");
|
||||
|
||||
mbgl::Polygon<double> geometry {
|
||||
MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, polygon.Get(env, points))
|
||||
};
|
||||
|
||||
auto jHoleListsArray = java::util::List::toArray<java::util::List>(env, polygon.Get(env, holes));
|
||||
|
||||
std::size_t jHoleListsSize = jHoleListsArray.Length(env);
|
||||
for (std::size_t i = 0; i < jHoleListsSize; i++) {
|
||||
geometry.push_back(MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, jHoleListsArray.Get(env, i)));
|
||||
}
|
||||
|
||||
mbgl::FillAnnotation annotation { geometry };
|
||||
annotation.opacity = polygon.Get(env, alpha);
|
||||
annotation.color = *conversion::convert<mbgl::Color>(env, polygon.Get(env, fillColor));
|
||||
annotation.outlineColor = *conversion::convert<mbgl::Color>(env, polygon.Get(env, strokeColor));
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
void Polygon::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Polygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
21
MapboxGLAndroidSDK/src/cpp/annotation/polygon.hpp
Normal file
21
MapboxGLAndroidSDK/src/cpp/annotation/polygon.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
|
||||
#include "multi_point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Polygon : private MultiPoint {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; };
|
||||
|
||||
static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
31
MapboxGLAndroidSDK/src/cpp/annotation/polyline.cpp
Normal file
31
MapboxGLAndroidSDK/src/cpp/annotation/polyline.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "polyline.hpp"
|
||||
|
||||
#include "../conversion/color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, const jni::Object<Polyline>& polyline) {
|
||||
static auto& javaClass = jni::Class<Polyline>::Singleton(env);
|
||||
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
|
||||
static auto alpha = javaClass.GetField<float>(env, "alpha");
|
||||
static auto color = javaClass.GetField<int>(env, "color");
|
||||
static auto width = javaClass.GetField<float>(env, "width");
|
||||
|
||||
mbgl::LineAnnotation annotation {
|
||||
MultiPoint::toGeometry<mbgl::LineString<double>>(env, polyline.Get(env, points))
|
||||
};
|
||||
|
||||
annotation.opacity = polyline.Get(env, alpha);
|
||||
annotation.color = *conversion::convert<mbgl::Color>(env, polyline.Get(env, color));
|
||||
annotation.width = polyline.Get(env, width);
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
void Polyline::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Polyline>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
21
MapboxGLAndroidSDK/src/cpp/annotation/polyline.hpp
Normal file
21
MapboxGLAndroidSDK/src/cpp/annotation/polyline.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
|
||||
#include "multi_point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Polyline : private MultiPoint {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; };
|
||||
|
||||
static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polyline>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
14
MapboxGLAndroidSDK/src/cpp/asset_manager.hpp
Normal file
14
MapboxGLAndroidSDK/src/cpp/asset_manager.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AssetManager {
|
||||
public:
|
||||
static constexpr auto Name() {
|
||||
return "android/content/res/AssetManager";
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
65
MapboxGLAndroidSDK/src/cpp/asset_manager_file_source.cpp
Normal file
65
MapboxGLAndroidSDK/src/cpp/asset_manager_file_source.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "asset_manager_file_source.hpp"
|
||||
|
||||
#include <mbgl/platform/settings.hpp>
|
||||
#include <mbgl/storage/file_source_request.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/url.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include <android/asset_manager.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class AssetManagerFileSource::Impl {
|
||||
public:
|
||||
Impl(ActorRef<Impl>, AAssetManager* assetManager_) : assetManager(assetManager_) {
|
||||
}
|
||||
|
||||
void request(const std::string& url, ActorRef<FileSourceRequest> req) {
|
||||
// Note: AssetManager already prepends "assets" to the filename.
|
||||
const std::string path = mbgl::util::percentDecode(url.substr(8));
|
||||
|
||||
Response response;
|
||||
|
||||
if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) {
|
||||
response.data = std::make_shared<std::string>(
|
||||
reinterpret_cast<const char*>(AAsset_getBuffer(asset)), AAsset_getLength64(asset));
|
||||
AAsset_close(asset);
|
||||
} else {
|
||||
response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound,
|
||||
"Could not read asset");
|
||||
}
|
||||
|
||||
req.invoke(&FileSourceRequest::setResponse, response);
|
||||
}
|
||||
|
||||
private:
|
||||
AAssetManager* assetManager;
|
||||
};
|
||||
|
||||
AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env,
|
||||
const jni::Object<android::AssetManager>& assetManager_)
|
||||
: assetManager(jni::NewGlobal(env, assetManager_)),
|
||||
impl(std::make_unique<util::Thread<Impl>>(
|
||||
util::makeThreadPrioritySetter(platform::EXPERIMENTAL_THREAD_PRIORITY_FILE),
|
||||
"AssetManagerFileSource",
|
||||
AAssetManager_fromJava(&env, jni::Unwrap(assetManager.get())))) {}
|
||||
|
||||
AssetManagerFileSource::~AssetManagerFileSource() = default;
|
||||
|
||||
std::unique_ptr<AsyncRequest> AssetManagerFileSource::request(const Resource& resource, Callback callback) {
|
||||
auto req = std::make_unique<FileSourceRequest>(std::move(callback));
|
||||
|
||||
impl->actor().invoke(&Impl::request, resource.url, req->actor());
|
||||
|
||||
return std::move(req);
|
||||
}
|
||||
|
||||
bool AssetManagerFileSource::canRequest(const Resource& resource) const {
|
||||
return 0 == resource.url.rfind(mbgl::util::ASSET_PROTOCOL, 0);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
30
MapboxGLAndroidSDK/src/cpp/asset_manager_file_source.hpp
Normal file
30
MapboxGLAndroidSDK/src/cpp/asset_manager_file_source.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace util {
|
||||
template <typename T> class Thread;
|
||||
} // namespace util
|
||||
|
||||
class AssetManagerFileSource : public FileSource {
|
||||
public:
|
||||
AssetManagerFileSource(jni::JNIEnv&, const jni::Object<android::AssetManager>&);
|
||||
~AssetManagerFileSource() override;
|
||||
|
||||
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
|
||||
bool canRequest(const Resource&) const override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
jni::Global<jni::Object<android::AssetManager>> assetManager;
|
||||
std::unique_ptr<util::Thread<Impl>> impl;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
41
MapboxGLAndroidSDK/src/cpp/connectivity_listener.cpp
Normal file
41
MapboxGLAndroidSDK/src/cpp/connectivity_listener.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "connectivity_listener.hpp"
|
||||
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Invoked when the construction is initiated from the jvm
|
||||
*/
|
||||
ConnectivityListener::ConnectivityListener(jni::JNIEnv&) {}
|
||||
|
||||
ConnectivityListener::~ConnectivityListener() {}
|
||||
|
||||
void ConnectivityListener::onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean connected) {
|
||||
NetworkStatus::Set(connected ? NetworkStatus::Status::Online : NetworkStatus::Status::Offline);
|
||||
}
|
||||
|
||||
void ConnectivityListener::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<ConnectivityListener>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<ConnectivityListener>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
std::make_unique<ConnectivityListener, JNIEnv&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&ConnectivityListener::onConnectivityStateChanged, "nativeOnConnectivityStateChanged")
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
29
MapboxGLAndroidSDK/src/cpp/connectivity_listener.hpp
Normal file
29
MapboxGLAndroidSDK/src/cpp/connectivity_listener.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class ConnectivityListener : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/net/NativeConnectivityListener"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
/*
|
||||
* Called when a Java object was created from the jvm side
|
||||
*/
|
||||
ConnectivityListener(jni::JNIEnv&);
|
||||
|
||||
~ConnectivityListener();
|
||||
|
||||
void onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean);
|
||||
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
32
MapboxGLAndroidSDK/src/cpp/conversion/collection.cpp
Normal file
32
MapboxGLAndroidSDK/src/cpp/conversion/collection.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "collection.hpp"
|
||||
#include "constant.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array) {
|
||||
std::size_t len = array.Length(env);
|
||||
std::vector<std::string> vector;
|
||||
vector.reserve(len);
|
||||
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
vector.push_back(jni::Make<std::string>(env, array.Get(env, i)));
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>& vector) {
|
||||
auto result = jni::Array<jni::String>::New(env, vector.size());
|
||||
|
||||
for (std::size_t i = 0; i < vector.size(); i++) {
|
||||
result.Set(env, i, jni::Make<jni::String>(env, vector.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
18
MapboxGLAndroidSDK/src/cpp/conversion/collection.hpp
Normal file
18
MapboxGLAndroidSDK/src/cpp/conversion/collection.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array);
|
||||
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>&);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
17
MapboxGLAndroidSDK/src/cpp/conversion/color.cpp
Normal file
17
MapboxGLAndroidSDK/src/cpp/conversion/color.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
Result<mbgl::Color> Converter<mbgl::Color, int>::operator()(jni::JNIEnv&, const int& color) const {
|
||||
float r = (color >> 16) & 0xFF;
|
||||
float g = (color >> 8) & 0xFF;
|
||||
float b = (color) & 0xFF;
|
||||
float a = (color >> 24) & 0xFF;
|
||||
return { mbgl::Color( r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f ) };
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
18
MapboxGLAndroidSDK/src/cpp/conversion/color.hpp
Normal file
18
MapboxGLAndroidSDK/src/cpp/conversion/color.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
template <>
|
||||
struct Converter<mbgl::Color, int> {
|
||||
Result<mbgl::Color> operator()(jni::JNIEnv&, const int& color) const;
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
62
MapboxGLAndroidSDK/src/cpp/conversion/constant.cpp
Normal file
62
MapboxGLAndroidSDK/src/cpp/conversion/constant.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "constant.hpp"
|
||||
#include "collection.hpp"
|
||||
#include "../style/formatted.hpp"
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, bool>::operator()(jni::JNIEnv& env, const bool& value) const {
|
||||
return jni::Box(env, value ? jni::jni_true : jni::jni_false);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, float>::operator()(jni::JNIEnv& env, const float& value) const {
|
||||
return jni::Box(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, double>::operator()(jni::JNIEnv& env, const double& value) const {
|
||||
return jni::Box(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::string>::operator()(jni::JNIEnv& env, const std::string& value) const {
|
||||
return jni::Make<jni::String>(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, Color>::operator()(jni::JNIEnv& env, const Color& value) const {
|
||||
return jni::Make<jni::String>(env, value.stringify());
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Formatted>::operator()(jni::JNIEnv& env, const style::expression::Formatted& value) const {
|
||||
return Formatted::New(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<std::string>>::operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const {
|
||||
auto result = jni::Array<jni::String>::New(env, value.size());
|
||||
|
||||
for (std::size_t i = 0; i < value.size(); i++) {
|
||||
result.Set(env, i, jni::Make<jni::String>(env, value.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<float>>::operator()(jni::JNIEnv& env, const std::vector<float>& value) const {
|
||||
auto result = jni::Array<jni::Float>::New(env, value.size());
|
||||
|
||||
for (std::size_t i = 0; i < value.size(); i++) {
|
||||
result.Set(env, i, jni::Box(env, value.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Image>::operator()(
|
||||
jni::JNIEnv& env, const style::expression::Image& value) const {
|
||||
return jni::Make<jni::String>(env, value.id());
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
110
MapboxGLAndroidSDK/src/cpp/conversion/constant.hpp
Normal file
110
MapboxGLAndroidSDK/src/cpp/conversion/constant.hpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
#include <mbgl/util/enum.hpp>
|
||||
|
||||
#include <mbgl/style/expression/formatted.hpp>
|
||||
#include <mbgl/style/expression/image.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, bool> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const bool& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, float> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const float& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, double> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const double& value) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* All integrals. java is limited to 64 bit signed, so...
|
||||
* TODO: use BigDecimal for > 64 / unsigned?
|
||||
*/
|
||||
template<typename T>
|
||||
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if<std::is_integral<T>::value>::type> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
|
||||
return jni::Box(env, jni::jlong(value));
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: convert integral types to primitive jni types
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::string> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::string& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, Color> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const Color& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, style::expression::Formatted> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const style::expression::Formatted& value) const;
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::array<float, N>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::array<float, N>& value) const {
|
||||
std::vector<float> v;
|
||||
for (const float& id : value) {
|
||||
v.push_back(id);
|
||||
}
|
||||
return convert<jni::Local<jni::Object<>>, std::vector<float>>(env, v);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<std::string>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<float>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<float>& value) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if_t<std::is_enum<T>::value>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
|
||||
return convert<jni::Local<jni::Object<>>, std::string>(env, Enum<T>::toString(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<T>, typename std::enable_if_t<std::is_enum<T>::value>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<T>& value) const {
|
||||
auto result = jni::Array<jni::String>::New(env, value.size());
|
||||
for (std::size_t i = 0; i < value.size(); ++i) {
|
||||
result.Set(env, i, jni::Make<jni::String>(env, Enum<T>::toString(value.at(i))));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, style::expression::Image> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const style::expression::Image& value) const;
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
50
MapboxGLAndroidSDK/src/cpp/conversion/conversion.hpp
Normal file
50
MapboxGLAndroidSDK/src/cpp/conversion/conversion.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/variant.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
struct Error { std::string message; };
|
||||
|
||||
template <class T>
|
||||
class Result : private variant<T, Error> {
|
||||
public:
|
||||
using variant<T, Error>::variant;
|
||||
|
||||
explicit operator bool() const {
|
||||
return this->template is<T>();
|
||||
}
|
||||
|
||||
T& operator*() {
|
||||
assert(this->template is<T>());
|
||||
return this->template get<T>();
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
assert(this->template is<T>());
|
||||
return this->template get<T>();
|
||||
}
|
||||
|
||||
const Error& error() const {
|
||||
assert(this->template is<Error>());
|
||||
return this->template get<Error>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class V, class Enable = void>
|
||||
struct Converter;
|
||||
|
||||
template <class T, typename V, class...Args>
|
||||
Result<T> convert(jni::JNIEnv& env, const V& value, Args&&...args) {
|
||||
return Converter<T, V>()(env, value, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
252
MapboxGLAndroidSDK/src/cpp/file_source.cpp
Normal file
252
MapboxGLAndroidSDK/src/cpp/file_source.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
#include "file_source.hpp"
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "mapbox.hpp"
|
||||
|
||||
#include <mbgl/actor/actor.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/storage/file_source_manager.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/resource_transform.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <mbgl/storage/sqlite3.hpp>
|
||||
|
||||
#include "asset_manager_file_source.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// FileSource //
|
||||
|
||||
FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const jni::String& _cachePath) {
|
||||
std::string path = jni::Make<std::string>(_env, _cachePath);
|
||||
mapbox::sqlite::setTempPath(path);
|
||||
|
||||
mbgl::FileSourceManager::get()->registerFileSourceFactory(
|
||||
mbgl::FileSourceType::Asset, [](const mbgl::ResourceOptions&) {
|
||||
auto env{android::AttachEnv()};
|
||||
std::unique_ptr<mbgl::FileSource> assetFileSource;
|
||||
if (android::Mapbox::hasInstance(*env)) {
|
||||
auto assetManager = android::Mapbox::getAssetManager(*env);
|
||||
assetFileSource = std::make_unique<AssetManagerFileSource>(*env, assetManager);
|
||||
}
|
||||
return assetFileSource;
|
||||
});
|
||||
|
||||
resourceOptions.withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "")
|
||||
.withCachePath(path + DATABASE_FILE);
|
||||
|
||||
// Create a core file sources
|
||||
// TODO: Split Android FileSource API to smaller interfaces
|
||||
resourceLoader =
|
||||
mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::ResourceLoader, resourceOptions);
|
||||
databaseSource = std::static_pointer_cast<mbgl::DatabaseFileSource>(std::shared_ptr<mbgl::FileSource>(
|
||||
mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Database, resourceOptions)));
|
||||
onlineSource = mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Network, resourceOptions);
|
||||
}
|
||||
|
||||
FileSource::~FileSource() {
|
||||
}
|
||||
|
||||
jni::Local<jni::String> FileSource::getAccessToken(jni::JNIEnv& env) {
|
||||
if (auto* token = onlineSource->getProperty(mbgl::ACCESS_TOKEN_KEY).getString()) {
|
||||
return jni::Make<jni::String>(env, *token);
|
||||
}
|
||||
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
return jni::Make<jni::String>(env, "");
|
||||
}
|
||||
|
||||
void FileSource::setAccessToken(jni::JNIEnv& env, const jni::String& token) {
|
||||
if (onlineSource) {
|
||||
onlineSource->setProperty(mbgl::ACCESS_TOKEN_KEY, token ? jni::Make<std::string>(env, token) : "");
|
||||
} else {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) {
|
||||
if (onlineSource) {
|
||||
onlineSource->setProperty(mbgl::API_BASE_URL_KEY, jni::Make<std::string>(env, url));
|
||||
} else {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& transformCallback) {
|
||||
// Core could be built without support for network resource provider.
|
||||
if (!onlineSource) {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (transformCallback) {
|
||||
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, transformCallback);
|
||||
resourceTransform = std::make_unique<Actor<ResourceTransform::TransformCallback>>(
|
||||
*Scheduler::GetCurrent(),
|
||||
// Capture the ResourceTransformCallback object as a managed global into
|
||||
// the lambda. It is released automatically when we're setting a new ResourceTransform in
|
||||
// a subsequent call.
|
||||
// Note: we're converting it to shared_ptr because this lambda is converted to a std::function,
|
||||
// which requires copyability of its captured variables.
|
||||
[callback = std::make_shared<decltype(global)>(std::move(global))](
|
||||
mbgl::Resource::Kind kind, const std::string& url_, ResourceTransform::FinishedCallback cb) {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
cb(FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_));
|
||||
});
|
||||
onlineSource->setResourceTransform(
|
||||
{[actorRef = resourceTransform->self()](
|
||||
Resource::Kind kind, const std::string& url, ResourceTransform::FinishedCallback cb) {
|
||||
actorRef.invoke(&ResourceTransform::TransformCallback::operator(), kind, url, std::move(cb));
|
||||
}});
|
||||
} else {
|
||||
// Reset the callback
|
||||
resourceTransform.reset();
|
||||
onlineSource->setResourceTransform({});
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::setResourceCachePath(jni::JNIEnv& env,
|
||||
const jni::String& path,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& _callback) {
|
||||
if (!databaseSource) {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pathChangeCallback) {
|
||||
FileSource::ResourcesCachePathChangeCallback::onError(env, _callback, jni::Make<jni::String>(env, "Another resources cache path change is in progress"));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string newPath = jni::Make<std::string>(env, path);
|
||||
mapbox::sqlite::setTempPath(newPath);
|
||||
|
||||
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, _callback);
|
||||
pathChangeCallback = Scheduler::GetCurrent()->bindOnce(
|
||||
[this, callback = std::make_shared<decltype(global)>(std::move(global)), newPath] {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
FileSource::ResourcesCachePathChangeCallback::onSuccess(
|
||||
*_env, *callback, jni::Make<jni::String>(*_env, newPath));
|
||||
pathChangeCallback = {};
|
||||
});
|
||||
|
||||
databaseSource->setDatabasePath(newPath + DATABASE_FILE, pathChangeCallback);
|
||||
}
|
||||
|
||||
void FileSource::resume(jni::JNIEnv&) {
|
||||
if (!resourceLoader) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!activationCounter) {
|
||||
activationCounter = optional<int>(1) ;
|
||||
return;
|
||||
}
|
||||
|
||||
activationCounter.value()++;
|
||||
if (activationCounter == 1) {
|
||||
resourceLoader->resume();
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::pause(jni::JNIEnv&) {
|
||||
if (!resourceLoader) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (activationCounter) {
|
||||
activationCounter.value()--;
|
||||
if (activationCounter == 0) {
|
||||
resourceLoader->pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jni::jboolean FileSource::isResumed(jni::JNIEnv&) {
|
||||
if (activationCounter) {
|
||||
return (jboolean) (activationCounter > 0);
|
||||
}
|
||||
return (jboolean) false;
|
||||
}
|
||||
|
||||
FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
|
||||
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
|
||||
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
|
||||
return reinterpret_cast<FileSource *>(jFileSource.Get(env, field));
|
||||
}
|
||||
|
||||
mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource>& jFileSource) {
|
||||
FileSource* fileSource = FileSource::getNativePeer(env, jFileSource);
|
||||
// Core could be compiled without support for any sources.
|
||||
if (fileSource) {
|
||||
return fileSource->resourceOptions.clone();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// FileSource::ResourcesCachePathChangeCallback //
|
||||
|
||||
void FileSource::ResourcesCachePathChangeCallback::onSuccess(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
|
||||
const jni::String& path) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onSuccess");
|
||||
|
||||
callback.Call(env, method, path);
|
||||
}
|
||||
|
||||
void FileSource::ResourcesCachePathChangeCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
|
||||
const jni::String& message) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, message);
|
||||
}
|
||||
|
||||
void FileSource::registerNative(jni::JNIEnv& env) {
|
||||
// Ensure the classes are cached. If they're requested for the
|
||||
// first time on a background thread, Android's class loader heuristics will fail.
|
||||
// https://developer.android.com/training/articles/perf-jni#faq_FindClass
|
||||
jni::Class<ResourceTransformCallback>::Singleton(env);
|
||||
jni::Class<ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
|
||||
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<FileSource>(env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
jni::MakePeer<FileSource, const jni::String&, const jni::String&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&FileSource::getAccessToken, "getAccessToken"),
|
||||
METHOD(&FileSource::setAccessToken, "setAccessToken"),
|
||||
METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"),
|
||||
METHOD(&FileSource::setResourceTransform, "setResourceTransform"),
|
||||
METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"),
|
||||
METHOD(&FileSource::resume, "activate"),
|
||||
METHOD(&FileSource::pause, "deactivate"),
|
||||
METHOD(&FileSource::isResumed, "isActivated"));
|
||||
}
|
||||
|
||||
|
||||
// FileSource::ResourceTransformCallback //
|
||||
|
||||
std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& callback, int kind, std::string url_) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourceTransformCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String (jni::jint, jni::String)>(env, "onURL");
|
||||
|
||||
return jni::Make<std::string>(env,
|
||||
callback.Call(env, method, kind,
|
||||
jni::Make<jni::String>(env, url_)));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
83
MapboxGLAndroidSDK/src/cpp/file_source.hpp
Normal file
83
MapboxGLAndroidSDK/src/cpp/file_source.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/database_file_source.hpp>
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/resource_transform.hpp>
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <typename T> class Actor;
|
||||
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Peer class for the Android FileSource holder. Ensures that a single core FileSource
|
||||
* of a ResourceLoader type is used.
|
||||
*/
|
||||
class FileSource {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource"; };
|
||||
|
||||
struct ResourceTransformCallback {
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourceTransformCallback"; }
|
||||
|
||||
static std::string onURL(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&, int, std::string);
|
||||
};
|
||||
|
||||
struct ResourcesCachePathChangeCallback {
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourcesCachePathChangeCallback";}
|
||||
|
||||
static void onSuccess(jni::JNIEnv&,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
|
||||
const jni::String&);
|
||||
|
||||
static void onError(jni::JNIEnv&,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
|
||||
const jni::String&);
|
||||
};
|
||||
|
||||
FileSource(jni::JNIEnv&, const jni::String&, const jni::String&);
|
||||
|
||||
~FileSource();
|
||||
|
||||
jni::Local<jni::String> getAccessToken(jni::JNIEnv&);
|
||||
|
||||
void setAccessToken(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
void setAPIBaseUrl(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
void setResourceTransform(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&);
|
||||
|
||||
void setResourceCachePath(jni::JNIEnv&, const jni::String&, const jni::Object<FileSource::ResourcesCachePathChangeCallback>&);
|
||||
|
||||
void resume(jni::JNIEnv&);
|
||||
|
||||
void pause(jni::JNIEnv&);
|
||||
|
||||
jni::jboolean isResumed(jni::JNIEnv&);
|
||||
|
||||
static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
|
||||
static mbgl::ResourceOptions getSharedResourceOptions(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
private:
|
||||
const std::string DATABASE_FILE = "/mbgl-offline.db";
|
||||
optional<int> activationCounter;
|
||||
mbgl::ResourceOptions resourceOptions;
|
||||
std::unique_ptr<Actor<ResourceTransform::TransformCallback>> resourceTransform;
|
||||
std::function<void()> pathChangeCallback;
|
||||
std::shared_ptr<mbgl::DatabaseFileSource> databaseSource;
|
||||
std::shared_ptr<mbgl::FileSource> onlineSource;
|
||||
std::shared_ptr<mbgl::FileSource> resourceLoader;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
88
MapboxGLAndroidSDK/src/cpp/geojson/feature.cpp
Normal file
88
MapboxGLAndroidSDK/src/cpp/geojson/feature.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "feature.hpp"
|
||||
#include "geometry.hpp"
|
||||
#include "../gson/json_object.hpp"
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
using namespace gson;
|
||||
|
||||
mbgl::GeoJSONFeature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFeature) {
|
||||
static auto& javaClass = jni::Class<Feature>::Singleton(env);
|
||||
static auto id = javaClass.GetMethod<jni::String ()>(env, "id");
|
||||
static auto geometry = javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry");
|
||||
static auto properties = javaClass.GetMethod<jni::Object<gson::JsonObject> ()>(env, "properties");
|
||||
|
||||
auto jId = jFeature.Call(env, id);
|
||||
|
||||
using mbid = mapbox::feature::identifier;
|
||||
|
||||
return mbgl::GeoJSONFeature{Geometry::convert(env, jFeature.Call(env, geometry)),
|
||||
JsonObject::convert(env, jFeature.Call(env, properties)),
|
||||
jId ? mbid{jni::Make<std::string>(env, jId)} : mbid{mapbox::feature::null_value}};
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn feature identifier into std::string
|
||||
*/
|
||||
class FeatureIdVisitor {
|
||||
public:
|
||||
template<class T>
|
||||
std::string operator()(const T& i) const {
|
||||
return util::toString(i);
|
||||
}
|
||||
|
||||
std::string operator()(const std::string& i) const {
|
||||
return i;
|
||||
}
|
||||
|
||||
std::string operator()(const std::nullptr_t&) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string operator()(const mapbox::feature::null_value_t&) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::GeoJSONFeature& value) {
|
||||
static auto& javaClass = jni::Class<Feature>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<JsonObject>, jni::String)>(env, "fromGeometry");
|
||||
|
||||
return javaClass.Call(env, method,
|
||||
Geometry::New(env, value.geometry),
|
||||
JsonObject::New(env, value.properties),
|
||||
jni::Make<jni::String>(env, value.id.is<mbgl::NullValue>() ? std::string {} : value.id.match(FeatureIdVisitor())));
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) {
|
||||
auto features = jni::Array<jni::Object<Feature>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
features.Set(env, i, convertFeature(env, static_cast<mbgl::GeoJSONFeature>(value.at(i))));
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env,
|
||||
const std::vector<mbgl::GeoJSONFeature>& value) {
|
||||
auto features = jni::Array<jni::Object<Feature>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
features.Set(env, i, convertFeature(env, value.at(i)));
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
void Feature::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Feature>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
24
MapboxGLAndroidSDK/src/cpp/geojson/feature.hpp
Normal file
24
MapboxGLAndroidSDK/src/cpp/geojson/feature.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/feature.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Feature {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Feature"; };
|
||||
|
||||
static mbgl::GeoJSONFeature convert(jni::JNIEnv&, const jni::Object<Feature>&);
|
||||
static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::Feature>&);
|
||||
static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::GeoJSONFeature>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
37
MapboxGLAndroidSDK/src/cpp/geojson/feature_collection.cpp
Normal file
37
MapboxGLAndroidSDK/src/cpp/geojson/feature_collection.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "feature_collection.hpp"
|
||||
|
||||
#include "feature.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) {
|
||||
auto collection = mbgl::FeatureCollection();
|
||||
|
||||
if (jCollection) {
|
||||
auto jFeatureList = FeatureCollection::features(env, jCollection);
|
||||
auto jFeatures = java::util::List::toArray<Feature>(env, jFeatureList);
|
||||
auto size = size_t(jFeatures.Length(env));
|
||||
collection.reserve(size);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
collection.push_back(Feature::convert(env, jFeatures.Get(env, i)));
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> FeatureCollection::features(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) {
|
||||
static auto& javaClass = jni::Class<FeatureCollection>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "features");
|
||||
return jCollection.Call(env, method);
|
||||
}
|
||||
|
||||
void FeatureCollection::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<FeatureCollection>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
26
MapboxGLAndroidSDK/src/cpp/geojson/feature_collection.hpp
Normal file
26
MapboxGLAndroidSDK/src/cpp/geojson/feature_collection.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class FeatureCollection {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/FeatureCollection"; };
|
||||
|
||||
static mbgl::FeatureCollection convert(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> features(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
97
MapboxGLAndroidSDK/src/cpp/geojson/geometry.cpp
Normal file
97
MapboxGLAndroidSDK/src/cpp/geojson/geometry.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include "point.hpp"
|
||||
#include "multi_point.hpp"
|
||||
#include "line_string.hpp"
|
||||
#include "multi_line_string.hpp"
|
||||
#include "polygon.hpp"
|
||||
#include "multi_polygon.hpp"
|
||||
#include "geometry_collection.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
/**
|
||||
* Turn mapbox::geometry type into Java GeoJson Geometries
|
||||
*/
|
||||
class GeometryEvaluator {
|
||||
public:
|
||||
|
||||
jni::JNIEnv& env;
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::EmptyGeometry &) const {
|
||||
// FIXME: mapbox-java needs to have its own Empty type.
|
||||
return GeometryCollection::New(env, {});
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Point<double> &geometry) const {
|
||||
return Point::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::LineString<double> &geometry) const {
|
||||
return LineString::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiLineString<double> &geometry) const {
|
||||
return MultiLineString::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPoint<double> &geometry) const {
|
||||
return MultiPoint::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Polygon<double> &geometry) const {
|
||||
return Polygon::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPolygon<double> &geometry) const {
|
||||
return MultiPolygon::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const {
|
||||
return GeometryCollection::New(env, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
jni::Local<jni::Object<Geometry>> Geometry::New(jni::JNIEnv& env, mbgl::Geometry<double> geometry) {
|
||||
GeometryEvaluator evaluator { env } ;
|
||||
return mbgl::Geometry<double>::visit(geometry, evaluator);
|
||||
}
|
||||
|
||||
mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) {
|
||||
auto type = Geometry::getType(env, jGeometry);
|
||||
if (type == Point::Type()) {
|
||||
return { Point::convert(env, jni::Cast(env, jni::Class<Point>::Singleton(env), jGeometry)) };
|
||||
} else if (type == MultiPoint::Type()) {
|
||||
return { MultiPoint::convert(env, jni::Cast(env, jni::Class<MultiPoint>::Singleton(env), jGeometry)) };
|
||||
} else if (type == LineString::Type()) {
|
||||
return { LineString::convert(env, jni::Cast(env, jni::Class<LineString>::Singleton(env), jGeometry)) };
|
||||
} else if (type == MultiLineString::Type()) {
|
||||
return { MultiLineString::convert(env, jni::Cast(env, jni::Class<MultiLineString>::Singleton(env), jGeometry)) };
|
||||
} else if (type == Polygon::Type()) {
|
||||
return { Polygon::convert(env, jni::Cast(env, jni::Class<Polygon>::Singleton(env), jGeometry)) };
|
||||
} else if (type == MultiPolygon::Type()) {
|
||||
return { MultiPolygon::convert(env, jni::Cast(env, jni::Class<MultiPolygon>::Singleton(env), jGeometry)) };
|
||||
} else if (type == GeometryCollection::Type()) {
|
||||
return { GeometryCollection::convert(env, jni::Cast(env, jni::Class<GeometryCollection>::Singleton(env), jGeometry)) };
|
||||
}
|
||||
|
||||
throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type);
|
||||
}
|
||||
|
||||
std::string Geometry::getType(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) {
|
||||
static auto& javaClass = jni::Class<Geometry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String ()>(env, "type");
|
||||
return jni::Make<std::string>(env, jGeometry.Call(env, method));
|
||||
}
|
||||
|
||||
void Geometry::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Geometry>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
28
MapboxGLAndroidSDK/src/cpp/geojson/geometry.hpp
Normal file
28
MapboxGLAndroidSDK/src/cpp/geojson/geometry.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Geometry {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; };
|
||||
|
||||
static jni::Local<jni::Object<Geometry>> New(jni::JNIEnv&, mbgl::Geometry<double>);
|
||||
|
||||
static mbgl::Geometry<double> convert(jni::JNIEnv&, const jni::Object<Geometry>&);
|
||||
|
||||
static std::string getType(jni::JNIEnv&, const jni::Object<Geometry>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
47
MapboxGLAndroidSDK/src/cpp/geojson/geometry_collection.cpp
Normal file
47
MapboxGLAndroidSDK/src/cpp/geojson/geometry_collection.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "geometry_collection.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<GeometryCollection>> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) {
|
||||
// Create an array of geometries
|
||||
auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size());
|
||||
|
||||
for (size_t i = 0; i < collection.size(); i++) {
|
||||
jarray.Set(env, i, Geometry::New(env, collection.at(i)));
|
||||
}
|
||||
|
||||
// create the GeometryCollection
|
||||
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection> (jni::Object<java::util::List>)>(env, "fromGeometries");
|
||||
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
|
||||
}
|
||||
|
||||
mapbox::geometry::geometry_collection<double> GeometryCollection::convert(jni::JNIEnv &env, const jni::Object<GeometryCollection>& jCollection) {
|
||||
// Get geometries
|
||||
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
|
||||
static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "geometries");
|
||||
|
||||
// Turn into array
|
||||
auto jarray = java::util::List::toArray<Geometry>(env, jCollection.Call(env, getGeometries));
|
||||
|
||||
// Convert each geometry
|
||||
mapbox::geometry::geometry_collection<double> collection{};
|
||||
|
||||
auto size = jarray.Length(env);
|
||||
for (jni::jsize i = 0; i < size; i++) {
|
||||
collection.push_back(Geometry::convert(env, jarray.Get(env, i)));
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
void GeometryCollection::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<GeometryCollection>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
26
MapboxGLAndroidSDK/src/cpp/geojson/geometry_collection.hpp
Normal file
26
MapboxGLAndroidSDK/src/cpp/geojson/geometry_collection.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class GeometryCollection {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/GeometryCollection"; };
|
||||
static constexpr auto Type() { return "GeometryCollection"; };
|
||||
|
||||
static jni::Local<jni::Object<GeometryCollection>> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection<double>&);
|
||||
|
||||
static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, const jni::Object<GeometryCollection>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
55
MapboxGLAndroidSDK/src/cpp/geojson/line_string.cpp
Normal file
55
MapboxGLAndroidSDK/src/cpp/geojson/line_string.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "line_string.hpp"
|
||||
#include "point.hpp"
|
||||
#include "util.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<LineString>> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) {
|
||||
static auto& javaClass = jni::Class<LineString>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsList(env, lineString));
|
||||
}
|
||||
|
||||
mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) {
|
||||
mapbox::geojson::line_string lineString;
|
||||
|
||||
if (jLineString) {
|
||||
lineString = LineString::convert(env, LineString::coordinates(env, jLineString));
|
||||
}
|
||||
|
||||
return lineString;
|
||||
}
|
||||
|
||||
mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<Point>*/>& jPointList) {
|
||||
mapbox::geojson::line_string lineString;
|
||||
|
||||
if (jPointList) {
|
||||
auto jPointArray = java::util::List::toArray<Point>(env, jPointList);
|
||||
auto size = jPointArray.Length(env);
|
||||
lineString.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
lineString.push_back(Point::convert(env, jPointArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return lineString;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> LineString::coordinates(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) {
|
||||
static auto& javaClass = jni::Class<LineString>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jLineString.Call(env, method);
|
||||
}
|
||||
|
||||
void LineString::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<LineString>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
36
MapboxGLAndroidSDK/src/cpp/geojson/line_string.hpp
Normal file
36
MapboxGLAndroidSDK/src/cpp/geojson/line_string.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
|
||||
class LineString {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/LineString"; };
|
||||
static constexpr auto Type() { return "LineString"; };
|
||||
|
||||
static jni::Local<jni::Object<LineString>> New(jni::JNIEnv&, const mbgl::LineString<double>&);
|
||||
|
||||
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<LineString>&);
|
||||
|
||||
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<Point>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<LineString>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
56
MapboxGLAndroidSDK/src/cpp/geojson/multi_line_string.cpp
Normal file
56
MapboxGLAndroidSDK/src/cpp/geojson/multi_line_string.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "multi_line_string.hpp"
|
||||
|
||||
#include "line_string.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiLineString>> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) {
|
||||
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString> (jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsListsList(env, multiLineString));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<MultiLineString>& jMultiLineString) {
|
||||
mapbox::geojson::multi_line_string multiLineString;
|
||||
|
||||
if (jMultiLineString) {
|
||||
multiLineString = MultiLineString::convert(env, MultiLineString::coordinates(env, jMultiLineString));
|
||||
}
|
||||
|
||||
return multiLineString;
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) {
|
||||
mapbox::geojson::multi_line_string multiLineString;
|
||||
|
||||
if (jPointListsList) {
|
||||
auto jPositionListsArray = java::util::List::toArray<java::util::List>(env, jPointListsList);
|
||||
|
||||
auto size = jPositionListsArray.Length(env);
|
||||
multiLineString.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
multiLineString.push_back(LineString::convert(env, jPositionListsArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return multiLineString;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiLineString::coordinates(jni::JNIEnv &env, const jni::Object<MultiLineString>& jLineString) {
|
||||
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jLineString.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiLineString::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<MultiLineString>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
34
MapboxGLAndroidSDK/src/cpp/geojson/multi_line_string.hpp
Normal file
34
MapboxGLAndroidSDK/src/cpp/geojson/multi_line_string.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiLineString {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiLineString"; };
|
||||
static constexpr auto Type() { return "MultiLineString"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiLineString>> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&);
|
||||
|
||||
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<MultiLineString>&);
|
||||
|
||||
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiLineString>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
41
MapboxGLAndroidSDK/src/cpp/geojson/multi_point.cpp
Normal file
41
MapboxGLAndroidSDK/src/cpp/geojson/multi_point.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "multi_point.hpp"
|
||||
|
||||
#include "line_string.hpp"
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiPoint>> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) {
|
||||
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsList(env, multiPoint));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) {
|
||||
mapbox::geojson::multi_point multiPoint;
|
||||
|
||||
if (jMultiPoint) {
|
||||
multiPoint = convertExplicit<mapbox::geojson::multi_point>(
|
||||
LineString::convert(env, MultiPoint::coordinates(env, jMultiPoint)));
|
||||
}
|
||||
|
||||
return multiPoint;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiPoint::coordinates(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) {
|
||||
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jMultiPoint.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiPoint::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<MultiPoint>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
33
MapboxGLAndroidSDK/src/cpp/geojson/multi_point.hpp
Normal file
33
MapboxGLAndroidSDK/src/cpp/geojson/multi_point.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiPoint {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiPoint"; };
|
||||
static constexpr auto Type() { return "MultiPoint"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiPoint>> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&);
|
||||
|
||||
static mapbox::geojson::multi_point convert(jni::JNIEnv&, const jni::Object<MultiPoint>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPoint>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
53
MapboxGLAndroidSDK/src/cpp/geojson/multi_polygon.cpp
Normal file
53
MapboxGLAndroidSDK/src/cpp/geojson/multi_polygon.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "multi_polygon.hpp"
|
||||
|
||||
#include "polygon.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiPolygon>> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) {
|
||||
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size());
|
||||
|
||||
for (size_t i = 0; i < multiPolygon.size(); i++) {
|
||||
jarray.Set(env, i, asPointsListsList(env, multiPolygon.at(i)));
|
||||
}
|
||||
|
||||
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jMultiPolygon) {
|
||||
mapbox::geojson::multi_polygon multiPolygon;
|
||||
|
||||
if (jMultiPolygon) {
|
||||
auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon);
|
||||
auto jPointListsListArray = java::util::List::toArray<java::util::List>(env, jPointListsListList);
|
||||
|
||||
auto size = jPointListsListArray.Length(env);
|
||||
multiPolygon.reserve(size);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
multiPolygon.push_back(Polygon::convert(env, jPointListsListArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return multiPolygon;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiPolygon::coordinates(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jPolygon) {
|
||||
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jPolygon.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiPolygon::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<MultiPolygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
32
MapboxGLAndroidSDK/src/cpp/geojson/multi_polygon.hpp
Normal file
32
MapboxGLAndroidSDK/src/cpp/geojson/multi_polygon.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiPolygon {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiPolygon"; };
|
||||
static constexpr auto Type() { return "MultiPolygon"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiPolygon>> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&);
|
||||
|
||||
static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
34
MapboxGLAndroidSDK/src/cpp/geojson/point.cpp
Normal file
34
MapboxGLAndroidSDK/src/cpp/geojson/point.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<Point>> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) {
|
||||
static auto& javaClass = jni::Class<Point>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Point> (jni::jdouble, jni::jdouble)>(env, "fromLngLat");
|
||||
return javaClass.Call(env, method, point.x, point.y);
|
||||
}
|
||||
|
||||
mbgl::Point<double> Point::convert(jni::JNIEnv &env, const jni::Object<Point>& jPoint) {
|
||||
static auto& javaClass = jni::Class<Point>::Singleton(env);
|
||||
static auto longitude = javaClass.GetMethod<jni::jdouble ()>(env, "longitude");
|
||||
static auto latitude = javaClass.GetMethod<jni::jdouble ()>(env, "latitude");
|
||||
|
||||
if (!jPoint) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
jPoint.Call(env, longitude),
|
||||
jPoint.Call(env, latitude)
|
||||
};
|
||||
}
|
||||
|
||||
void Point::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Point>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
27
MapboxGLAndroidSDK/src/cpp/geojson/point.hpp
Normal file
27
MapboxGLAndroidSDK/src/cpp/geojson/point.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Point {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Point"; };
|
||||
static constexpr auto Type() { return "Point"; };
|
||||
|
||||
static jni::Local<jni::Object<Point>> New(jni::JNIEnv&, const mbgl::Point<double>&);
|
||||
static mbgl::Point<double> convert(jni::JNIEnv&, const jni::Object<Point>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
55
MapboxGLAndroidSDK/src/cpp/geojson/polygon.cpp
Normal file
55
MapboxGLAndroidSDK/src/cpp/geojson/polygon.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "polygon.hpp"
|
||||
|
||||
#include "multi_line_string.hpp"
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<Polygon>> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Polygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsListsList(env, polygon));
|
||||
}
|
||||
|
||||
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) {
|
||||
mapbox::geojson::polygon polygon;
|
||||
|
||||
if (jPolygon) {
|
||||
polygon = Polygon::convert(env, Polygon::coordinates(env, jPolygon));
|
||||
}
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) {
|
||||
mapbox::geojson::polygon polygon;
|
||||
|
||||
if (jPointListsList) {
|
||||
auto multiLine = MultiLineString::convert(env, jPointListsList);
|
||||
polygon.reserve(multiLine.size());
|
||||
for (auto&& line : multiLine) {
|
||||
polygon.emplace_back(convertExplicit<mapbox::geojson::linear_ring>(std::move(line)));
|
||||
}
|
||||
}
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> Polygon::coordinates(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jPolygon.Call(env, method);
|
||||
}
|
||||
|
||||
void Polygon::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Polygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
35
MapboxGLAndroidSDK/src/cpp/geojson/polygon.hpp
Normal file
35
MapboxGLAndroidSDK/src/cpp/geojson/polygon.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Polygon {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Polygon"; };
|
||||
static constexpr auto Type() { return "Polygon"; };
|
||||
|
||||
static jni::Local<jni::Object<Polygon>> New(jni::JNIEnv&, const mbgl::Polygon<double>&);
|
||||
|
||||
static mapbox::geojson::polygon convert(jni::JNIEnv &, const jni::Object<Polygon>&);
|
||||
|
||||
static mapbox::geojson::polygon convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<Polygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv &);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
52
MapboxGLAndroidSDK/src/cpp/geojson/util.hpp
Normal file
52
MapboxGLAndroidSDK/src/cpp/geojson/util.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "point.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
// Clang 3.8 fails to implicitly convert matching types, so we'll have to do it explicitly.
|
||||
template <typename To, typename From>
|
||||
To convertExplicit(From&& src) {
|
||||
static_assert(std::is_same<typename std::decay_t<From>::container_type,
|
||||
typename To::container_type>::value,
|
||||
"container types do not match");
|
||||
static_assert(std::is_rvalue_reference<From&&>::value,
|
||||
"argument must be rvalue reference");
|
||||
return *reinterpret_cast<std::add_pointer_t<To>>(&src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geometry -> List<Point>
|
||||
*/
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<java::util::List>> asPointsList(jni::JNIEnv& env, const T& pointsList) {
|
||||
auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size());
|
||||
|
||||
for (jni::jsize i = 0; i < pointsList.size(); i++) {
|
||||
jarray.Set(env, i, Point::New(env, pointsList.at(i)));
|
||||
}
|
||||
|
||||
return java::util::Arrays::asList(env, jarray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geometry -> List<List<Point>>
|
||||
*/
|
||||
template <class SHAPE>
|
||||
static jni::Local<jni::Object<java::util::List>> asPointsListsList(JNIEnv& env, const SHAPE& value) {
|
||||
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); i++) {
|
||||
jarray.Set(env, i, asPointsList(env, value[i]));
|
||||
}
|
||||
|
||||
return java::util::Arrays::asList(env, jarray);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
29
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng.cpp
Normal file
29
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLng>> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) {
|
||||
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double>(env);
|
||||
return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude());
|
||||
}
|
||||
|
||||
mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
|
||||
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
|
||||
static auto latitudeField = javaClass.GetField<jni::jdouble>(env, "latitude");
|
||||
static auto longitudeField = javaClass.GetField<jni::jdouble>(env, "longitude");
|
||||
return mbgl::Point<double>(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField));
|
||||
}
|
||||
|
||||
mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
|
||||
auto point = LatLng::getGeometry(env, latLng);
|
||||
return mbgl::LatLng(point.y, point.x);
|
||||
}
|
||||
|
||||
void LatLng::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLng>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
29
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng.hpp
Normal file
29
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLng : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLng"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLng>> New(jni::JNIEnv&, const mbgl::LatLng&);
|
||||
|
||||
static mbgl::Point<double> getGeometry(jni::JNIEnv&, const jni::Object<LatLng>&);
|
||||
|
||||
static mbgl::LatLng getLatLng(jni::JNIEnv&, const jni::Object<LatLng>&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
30
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_bounds.cpp
Normal file
30
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_bounds.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "lat_lng_bounds.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLngBounds>> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) {
|
||||
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double, double, double>(env);
|
||||
return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west());
|
||||
}
|
||||
|
||||
mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& bounds) {
|
||||
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
|
||||
static auto swLatField = javaClass.GetField<jni::jdouble>(env, "latitudeSouth");
|
||||
static auto swLonField = javaClass.GetField<jni::jdouble>(env, "longitudeWest");
|
||||
static auto neLatField = javaClass.GetField<jni::jdouble>(env, "latitudeNorth");
|
||||
static auto neLonField = javaClass.GetField<jni::jdouble>(env, "longitudeEast");
|
||||
|
||||
mbgl::LatLng sw = { bounds.Get(env, swLatField), bounds.Get(env, swLonField) };
|
||||
mbgl::LatLng ne = { bounds.Get(env, neLatField), bounds.Get(env, neLonField) };
|
||||
|
||||
return mbgl::LatLngBounds::hull(sw, ne);
|
||||
}
|
||||
|
||||
void LatLngBounds::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLngBounds>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
26
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_bounds.hpp
Normal file
26
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_bounds.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLngBounds : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngBounds"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLngBounds>> New(jni::JNIEnv&, mbgl::LatLngBounds);
|
||||
|
||||
static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, const jni::Object<LatLngBounds>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
37
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_quad.cpp
Normal file
37
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_quad.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "lat_lng_quad.hpp"
|
||||
#include "lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLngQuad>> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLng, 4> coordinates) {
|
||||
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
|
||||
static auto quadConstructor = javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(env);
|
||||
return javaClass.New(env, quadConstructor,
|
||||
LatLng::New(env, coordinates[0]),
|
||||
LatLng::New(env, coordinates[1]),
|
||||
LatLng::New(env, coordinates[2]),
|
||||
LatLng::New(env, coordinates[3]));
|
||||
}
|
||||
|
||||
std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, const jni::Object<LatLngQuad>& quad) {
|
||||
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
|
||||
static auto topLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "topLeft");
|
||||
static auto topRightField = javaClass.GetField <jni::Object<LatLng>>(env, "topRight");
|
||||
static auto bottomRightField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomRight");
|
||||
static auto bottomLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomLeft");
|
||||
|
||||
return std::array < mbgl::LatLng, 4 > {{
|
||||
LatLng::getLatLng(env, quad.Get(env, topLeftField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, topRightField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, bottomRightField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, bottomLeftField))
|
||||
}};
|
||||
}
|
||||
|
||||
void LatLngQuad::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLngQuad>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
27
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_quad.hpp
Normal file
27
MapboxGLAndroidSDK/src/cpp/geometry/lat_lng_quad.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLngQuad : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngQuad"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLngQuad>> New(jni::JNIEnv&, std::array<mbgl::LatLng, 4>);
|
||||
|
||||
static std::array<mbgl::LatLng, 4> getLatLngArray(jni::JNIEnv&, const jni::Object<LatLngQuad>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
17
MapboxGLAndroidSDK/src/cpp/geometry/projected_meters.cpp
Normal file
17
MapboxGLAndroidSDK/src/cpp/geometry/projected_meters.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "projected_meters.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<ProjectedMeters>> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) {
|
||||
static auto& javaClass = jni::Class<ProjectedMeters>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double>(env);
|
||||
return javaClass.New(env, constructor, northing, easting);
|
||||
}
|
||||
|
||||
void ProjectedMeters::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<ProjectedMeters>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
21
MapboxGLAndroidSDK/src/cpp/geometry/projected_meters.hpp
Normal file
21
MapboxGLAndroidSDK/src/cpp/geometry/projected_meters.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class ProjectedMeters : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/ProjectedMeters"; };
|
||||
|
||||
static jni::Local<jni::Object<ProjectedMeters>> New(jni::JNIEnv&, double, double);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
25
MapboxGLAndroidSDK/src/cpp/graphics/pointf.cpp
Normal file
25
MapboxGLAndroidSDK/src/cpp/graphics/pointf.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include "pointf.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<PointF>> PointF::New(jni::JNIEnv& env, float x, float y) {
|
||||
static auto& javaClass = jni::Class<PointF>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<float, float>(env);
|
||||
return javaClass.New(env, constructor, x, y);
|
||||
}
|
||||
|
||||
mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, const jni::Object<PointF>& point) {
|
||||
static auto& javaClass = jni::Class<PointF>::Singleton(env);
|
||||
static auto xField = javaClass.GetField<jni::jfloat>(env, "x");
|
||||
static auto yField = javaClass.GetField<jni::jfloat>(env, "y");
|
||||
return mbgl::ScreenCoordinate{point.Get(env, xField), point.Get(env, yField)};
|
||||
}
|
||||
|
||||
void PointF::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<PointF>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
24
MapboxGLAndroidSDK/src/cpp/graphics/pointf.hpp
Normal file
24
MapboxGLAndroidSDK/src/cpp/graphics/pointf.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class PointF : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "android/graphics/PointF"; };
|
||||
|
||||
static jni::Local<jni::Object<PointF>> New(jni::JNIEnv&, float, float);
|
||||
|
||||
static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, const jni::Object<PointF>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
35
MapboxGLAndroidSDK/src/cpp/graphics/rectf.cpp
Normal file
35
MapboxGLAndroidSDK/src/cpp/graphics/rectf.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "rectf.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
float RectF::getLeft(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "left");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getTop(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "top");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getRight(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "right");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getBottom(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "bottom");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
void RectF::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<RectF>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
28
MapboxGLAndroidSDK/src/cpp/graphics/rectf.hpp
Normal file
28
MapboxGLAndroidSDK/src/cpp/graphics/rectf.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class RectF : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "android/graphics/RectF"; };
|
||||
|
||||
static float getLeft(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getTop(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getRight(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getBottom(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
50
MapboxGLAndroidSDK/src/cpp/gson/json_array.cpp
Normal file
50
MapboxGLAndroidSDK/src/cpp/gson/json_array.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "json_array.hpp"
|
||||
#include "json_element.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
jni::Local<jni::Object<JsonArray>> JsonArray::New(jni::JNIEnv& env, const std::vector<mbgl::Value>& values){
|
||||
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor(env);
|
||||
static auto addMethod = javaClass.GetMethod<void (jni::Object<JsonElement>)>(env, "add");
|
||||
|
||||
auto jsonArray = javaClass.New(env, constructor);
|
||||
|
||||
for (const auto &v : values) {
|
||||
jsonArray.Call(env, addMethod, JsonElement::New(env, v));
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
std::vector<mbgl::Value> JsonArray::convert(jni::JNIEnv& env, const jni::Object<JsonArray>& jsonArray) {
|
||||
std::vector<mbgl::Value> values;
|
||||
|
||||
if (jsonArray) {
|
||||
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
|
||||
static auto getMethod = javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get");
|
||||
static auto sizeMethod = javaClass.GetMethod<jni::jint ()>(env, "size");
|
||||
|
||||
int size = jsonArray.Call(env, sizeMethod);
|
||||
values.reserve(uint(size));
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
auto entry = jsonArray.Call(env, getMethod, i);
|
||||
if (entry) {
|
||||
values.push_back(JsonElement::convert(env, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
void JsonArray::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<JsonArray>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
24
MapboxGLAndroidSDK/src/cpp/gson/json_array.hpp
Normal file
24
MapboxGLAndroidSDK/src/cpp/gson/json_array.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonArray {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonArray"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonArray>> New(jni::JNIEnv&, const std::vector<mbgl::Value>&);
|
||||
static std::vector<mbgl::Value> convert(JNIEnv&, const jni::Object<JsonArray>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
88
MapboxGLAndroidSDK/src/cpp/gson/json_element.cpp
Normal file
88
MapboxGLAndroidSDK/src/cpp/gson/json_element.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "json_element.hpp"
|
||||
#include "json_array.hpp"
|
||||
#include "json_object.hpp"
|
||||
#include "json_primitive.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
jni::Local<jni::Object<JsonElement>> JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) {
|
||||
static auto& primitive = jni::Class<JsonPrimitive>::Singleton(env);
|
||||
static auto stringConstructor = primitive.GetConstructor<jni::String>(env);
|
||||
static auto numberConstructor = primitive.GetConstructor<jni::Number>(env);
|
||||
static auto booleanConstructor = primitive.GetConstructor<jni::Boolean>(env);
|
||||
|
||||
return value.match(
|
||||
[&] (const mbgl::NullValue&) {
|
||||
return jni::Local<jni::Object<JsonElement>>();
|
||||
},
|
||||
[&] (const std::string& value) {
|
||||
return primitive.New(env, stringConstructor, jni::Make<jni::String>(env, value));
|
||||
},
|
||||
[&] (const double value) {
|
||||
return primitive.New(env, numberConstructor, jni::Box(env, value));
|
||||
},
|
||||
[&] (const int64_t value) {
|
||||
return primitive.New(env, numberConstructor, jni::Box(env, value));
|
||||
},
|
||||
[&] (const uint64_t value) {
|
||||
return primitive.New(env, numberConstructor, jni::Box(env, int64_t(value))); // TODO: should use BigInteger
|
||||
},
|
||||
[&] (const bool value) {
|
||||
return primitive.New(env, booleanConstructor, jni::Box(env, value ? jni::jni_true : jni::jni_false));
|
||||
},
|
||||
[&] (const std::vector<mbgl::Value>& values) {
|
||||
return JsonArray::New(env, values);
|
||||
},
|
||||
[&] (const mbgl::PropertyMap& values) {
|
||||
return JsonObject::New(env, values);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
mbgl::Value JsonElement::convert(jni::JNIEnv &env, const jni::Object<JsonElement>& jsonElement) {
|
||||
if (!jsonElement) {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
|
||||
static auto& elementClass = jni::Class<JsonElement>::Singleton(env);
|
||||
static auto isJsonObject = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonObject");
|
||||
static auto isJsonArray = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonArray");
|
||||
static auto isJsonPrimitive = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive");
|
||||
|
||||
static auto& primitiveClass = jni::Class<JsonPrimitive>::Singleton(env);
|
||||
static auto isBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "isBoolean");
|
||||
static auto isString = primitiveClass.GetMethod<jni::jboolean ()>(env, "isString");
|
||||
static auto isNumber = primitiveClass.GetMethod<jni::jboolean ()>(env, "isNumber");
|
||||
static auto getAsBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean");
|
||||
static auto getAsString = primitiveClass.GetMethod<jni::String ()>(env, "getAsString");
|
||||
static auto getAsDouble = primitiveClass.GetMethod<jni::jdouble ()>(env, "getAsDouble");
|
||||
|
||||
if (jsonElement.Call(env, isJsonPrimitive)) {
|
||||
auto primitive = jni::Cast(env, primitiveClass, jsonElement);
|
||||
if (primitive.Call(env, isBoolean)) {
|
||||
return bool(primitive.Call(env, getAsBoolean));
|
||||
} else if (primitive.Call(env, isNumber)) {
|
||||
return primitive.Call(env, getAsDouble);
|
||||
} else if (primitive.Call(env, isString)) {
|
||||
return jni::Make<std::string>(env, primitive.Call(env, getAsString));
|
||||
} else {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
} else if (jsonElement.Call(env, isJsonObject)) {
|
||||
return JsonObject::convert(env, jni::Cast(env, jni::Class<JsonObject>::Singleton(env), jsonElement));
|
||||
} else if (jsonElement.Call(env, isJsonArray)) {
|
||||
return JsonArray::convert(env, jni::Cast(env, jni::Class<JsonArray>::Singleton(env), jsonElement));
|
||||
} else {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonElement::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<JsonElement>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
24
MapboxGLAndroidSDK/src/cpp/gson/json_element.hpp
Normal file
24
MapboxGLAndroidSDK/src/cpp/gson/json_element.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/feature.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonElement {
|
||||
public:
|
||||
using SuperTag = jni::ObjectTag;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonElement"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonElement>> New(jni::JNIEnv&, const mbgl::Value&);
|
||||
static mbgl::Value convert(JNIEnv&, const jni::Object<JsonElement>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
65
MapboxGLAndroidSDK/src/cpp/gson/json_object.cpp
Normal file
65
MapboxGLAndroidSDK/src/cpp/gson/json_object.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "json_object.hpp"
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
|
||||
jni::Local<jni::Object<JsonObject>> JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) {
|
||||
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor(env);
|
||||
static auto addMethod = javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add");
|
||||
|
||||
auto jsonObject = javaClass.New(env, constructor);
|
||||
|
||||
for (auto &item : values) {
|
||||
jsonObject.Call(env, addMethod,
|
||||
jni::Make<jni::String>(env, item.first),
|
||||
JsonElement::New(env, item.second));
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
template <typename F> // void (jni::String, jni::Object<gson::JsonElement>)
|
||||
static void iterateEntrySet(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject, F callback) {
|
||||
// Get Set<Map.Entry<String, JsonElement>>
|
||||
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet");
|
||||
|
||||
auto entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, jsonObject.Call(env, method));
|
||||
|
||||
size_t size = entryArray.Length(env);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
auto entry = entryArray.Get(env, i);
|
||||
if (entry) {
|
||||
callback(
|
||||
java::util::Map::Entry::getKey<jni::StringTag>(env, entry),
|
||||
java::util::Map::Entry::getValue<gson::JsonElement>(env, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mbgl::PropertyMap JsonObject::convert(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject) {
|
||||
mbgl::PropertyMap map;
|
||||
|
||||
if (jsonObject) {
|
||||
iterateEntrySet(env, jsonObject, [&map, &env](const jni::String& jId, const jni::Object<gson::JsonElement>& jsonElement) {
|
||||
map[jni::Make<std::string>(env, jId)] = JsonElement::convert(env, jsonElement);
|
||||
});
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void JsonObject::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<JsonObject>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
24
MapboxGLAndroidSDK/src/cpp/gson/json_object.hpp
Normal file
24
MapboxGLAndroidSDK/src/cpp/gson/json_object.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonObject {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonObject"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonObject>> New(jni::JNIEnv&, const mbgl::PropertyMap&);
|
||||
static mbgl::PropertyMap convert(JNIEnv&, const jni::Object<JsonObject>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
13
MapboxGLAndroidSDK/src/cpp/gson/json_primitive.cpp
Normal file
13
MapboxGLAndroidSDK/src/cpp/gson/json_primitive.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "json_primitive.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
void JsonPrimitive::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<JsonPrimitive>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
21
MapboxGLAndroidSDK/src/cpp/gson/json_primitive.hpp
Normal file
21
MapboxGLAndroidSDK/src/cpp/gson/json_primitive.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonPrimitive {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
195
MapboxGLAndroidSDK/src/cpp/http_file_source.cpp
Normal file
195
MapboxGLAndroidSDK/src/cpp/http_file_source.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <mbgl/storage/http_file_source.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <mbgl/util/async_request.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/http_header.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class HTTPFileSource::Impl {
|
||||
public:
|
||||
android::UniqueEnv env { android::AttachEnv() };
|
||||
};
|
||||
|
||||
class HTTPRequest : public AsyncRequest {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/http/NativeHttpRequest"; };
|
||||
|
||||
HTTPRequest(jni::JNIEnv&, const Resource&, FileSource::Callback);
|
||||
~HTTPRequest();
|
||||
|
||||
void onFailure(jni::JNIEnv&, int type, const jni::String& message);
|
||||
void onResponse(jni::JNIEnv&, int code,
|
||||
const jni::String& etag, const jni::String& modified,
|
||||
const jni::String& cacheControl, const jni::String& expires,
|
||||
const jni::String& retryAfter, const jni::String& xRateLimitReset,
|
||||
const jni::Array<jni::jbyte>& body);
|
||||
|
||||
jni::Global<jni::Object<HTTPRequest>> javaRequest;
|
||||
|
||||
private:
|
||||
Resource resource;
|
||||
FileSource::Callback callback;
|
||||
Response response;
|
||||
|
||||
util::AsyncTask async { [this] {
|
||||
// Calling `callback` may result in deleting `this`. Copy data to temporaries first.
|
||||
auto callback_ = callback;
|
||||
auto response_ = response;
|
||||
callback_(response_);
|
||||
} };
|
||||
|
||||
static const int connectionError = 0;
|
||||
static const int temporaryError = 1;
|
||||
static const int permanentError = 2;
|
||||
};
|
||||
|
||||
namespace android {
|
||||
|
||||
void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<HTTPRequest>(env, javaClass, "nativePtr",
|
||||
METHOD(&HTTPRequest::onFailure, "nativeOnFailure"),
|
||||
METHOD(&HTTPRequest::onResponse, "nativeOnResponse"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource::Callback callback_)
|
||||
: resource(resource_),
|
||||
callback(callback_) {
|
||||
std::string etagStr;
|
||||
std::string modifiedStr;
|
||||
|
||||
if (resource.priorEtag) {
|
||||
etagStr = *resource.priorEtag;
|
||||
} else if (resource.priorModified) {
|
||||
modifiedStr = util::rfc1123(*resource.priorModified);
|
||||
}
|
||||
|
||||
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10);
|
||||
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
|
||||
static auto constructor =
|
||||
javaClass.GetConstructor<jni::jlong, jni::String, jni::String, jni::String, jni::jboolean>(env);
|
||||
|
||||
javaRequest = jni::NewGlobal(env,
|
||||
javaClass.New(env, constructor,
|
||||
reinterpret_cast<jlong>(this),
|
||||
jni::Make<jni::String>(env, resource.url),
|
||||
jni::Make<jni::String>(env, etagStr),
|
||||
jni::Make<jni::String>(env, modifiedStr),
|
||||
(jboolean) (resource_.usage == Resource::Usage::Offline)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(*env);
|
||||
static auto cancel = javaClass.GetMethod<void ()>(*env, "cancel");
|
||||
|
||||
javaRequest.Call(*env, cancel);
|
||||
}
|
||||
|
||||
void HTTPRequest::onResponse(jni::JNIEnv& env, int code,
|
||||
const jni::String& etag, const jni::String& modified,
|
||||
const jni::String& cacheControl, const jni::String& expires,
|
||||
const jni::String& jRetryAfter, const jni::String& jXRateLimitReset,
|
||||
const jni::Array<jni::jbyte>& body) {
|
||||
|
||||
using Error = Response::Error;
|
||||
|
||||
if (etag) {
|
||||
response.etag = jni::Make<std::string>(env, etag);
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
response.modified = util::parseTimestamp(jni::Make<std::string>(env, modified).c_str());
|
||||
}
|
||||
|
||||
if (cacheControl) {
|
||||
const auto cc = http::CacheControl::parse(jni::Make<std::string>(env, cacheControl).c_str());
|
||||
response.expires = cc.toTimePoint();
|
||||
response.mustRevalidate = cc.mustRevalidate;
|
||||
}
|
||||
|
||||
if (expires) {
|
||||
response.expires = util::parseTimestamp(jni::Make<std::string>(env, expires).c_str());
|
||||
}
|
||||
|
||||
if (code == 200) {
|
||||
if (body) {
|
||||
auto data = std::make_shared<std::string>(body.Length(env), char());
|
||||
jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
|
||||
response.data = data;
|
||||
} else {
|
||||
response.data = std::make_shared<std::string>();
|
||||
}
|
||||
} else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) {
|
||||
response.noContent = true;
|
||||
} else if (code == 304) {
|
||||
response.notModified = true;
|
||||
} else if (code == 404) {
|
||||
response.error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
|
||||
} else if (code == 429) {
|
||||
optional<std::string> retryAfter;
|
||||
optional<std::string> xRateLimitReset;
|
||||
if (jRetryAfter) {
|
||||
retryAfter = jni::Make<std::string>(env, jRetryAfter);
|
||||
}
|
||||
if (jXRateLimitReset) {
|
||||
xRateLimitReset = jni::Make<std::string>(env, jXRateLimitReset);
|
||||
}
|
||||
response.error = std::make_unique<Error>(Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset));
|
||||
} else if (code >= 500 && code < 600) {
|
||||
response.error = std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } + util::toString(code));
|
||||
} else {
|
||||
response.error = std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } + util::toString(code));
|
||||
}
|
||||
|
||||
async.send();
|
||||
}
|
||||
|
||||
void HTTPRequest::onFailure(jni::JNIEnv& env, int type, const jni::String& message) {
|
||||
std::string messageStr = jni::Make<std::string>(env, message);
|
||||
|
||||
using Error = Response::Error;
|
||||
|
||||
switch (type) {
|
||||
case connectionError:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Connection, messageStr);
|
||||
break;
|
||||
case temporaryError:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Server, messageStr);
|
||||
break;
|
||||
default:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Other, messageStr);
|
||||
}
|
||||
|
||||
async.send();
|
||||
}
|
||||
|
||||
HTTPFileSource::HTTPFileSource()
|
||||
: impl(std::make_unique<Impl>()) {
|
||||
}
|
||||
|
||||
HTTPFileSource::~HTTPFileSource() = default;
|
||||
|
||||
std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, Callback callback) {
|
||||
return std::make_unique<HTTPRequest>(*impl->env, resource, callback);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
192
MapboxGLAndroidSDK/src/cpp/i18n/collator.cpp
Normal file
192
MapboxGLAndroidSDK/src/cpp/i18n/collator.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
#include <mbgl/i18n/collator.hpp>
|
||||
#include <mbgl/text/language_tag.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "collator_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void Collator::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Collator>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Collator>> Collator::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Collator> (jni::Object<Locale>)>(env, "getInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
void Collator::setStrength(jni::JNIEnv& env, const jni::Object<Collator>& collator, jni::jint strength) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setStrength");
|
||||
collator.Call(env, method, strength);
|
||||
}
|
||||
|
||||
jni::jint Collator::compare(jni::JNIEnv& env, const jni::Object<Collator>& collator, const jni::String& lhs, const jni::String& rhs) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::jint (jni::String, jni::String)>(env, "compare");
|
||||
return collator.Call(env, method, lhs, rhs);
|
||||
}
|
||||
|
||||
void StringUtils::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<StringUtils>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> StringUtils::unaccent(jni::JNIEnv& env, const jni::String& value) {
|
||||
static auto& javaClass = jni::Class<StringUtils>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::String (jni::String)>(env, "unaccent");
|
||||
return javaClass.Call(env, method, value);
|
||||
}
|
||||
|
||||
void Locale::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Locale>::Singleton(env);
|
||||
}
|
||||
|
||||
/*
|
||||
We would prefer to use for/toLanguageTag, but they're only available in API level 21+
|
||||
|
||||
jni::Object<Locale> Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) {
|
||||
using Signature = jni::Object<Locale>(jni::String);
|
||||
auto method = javaClass.GetStaticMethod<Signature>(env, "forLanguageTag");
|
||||
return javaClass.Call(env, method, languageTag);
|
||||
}
|
||||
|
||||
jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object<Locale> locale) {
|
||||
using Signature = jni::String();
|
||||
auto static method = javaClass.GetMethod<Signature>(env, "toLanguageTag");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
*/
|
||||
|
||||
jni::Local<jni::String> Locale::getLanguage(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String ()>(env, "getLanguage");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> Locale::getCountry(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String ()>(env, "getCountry");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::getDefault(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Locale> ()>(env, "getDefault");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String>(env);
|
||||
return javaClass.New(env, constructor, language);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language, const jni::String& region) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env);
|
||||
return javaClass.New(env, constructor, language, region);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
namespace platform {
|
||||
|
||||
class Collator::Impl {
|
||||
public:
|
||||
Impl(bool caseSensitive_, bool diacriticSensitive_, optional<std::string> locale_)
|
||||
: caseSensitive(caseSensitive_)
|
||||
, diacriticSensitive(diacriticSensitive_)
|
||||
, env(android::AttachEnv())
|
||||
{
|
||||
LanguageTag languageTag = locale_ ? LanguageTag::fromBCP47(*locale_) : LanguageTag();
|
||||
if (!languageTag.language) {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::getDefault(*env));
|
||||
} else if (!languageTag.region) {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
|
||||
} else {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language),
|
||||
jni::Make<jni::String>(*env, *languageTag.region)));
|
||||
}
|
||||
collator = jni::NewGlobal(*env, android::Collator::getInstance(*env, locale));
|
||||
if (!diacriticSensitive && !caseSensitive) {
|
||||
android::Collator::setStrength(*env, collator, 0 /*PRIMARY*/);
|
||||
} else if (diacriticSensitive && !caseSensitive) {
|
||||
android::Collator::setStrength(*env, collator, 1 /*SECONDARY*/);
|
||||
} else if (caseSensitive) {
|
||||
// If we're case-sensitive and diacritic-sensitive, we use a case-sensitive collator
|
||||
// and a fallback implementation of diacritic-insensitivity.
|
||||
android::Collator::setStrength(*env, collator, 2 /*TERTIARY*/);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Impl& other) const {
|
||||
return caseSensitive == other.caseSensitive &&
|
||||
diacriticSensitive == other.diacriticSensitive &&
|
||||
resolvedLocale() == other.resolvedLocale();
|
||||
}
|
||||
|
||||
int compare(const std::string& lhs, const std::string& rhs) const {
|
||||
bool useUnaccent = !diacriticSensitive && caseSensitive;
|
||||
// java.text.Collator doesn't support a diacritic-insensitive/case-sensitive collation
|
||||
// order, so we have to compromise here. We use Android's case-sensitive Collator
|
||||
// against strings that have been "unaccented" using non-locale-aware nunicode logic.
|
||||
// Because of the difference in locale-awareness, this means turning on case-sensitivity
|
||||
// can _potentially_ change compare results for strings that don't actually have any case
|
||||
// differences.
|
||||
jni::Local<jni::String> jlhs = useUnaccent
|
||||
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, lhs))
|
||||
: jni::Make<jni::String>(*env, lhs);
|
||||
jni::Local<jni::String> jrhs = useUnaccent
|
||||
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, rhs))
|
||||
: jni::Make<jni::String>(*env, rhs);
|
||||
|
||||
jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string resolvedLocale() const {
|
||||
std::string language = jni::Make<std::string>(*env, android::Locale::getLanguage(*env, locale));
|
||||
std::string region = jni::Make<std::string>(*env, android::Locale::getCountry(*env, locale));
|
||||
|
||||
optional<std::string> resultLanguage;
|
||||
if (!language.empty()) resultLanguage = language;
|
||||
optional<std::string> resultRegion;
|
||||
if (!region.empty()) resultRegion = region;
|
||||
|
||||
return LanguageTag(resultLanguage, {}, resultRegion).toBCP47();
|
||||
}
|
||||
|
||||
private:
|
||||
bool caseSensitive;
|
||||
bool diacriticSensitive;
|
||||
|
||||
android::UniqueEnv env;
|
||||
jni::Global<jni::Object<android::Collator>> collator;
|
||||
jni::Global<jni::Object<android::Locale>> locale;
|
||||
};
|
||||
|
||||
Collator::Collator(bool caseSensitive, bool diacriticSensitive, const optional<std::string>& locale_)
|
||||
: impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, locale_)) {}
|
||||
|
||||
bool Collator::operator==(const Collator& other) const {
|
||||
return *impl == *(other.impl);
|
||||
}
|
||||
|
||||
int Collator::compare(const std::string& lhs, const std::string& rhs) const {
|
||||
return impl->compare(lhs, rhs);
|
||||
}
|
||||
|
||||
std::string Collator::resolvedLocale() const {
|
||||
return impl->resolvedLocale();
|
||||
}
|
||||
|
||||
} // namespace platform
|
||||
} // namespace mbgl
|
||||
62
MapboxGLAndroidSDK/src/cpp/i18n/collator_jni.hpp
Normal file
62
MapboxGLAndroidSDK/src/cpp/i18n/collator_jni.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
/*
|
||||
android::Collator and android::Locale are
|
||||
the JNI wrappers of
|
||||
java/text/Collator and java/util/Locale
|
||||
|
||||
mbgl::Collator is the portable interface
|
||||
Both implementations are in collator.cpp
|
||||
*/
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Locale {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Locale"; };
|
||||
|
||||
/* Requires API level 21+ in order to support script/variant
|
||||
static jni::Object<Locale> forLanguageTag(jni::JNIEnv&, jni::String);
|
||||
static jni::String toLanguageTag(jni::JNIEnv&, jni::Object<Locale>);
|
||||
*/
|
||||
static jni::Local<jni::Object<Locale>> getDefault(jni::JNIEnv&);
|
||||
static jni::Local<jni::String> getLanguage(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::String> getCountry(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
|
||||
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&);
|
||||
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&, const jni::String&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
class Collator {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/text/Collator"; };
|
||||
|
||||
static jni::Local<jni::Object<Collator>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
|
||||
static void setStrength(jni::JNIEnv&, const jni::Object<Collator>&, jni::jint);
|
||||
|
||||
static jni::jint compare(jni::JNIEnv&, const jni::Object<Collator>&, const jni::String&, const jni::String&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
class StringUtils {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/utils/StringUtils"; };
|
||||
|
||||
static jni::Local<jni::String> unaccent(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
80
MapboxGLAndroidSDK/src/cpp/i18n/number_format.cpp
Normal file
80
MapboxGLAndroidSDK/src/cpp/i18n/number_format.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <mbgl/i18n/number_format.hpp>
|
||||
#include <mbgl/text/language_tag.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "number_format_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void NumberFormat::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<NumberFormat>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<NumberFormat>> NumberFormat::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat> (jni::Object<Locale>)>(env, "getInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<NumberFormat>> NumberFormat::getCurrencyInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat> (jni::Object<Locale>)>(env, "getCurrencyInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> NumberFormat::format(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jdouble number) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String (jni::jdouble)>(env, "format");
|
||||
return nf.Call(env, method, number);
|
||||
}
|
||||
|
||||
void NumberFormat::setMinimumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setMinimumFractionDigits");
|
||||
return nf.Call(env, method, value);
|
||||
}
|
||||
|
||||
void NumberFormat::setMaximumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setMaximumFractionDigits");
|
||||
return nf.Call(env, method, value);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
namespace platform {
|
||||
|
||||
std::string formatNumber(double number, const std::string& localeId, const std::string& currency,
|
||||
uint8_t minFractionDigits, uint8_t maxFractionDigits) {
|
||||
|
||||
auto env{ android::AttachEnv() };
|
||||
|
||||
jni::Global<jni::Object<android::Locale>> locale;
|
||||
LanguageTag languageTag = !localeId.empty() ? LanguageTag::fromBCP47(localeId) : LanguageTag();
|
||||
if (!languageTag.language) {
|
||||
locale = jni::NewGlobal(*env, android::Locale::getDefault(*env));
|
||||
} else if (!languageTag.region) {
|
||||
locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
|
||||
} else {
|
||||
locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language),
|
||||
jni::Make<jni::String>(*env, *languageTag.region)));
|
||||
}
|
||||
|
||||
jni::Global<jni::Object<android::NumberFormat>> formatter;
|
||||
if (currency.empty()) {
|
||||
formatter = jni::NewGlobal(*env, android::NumberFormat::getInstance(*env, locale));
|
||||
android::NumberFormat::setMinimumFractionDigits(*env, formatter, static_cast<jni::jint>(minFractionDigits));
|
||||
android::NumberFormat::setMaximumFractionDigits(*env, formatter, static_cast<jni::jint>(maxFractionDigits));
|
||||
} else {
|
||||
formatter = jni::NewGlobal(*env, android::NumberFormat::getCurrencyInstance(*env, locale));
|
||||
}
|
||||
|
||||
auto result = android::NumberFormat::format(*env, formatter, static_cast<jni::jdouble>(number));
|
||||
return jni::Make<std::string>(*env, result);
|
||||
}
|
||||
|
||||
} // namespace platform
|
||||
} // namespace mbgl
|
||||
29
MapboxGLAndroidSDK/src/cpp/i18n/number_format_jni.hpp
Normal file
29
MapboxGLAndroidSDK/src/cpp/i18n/number_format_jni.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "collator_jni.hpp"
|
||||
|
||||
/*
|
||||
android::NumberFormat is the JNI wrapper
|
||||
of java/text/NumberFormat.
|
||||
*/
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class NumberFormat {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/text/NumberFormat"; };
|
||||
|
||||
static jni::Local<jni::Object<NumberFormat>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::Object<NumberFormat>> getCurrencyInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::String> format(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jdouble);
|
||||
static void setMinimumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
|
||||
static void setMaximumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
19
MapboxGLAndroidSDK/src/cpp/java/util.cpp
Normal file
19
MapboxGLAndroidSDK/src/cpp/java/util.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
namespace util {
|
||||
|
||||
void registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Arrays>::Singleton(env);
|
||||
jni::Class<List>::Singleton(env);
|
||||
jni::Class<Set>::Singleton(env);
|
||||
jni::Class<Map>::Singleton(env);
|
||||
jni::Class<Map::Entry>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
81
MapboxGLAndroidSDK/src/cpp/java/util.hpp
Normal file
81
MapboxGLAndroidSDK/src/cpp/java/util.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
namespace util {
|
||||
|
||||
class List : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/List"; };
|
||||
|
||||
template<class T>
|
||||
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<List>& list) {
|
||||
static auto& javaClass = jni::Class<List>::Singleton(env);
|
||||
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray");
|
||||
|
||||
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
|
||||
};
|
||||
};
|
||||
|
||||
class Arrays : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Arrays"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<List>> asList(jni::JNIEnv& env, const jni::Array<jni::Object<T>>& array) {
|
||||
static auto& javaClass = jni::Class<Arrays>::Singleton(env);
|
||||
static auto asList = javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList");
|
||||
|
||||
auto typeErasedArray = jni::Local<jni::Array<jni::Object<>>>(env, jni::NewLocal(env, array).release());
|
||||
return javaClass.Call(env, asList, typeErasedArray);
|
||||
}
|
||||
};
|
||||
|
||||
class Set : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Set"; };
|
||||
|
||||
template<class T>
|
||||
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<Set>& list) {
|
||||
static auto& javaClass = jni::Class<Set>::Singleton(env);
|
||||
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray");
|
||||
|
||||
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
|
||||
};
|
||||
};
|
||||
|
||||
class Map : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Map"; };
|
||||
|
||||
class Entry : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Map$Entry"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<T>> getKey(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
|
||||
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getKey");
|
||||
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<T>> getValue(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
|
||||
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getValue");
|
||||
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void registerNative(jni::JNIEnv&);
|
||||
|
||||
} // namespace util
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
49
MapboxGLAndroidSDK/src/cpp/java_types.cpp
Normal file
49
MapboxGLAndroidSDK/src/cpp/java_types.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "java_types.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
|
||||
jni::jclass* ObjectArray::jclass;
|
||||
|
||||
jni::jclass* String::jclass;
|
||||
|
||||
jni::jclass* Boolean::jclass;
|
||||
jni::jmethodID* Boolean::booleanValueMethodId;
|
||||
|
||||
jni::jclass* Number::jclass;
|
||||
jni::jmethodID* Number::floatValueMethodId;
|
||||
jni::jmethodID* Number::doubleValueMethodId;
|
||||
jni::jmethodID* Number::longValueMethodId;
|
||||
|
||||
jni::jclass* Map::jclass;
|
||||
jni::jmethodID* Map::getMethodId;
|
||||
jni::jmethodID* Map::keySetMethodId;
|
||||
|
||||
jni::jclass* Set::jclass;
|
||||
jni::jmethodID* Set::toArrayMethodId;
|
||||
|
||||
void registerNatives(JNIEnv& env) {
|
||||
ObjectArray::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "[Ljava/lang/Object;")).release();
|
||||
|
||||
String::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release();
|
||||
|
||||
Boolean::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release();
|
||||
Boolean::booleanValueMethodId = &jni::GetMethodID(env, *Boolean::jclass, "booleanValue", "()Z");
|
||||
|
||||
Number::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Number")).release();
|
||||
Number::floatValueMethodId = &jni::GetMethodID(env, *Number::jclass, "floatValue", "()F");
|
||||
Number::doubleValueMethodId = &jni::GetMethodID(env, *Number::jclass, "doubleValue", "()D");
|
||||
Number::longValueMethodId = &jni::GetMethodID(env, *Number::jclass, "longValue", "()J");
|
||||
|
||||
Map::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Map")).release();
|
||||
Map::getMethodId = &jni::GetMethodID(env, *Map::jclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
Map::keySetMethodId = &jni::GetMethodID(env, *Map::jclass, "keySet", "()Ljava/util/Set;");
|
||||
|
||||
Set::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Set")).release();
|
||||
Set::toArrayMethodId = &jni::GetMethodID(env, *Set::jclass, "toArray", "()[Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
43
MapboxGLAndroidSDK/src/cpp/java_types.hpp
Normal file
43
MapboxGLAndroidSDK/src/cpp/java_types.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
|
||||
struct ObjectArray {
|
||||
static jni::jclass* jclass;
|
||||
};
|
||||
|
||||
struct String {
|
||||
static jni::jclass* jclass;
|
||||
};
|
||||
|
||||
struct Boolean {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* booleanValueMethodId;
|
||||
};
|
||||
|
||||
struct Number {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* floatValueMethodId;
|
||||
static jni::jmethodID* doubleValueMethodId;
|
||||
static jni::jmethodID* longValueMethodId;
|
||||
};
|
||||
|
||||
struct Map {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* getMethodId;
|
||||
static jni::jmethodID* keySetMethodId;
|
||||
};
|
||||
|
||||
struct Set {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* toArrayMethodId;
|
||||
};
|
||||
|
||||
void registerNatives(JNIEnv&);
|
||||
}
|
||||
}
|
||||
}
|
||||
168
MapboxGLAndroidSDK/src/cpp/jni_native.cpp
Normal file
168
MapboxGLAndroidSDK/src/cpp/jni_native.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "jni_native.hpp"
|
||||
|
||||
#include "annotation/marker.hpp"
|
||||
#include "annotation/polygon.hpp"
|
||||
#include "annotation/polyline.hpp"
|
||||
#include "bitmap.hpp"
|
||||
#include "bitmap_factory.hpp"
|
||||
#include "connectivity_listener.hpp"
|
||||
#include "conversion/collection.hpp"
|
||||
#include "conversion/conversion.hpp"
|
||||
#include "file_source.hpp"
|
||||
#include "geojson/feature.hpp"
|
||||
#include "geojson/feature_collection.hpp"
|
||||
#include "geojson/geometry.hpp"
|
||||
#include "geojson/geometry_collection.hpp"
|
||||
#include "geojson/line_string.hpp"
|
||||
#include "geojson/multi_line_string.hpp"
|
||||
#include "geojson/multi_point.hpp"
|
||||
#include "geojson/multi_polygon.hpp"
|
||||
#include "geojson/point.hpp"
|
||||
#include "geojson/polygon.hpp"
|
||||
#include "geometry/lat_lng.hpp"
|
||||
#include "geometry/lat_lng_bounds.hpp"
|
||||
#include "geometry/lat_lng_quad.hpp"
|
||||
#include "geometry/projected_meters.hpp"
|
||||
#include "graphics/pointf.hpp"
|
||||
#include "graphics/rectf.hpp"
|
||||
#include "gson/json_array.hpp"
|
||||
#include "gson/json_element.hpp"
|
||||
#include "gson/json_object.hpp"
|
||||
#include "gson/json_primitive.hpp"
|
||||
#include "java_types.hpp"
|
||||
#include "map_renderer.hpp"
|
||||
#include "map_renderer_runnable.hpp"
|
||||
#include "mapbox.hpp"
|
||||
#include "native_map_view.hpp"
|
||||
#ifndef MBGL_MODULE_OFFLINE_DISABLE
|
||||
#include "offline/offline_manager.hpp"
|
||||
#include "offline/offline_region.hpp"
|
||||
#include "offline/offline_region_definition.hpp"
|
||||
#include "offline/offline_region_error.hpp"
|
||||
#include "offline/offline_region_status.hpp"
|
||||
#endif
|
||||
#include "style/transition_options.hpp"
|
||||
#include "style/layers/layer_manager.hpp"
|
||||
#include "style/sources/source.hpp"
|
||||
#include "style/light.hpp"
|
||||
#include "style/formatted.hpp"
|
||||
#include "style/formatted_section.hpp"
|
||||
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
|
||||
#include "snapshotter/map_snapshotter.hpp"
|
||||
#include "snapshotter/map_snapshot.hpp"
|
||||
#endif
|
||||
#include "i18n/collator_jni.hpp"
|
||||
#include "i18n/number_format_jni.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "text/local_glyph_rasterizer_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void RegisterNativeHTTPRequest(JNIEnv&);
|
||||
|
||||
void registerNatives(JavaVM *vm) {
|
||||
theJVM = vm;
|
||||
|
||||
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
|
||||
|
||||
// For the FileSource
|
||||
static mbgl::util::RunLoop mainRunLoop;
|
||||
FileSource::registerNative(env);
|
||||
|
||||
// Basic types
|
||||
java::registerNatives(env);
|
||||
java::util::registerNative(env);
|
||||
PointF::registerNative(env);
|
||||
RectF::registerNative(env);
|
||||
|
||||
// GeoJSON
|
||||
geojson::Feature::registerNative(env);
|
||||
geojson::FeatureCollection::registerNative(env);
|
||||
geojson::Geometry::registerNative(env);
|
||||
geojson::GeometryCollection::registerNative(env);
|
||||
geojson::LineString::registerNative(env);
|
||||
geojson::MultiLineString::registerNative(env);
|
||||
geojson::MultiPoint::registerNative(env);
|
||||
geojson::MultiPolygon::registerNative(env);
|
||||
geojson::Point::registerNative(env);
|
||||
geojson::Polygon::registerNative(env);
|
||||
|
||||
// Geometry
|
||||
LatLng::registerNative(env);
|
||||
LatLngBounds::registerNative(env);
|
||||
LatLngQuad::registerNative(env);
|
||||
ProjectedMeters::registerNative(env);
|
||||
|
||||
// GSon
|
||||
gson::JsonArray::registerNative(env);
|
||||
gson::JsonElement::registerNative(env);
|
||||
gson::JsonObject::registerNative(env);
|
||||
gson::JsonPrimitive::registerNative(env);
|
||||
|
||||
//Annotation
|
||||
Marker::registerNative(env);
|
||||
Polygon::registerNative(env);
|
||||
Polyline::registerNative(env);
|
||||
|
||||
// Map
|
||||
MapRenderer::registerNative(env);
|
||||
MapRendererRunnable::registerNative(env);
|
||||
NativeMapView::registerNative(env);
|
||||
|
||||
// Http
|
||||
RegisterNativeHTTPRequest(env);
|
||||
|
||||
// Bitmap
|
||||
Bitmap::registerNative(env);
|
||||
BitmapFactory::registerNative(env);
|
||||
|
||||
// Style
|
||||
TransitionOptions::registerNative(env);
|
||||
LayerManagerAndroid::get()->registerNative(env);
|
||||
Source::registerNative(env);
|
||||
Light::registerNative(env);
|
||||
Position::registerNative(env);
|
||||
Formatted::registerNative(env);
|
||||
FormattedSection::registerNative(env);
|
||||
|
||||
// Map
|
||||
CameraPosition::registerNative(env);
|
||||
Image::registerNative(env);
|
||||
|
||||
// Connectivity
|
||||
ConnectivityListener::registerNative(env);
|
||||
|
||||
// Offline
|
||||
#ifndef MBGL_MODULE_OFFLINE_DISABLE
|
||||
OfflineManager::registerNative(env);
|
||||
OfflineRegion::registerNative(env);
|
||||
OfflineRegionDefinition::registerNative(env);
|
||||
OfflineTilePyramidRegionDefinition::registerNative(env);
|
||||
OfflineGeometryRegionDefinition::registerNative(env);
|
||||
OfflineRegionError::registerNative(env);
|
||||
OfflineRegionStatus::registerNative(env);
|
||||
#endif
|
||||
|
||||
// Snapshotter
|
||||
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
|
||||
MapSnapshotter::registerNative(env);
|
||||
MapSnapshot::registerNative(env);
|
||||
#endif
|
||||
|
||||
// text
|
||||
LocalGlyphRasterizer::registerNative(env);
|
||||
Locale::registerNative(env);
|
||||
Collator::registerNative(env);
|
||||
StringUtils::registerNative(env);
|
||||
NumberFormat::registerNative(env);
|
||||
|
||||
// Logger
|
||||
Logger::registerNative(env);
|
||||
|
||||
// AssetManager
|
||||
Mapbox::registerNative(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
13
MapboxGLAndroidSDK/src/cpp/jni_native.hpp
Normal file
13
MapboxGLAndroidSDK/src/cpp/jni_native.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include "jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MBGL_EXPORT void registerNatives(JavaVM* vm);
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
34
MapboxGLAndroidSDK/src/cpp/logger.cpp
Normal file
34
MapboxGLAndroidSDK/src/cpp/logger.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "logger.hpp"
|
||||
#include "java_types.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void Logger::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Logger>::Singleton(env);
|
||||
}
|
||||
|
||||
void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) {
|
||||
static auto& _class = jni::Class<Logger>::Singleton(env);
|
||||
|
||||
auto tag = jni::Make<jni::String>(env, "Mbgl");
|
||||
auto message = jni::Make<jni::String>(env, msg);
|
||||
using Signature = void(jni::String, jni::String);
|
||||
|
||||
if (severity == EventSeverity::Debug) {
|
||||
auto static debug = _class.GetStaticMethod<Signature>(env, "d");
|
||||
_class.Call(env, debug, tag, message);
|
||||
} else if (severity == EventSeverity::Info) {
|
||||
auto static info = _class.GetStaticMethod<Signature>(env, "i");
|
||||
_class.Call(env, info, tag, message);
|
||||
} else if(severity == EventSeverity::Warning) {
|
||||
auto static warning = _class.GetStaticMethod<Signature>(env, "w");
|
||||
_class.Call(env, warning, tag, message);
|
||||
} else {
|
||||
auto static error = _class.GetStaticMethod<Signature>(env, "e");
|
||||
_class.Call(env, error, tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
21
MapboxGLAndroidSDK/src/cpp/logger.hpp
Normal file
21
MapboxGLAndroidSDK/src/cpp/logger.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/event.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
#include "bitmap.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
static constexpr auto Name() {
|
||||
return "com/mapbox/mapboxsdk/log/Logger";
|
||||
};
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
static void log(jni::JNIEnv&, EventSeverity severity, const std::string &msg);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
13
MapboxGLAndroidSDK/src/cpp/logging_android.cpp
Normal file
13
MapboxGLAndroidSDK/src/cpp/logging_android.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include "logger.hpp"
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
void Log::platformRecord(EventSeverity severity, const std::string &msg) {
|
||||
auto env{ android::AttachEnv() };
|
||||
android::Logger::log(*env, severity, msg);
|
||||
}
|
||||
|
||||
}
|
||||
9
MapboxGLAndroidSDK/src/cpp/main.cpp
Normal file
9
MapboxGLAndroidSDK/src/cpp/main.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "jni.hpp"
|
||||
#include "jni_native.hpp"
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) {
|
||||
assert(vm != nullptr);
|
||||
mbgl::android::registerNatives(vm);
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
69
MapboxGLAndroidSDK/src/cpp/map/camera_position.cpp
Normal file
69
MapboxGLAndroidSDK/src/cpp/map/camera_position.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "camera_position.hpp"
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options, float pixelRatio) {
|
||||
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::Object<LatLng>, double, double, double, jni::Array<jni::jdouble>>(env);
|
||||
|
||||
// wrap LatLng values coming from core
|
||||
auto center = options.center.value();
|
||||
center.wrap();
|
||||
|
||||
// convert bearing, measured in radians counterclockwise from true north.
|
||||
// Wrapped to [−π rad, π rad). Android binding from 0 to 360 degrees
|
||||
double bearing_degrees = options.bearing.value_or(0);
|
||||
while (bearing_degrees > 360) {
|
||||
bearing_degrees -= 360;
|
||||
}
|
||||
while (bearing_degrees < 0) {
|
||||
bearing_degrees += 360;
|
||||
}
|
||||
|
||||
// convert tilt, core ranges from [0 rad, 1,0472 rad], android ranges from 0 to 60
|
||||
double tilt_degrees = options.pitch.value_or(0);
|
||||
|
||||
std::vector<jdouble> paddingVect;
|
||||
auto insets = options.padding.value_or(EdgeInsets {0, 0, 0, 0});
|
||||
auto padding = jni::Array<jni::jdouble>::New(env, 4);
|
||||
paddingVect.push_back(insets.left() * pixelRatio);
|
||||
paddingVect.push_back(insets.top() * pixelRatio);
|
||||
paddingVect.push_back(insets.right() * pixelRatio);
|
||||
paddingVect.push_back(insets.bottom() * pixelRatio);
|
||||
padding.SetRegion<std::vector<jni::jdouble>>(env, 0, paddingVect);
|
||||
|
||||
return javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees, padding);
|
||||
}
|
||||
|
||||
mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, const jni::Object<CameraPosition>& position, float pixelRatio) {
|
||||
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
|
||||
static auto bearing = javaClass.GetField<jni::jdouble>(env, "bearing");
|
||||
static auto target = javaClass.GetField<jni::Object<LatLng>>(env, "target");
|
||||
static auto tilt = javaClass.GetField<jni::jdouble>(env, "tilt");
|
||||
static auto zoom = javaClass.GetField<jni::jdouble>(env, "zoom");
|
||||
static auto paddingField = javaClass.GetField<jni::Array<jni::jdouble>>(env, "padding");
|
||||
|
||||
auto padding = position.Get(env, paddingField);
|
||||
auto center = LatLng::getLatLng(env, position.Get(env, target));
|
||||
|
||||
return mbgl::CameraOptions{center,
|
||||
padding && padding.Length(env) == 4 ? EdgeInsets{padding.Get(env, 1) * pixelRatio,
|
||||
padding.Get(env, 0) * pixelRatio,
|
||||
padding.Get(env, 3) * pixelRatio,
|
||||
padding.Get(env, 2) * pixelRatio}
|
||||
: (EdgeInsets){},
|
||||
{},
|
||||
position.Get(env, zoom),
|
||||
position.Get(env, bearing),
|
||||
position.Get(env, tilt)};
|
||||
}
|
||||
|
||||
void CameraPosition::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<CameraPosition>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mb
|
||||
|
||||
23
MapboxGLAndroidSDK/src/cpp/map/camera_position.hpp
Normal file
23
MapboxGLAndroidSDK/src/cpp/map/camera_position.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class CameraPosition : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/camera/CameraPosition"; };
|
||||
|
||||
static jni::Local<jni::Object<CameraPosition>> New(jni::JNIEnv&, mbgl::CameraOptions, float pixelRatio);
|
||||
|
||||
static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, const jni::Object<CameraPosition>&, float pixelRatio);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
41
MapboxGLAndroidSDK/src/cpp/map/image.cpp
Normal file
41
MapboxGLAndroidSDK/src/cpp/map/image.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <mbgl/style/image.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
#include "image.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::style::Image Image::getImage(jni::JNIEnv& env, const jni::Object<Image>& image) {
|
||||
static auto& javaClass = jni::Class<Image>::Singleton(env);
|
||||
static auto widthField = javaClass.GetField<jni::jint>(env, "width");
|
||||
static auto heightField = javaClass.GetField<jni::jint>(env, "height");
|
||||
static auto pixelRatioField = javaClass.GetField<jni::jfloat>(env, "pixelRatio");
|
||||
static auto bufferField = javaClass.GetField<jni::Array<jbyte>>(env, "buffer");
|
||||
static auto nameField = javaClass.GetField<jni::String>(env, "name");
|
||||
static auto sdfField = javaClass.GetField<jni::jboolean>(env, "sdf");
|
||||
|
||||
auto height = image.Get(env, heightField);
|
||||
auto width = image.Get(env, widthField);
|
||||
auto pixelRatio = image.Get(env, pixelRatioField);
|
||||
auto pixels = image.Get(env, bufferField);
|
||||
auto name = jni::Make<std::string>(env, image.Get(env, nameField));
|
||||
auto sdf = (bool) image.Get(env, sdfField);
|
||||
|
||||
jni::NullCheck(env, pixels.get());
|
||||
std::size_t size = pixels.Length(env);
|
||||
|
||||
mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
|
||||
if (premultipliedImage.bytes() != uint32_t(size)) {
|
||||
throw mbgl::util::StyleImageException("Image pixel count mismatch");
|
||||
}
|
||||
|
||||
jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
|
||||
return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio, sdf};
|
||||
}
|
||||
|
||||
void Image::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Image>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mb
|
||||
21
MapboxGLAndroidSDK/src/cpp/map/image.hpp
Normal file
21
MapboxGLAndroidSDK/src/cpp/map/image.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include <mbgl/style/image.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Image : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/Image"; };
|
||||
|
||||
static mbgl::style::Image getImage(jni::JNIEnv&, const jni::Object<Image>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
247
MapboxGLAndroidSDK/src/cpp/map_renderer.cpp
Normal file
247
MapboxGLAndroidSDK/src/cpp/map_renderer.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
#include "map_renderer.hpp"
|
||||
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "android_renderer_backend.hpp"
|
||||
#include "map_renderer_runnable.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MapRenderer::MapRenderer(jni::JNIEnv& _env,
|
||||
const jni::Object<MapRenderer>& obj,
|
||||
jni::jfloat pixelRatio_,
|
||||
const jni::String& localIdeographFontFamily_)
|
||||
: javaPeer(_env, obj),
|
||||
pixelRatio(pixelRatio_),
|
||||
localIdeographFontFamily(localIdeographFontFamily_ ? jni::Make<std::string>(_env, localIdeographFontFamily_)
|
||||
: optional<std::string>{}),
|
||||
mailboxData(this) {}
|
||||
|
||||
MapRenderer::MailboxData::MailboxData(Scheduler* scheduler_) : scheduler(scheduler_) {
|
||||
assert(scheduler);
|
||||
}
|
||||
|
||||
std::shared_ptr<Mailbox> MapRenderer::MailboxData::getMailbox() const noexcept {
|
||||
if (!mailbox) {
|
||||
mailbox = std::make_shared<Mailbox>(*scheduler);
|
||||
}
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
MapRenderer::~MapRenderer() = default;
|
||||
|
||||
void MapRenderer::reset() {
|
||||
destroyed = true;
|
||||
|
||||
if (renderer) {
|
||||
// Make sure to destroy the renderer on the GL Thread
|
||||
auto self = ActorRef<MapRenderer>(*this, mailboxData.getMailbox());
|
||||
self.ask(&MapRenderer::resetRenderer).wait();
|
||||
}
|
||||
|
||||
// Lock to make sure there is no concurrent initialisation on the gl thread
|
||||
std::lock_guard<std::mutex> lock(initialisationMutex);
|
||||
rendererObserver.reset();
|
||||
}
|
||||
|
||||
ActorRef<Renderer> MapRenderer::actor() const {
|
||||
return *rendererRef;
|
||||
}
|
||||
|
||||
void MapRenderer::schedule(std::function<void()> scheduled) {
|
||||
// Create a runnable
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
auto runnable = std::make_unique<MapRendererRunnable>(*_env, std::move(scheduled));
|
||||
|
||||
// Obtain ownership of the peer (gets transferred to the MapRenderer on the JVM for later GC)
|
||||
auto peer = runnable->peer();
|
||||
|
||||
// Queue the event on the Java Peer
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env);
|
||||
static auto queueEvent = javaClass.GetMethod<void(
|
||||
jni::Object<MapRendererRunnable>)>(*_env, "queueEvent");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env, queueEvent, peer);
|
||||
}
|
||||
|
||||
// Release the c++ peer as it will be destroyed on GC of the Java Peer
|
||||
runnable.release();
|
||||
}
|
||||
|
||||
void MapRenderer::requestRender() {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env);
|
||||
static auto onInvalidate = javaClass.GetMethod<void()>(*_env, "requestRender");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env, onInvalidate);
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::update(std::shared_ptr<UpdateParameters> params) {
|
||||
// Lock on the parameters
|
||||
std::lock_guard<std::mutex> lock(updateMutex);
|
||||
updateParameters = std::move(params);
|
||||
}
|
||||
|
||||
void MapRenderer::setObserver(std::shared_ptr<RendererObserver> _rendererObserver) {
|
||||
// Lock as the initialization can come from the main thread or the GL thread first
|
||||
std::lock_guard<std::mutex> lock(initialisationMutex);
|
||||
|
||||
rendererObserver = std::move(_rendererObserver);
|
||||
|
||||
// Set the new observer on the Renderer implementation
|
||||
if (renderer) {
|
||||
renderer->setObserver(rendererObserver.get());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::requestSnapshot(SnapshotCallback callback) {
|
||||
auto self = ActorRef<MapRenderer>(*this, mailboxData.getMailbox());
|
||||
self.invoke(
|
||||
&MapRenderer::scheduleSnapshot,
|
||||
std::make_unique<SnapshotCallback>([&, callback=std::move(callback), runloop=util::RunLoop::Get()](PremultipliedImage image) {
|
||||
runloop->invoke([callback=std::move(callback), image=std::move(image), renderer=std::move(this)]() mutable {
|
||||
if (renderer && !renderer->destroyed) {
|
||||
callback(std::move(image));
|
||||
}
|
||||
});
|
||||
snapshotCallback.reset();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Called on OpenGL thread //
|
||||
|
||||
void MapRenderer::resetRenderer() {
|
||||
renderer.reset();
|
||||
}
|
||||
|
||||
void MapRenderer::scheduleSnapshot(std::unique_ptr<SnapshotCallback> callback) {
|
||||
snapshotCallback = std::move(callback);
|
||||
requestRender();
|
||||
}
|
||||
|
||||
void MapRenderer::render(JNIEnv&) {
|
||||
assert (renderer);
|
||||
|
||||
std::shared_ptr<UpdateParameters> params;
|
||||
{
|
||||
// Lock on the parameters
|
||||
std::unique_lock<std::mutex> lock(updateMutex);
|
||||
if (!updateParameters) return;
|
||||
|
||||
// Hold on to the update parameters during render
|
||||
params = updateParameters;
|
||||
}
|
||||
|
||||
// Activate the backend
|
||||
gfx::BackendScope backendGuard { *backend };
|
||||
|
||||
// Ensure that the "current" scheduler on the render thread is
|
||||
// this scheduler.
|
||||
Scheduler::SetCurrent(this);
|
||||
|
||||
if (framebufferSizeChanged) {
|
||||
backend->updateViewPort();
|
||||
framebufferSizeChanged = false;
|
||||
}
|
||||
|
||||
renderer->render(params);
|
||||
|
||||
// Deliver the snapshot if requested
|
||||
if (snapshotCallback) {
|
||||
snapshotCallback->operator()(backend->readFramebuffer());
|
||||
snapshotCallback.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::onSurfaceCreated(JNIEnv&) {
|
||||
// Lock as the initialization can come from the main thread or the GL thread first
|
||||
std::lock_guard<std::mutex> lock(initialisationMutex);
|
||||
|
||||
// The GL context is already active if get a new surface.
|
||||
gfx::BackendScope backendGuard { *backend, gfx::BackendScope::ScopeType::Implicit };
|
||||
|
||||
// The android system will have already destroyed the underlying
|
||||
// GL resources if this is not the first initialization and an
|
||||
// attempt to clean them up will fail
|
||||
if (backend) backend->markContextLost();
|
||||
if (renderer) renderer->markContextLost();
|
||||
|
||||
// Reset in opposite order
|
||||
renderer.reset();
|
||||
backend.reset();
|
||||
|
||||
// Create the new backend and renderer
|
||||
backend = std::make_unique<AndroidRendererBackend>();
|
||||
renderer = std::make_unique<Renderer>(*backend, pixelRatio, localIdeographFontFamily);
|
||||
rendererRef = std::make_unique<ActorRef<Renderer>>(*renderer, mailboxData.getMailbox());
|
||||
|
||||
// Set the observer on the new Renderer implementation
|
||||
if (rendererObserver) {
|
||||
renderer->setObserver(rendererObserver.get());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::onSurfaceChanged(JNIEnv& env, jint width, jint height) {
|
||||
if (!renderer) {
|
||||
// In case the surface has been destroyed (due to app back-grounding)
|
||||
onSurfaceCreated(env);
|
||||
}
|
||||
|
||||
backend->resizeFramebuffer(width, height);
|
||||
framebufferSizeChanged = true;
|
||||
requestRender();
|
||||
}
|
||||
|
||||
void MapRenderer::onRendererReset(JNIEnv&) {
|
||||
// Make sure to destroy the renderer on the GL Thread
|
||||
auto self = ActorRef<MapRenderer>(*this, mailboxData.getMailbox());
|
||||
self.ask(&MapRenderer::resetRenderer).wait();
|
||||
}
|
||||
|
||||
// needs to be called on GL thread
|
||||
void MapRenderer::onSurfaceDestroyed(JNIEnv&) {
|
||||
resetRenderer();
|
||||
}
|
||||
|
||||
// Static methods //
|
||||
|
||||
void MapRenderer::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<MapRenderer>(env, javaClass, "nativePtr",
|
||||
jni::MakePeer<MapRenderer, const jni::Object<MapRenderer>&, jni::jfloat, const jni::String&>,
|
||||
"nativeInitialize", "finalize",
|
||||
METHOD(&MapRenderer::render, "nativeRender"),
|
||||
METHOD(&MapRenderer::onRendererReset, "nativeReset"),
|
||||
METHOD(&MapRenderer::onSurfaceCreated,
|
||||
"nativeOnSurfaceCreated"),
|
||||
METHOD(&MapRenderer::onSurfaceChanged,
|
||||
"nativeOnSurfaceChanged"),
|
||||
METHOD(&MapRenderer::onSurfaceDestroyed,
|
||||
"nativeOnSurfaceDestroyed"));
|
||||
}
|
||||
|
||||
MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, const jni::Object<MapRenderer>& jObject) {
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
|
||||
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
|
||||
MapRenderer* mapRenderer = reinterpret_cast<MapRenderer*>(jObject.Get(env, field));
|
||||
assert(mapRenderer != nullptr);
|
||||
return *mapRenderer;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
138
MapboxGLAndroidSDK/src/cpp/map_renderer.hpp
Normal file
138
MapboxGLAndroidSDK/src/cpp/map_renderer.hpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/actor_ref.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <class>
|
||||
class ActorRef;
|
||||
class Mailbox;
|
||||
class Renderer;
|
||||
class RendererBackend;
|
||||
class RendererObserver;
|
||||
class ThreadPool;
|
||||
class UpdateParameters;
|
||||
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererBackend;
|
||||
|
||||
/**
|
||||
* The MapRenderer is a peer class that encapsulates the actions
|
||||
* performed on the GL Thread.
|
||||
*
|
||||
* The public methods are safe to call from the main thread, others are not.
|
||||
*/
|
||||
class MapRenderer : public Scheduler {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRenderer"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
static MapRenderer& getNativePeer(JNIEnv&, const jni::Object<MapRenderer>&);
|
||||
|
||||
MapRenderer(jni::JNIEnv& _env,
|
||||
const jni::Object<MapRenderer>&,
|
||||
jni::jfloat pixelRatio,
|
||||
const jni::String& localIdeographFontFamily);
|
||||
|
||||
~MapRenderer() override;
|
||||
|
||||
// Resets the renderer to clean up on the calling thread
|
||||
void reset();
|
||||
|
||||
// Takes the RendererObserver by shared_ptr so we
|
||||
// don't have to make the header public. Use
|
||||
// this instead of Renderer#setObserver directly
|
||||
void setObserver(std::shared_ptr<RendererObserver>);
|
||||
|
||||
// Sets the new update parameters to use on subsequent
|
||||
// renders. Be sure to trigger a render with
|
||||
// requestRender().
|
||||
void update(std::shared_ptr<UpdateParameters>);
|
||||
|
||||
// Gives a handle to the Renderer to enable actions on
|
||||
// any thread.
|
||||
ActorRef<Renderer> actor() const;
|
||||
|
||||
// From Scheduler. Schedules by using callbacks to the
|
||||
// JVM to process the mailbox on the right thread.
|
||||
void schedule(std::function<void()> scheduled) override;
|
||||
mapbox::base::WeakPtr<Scheduler> makeWeakPtr() override { return weakFactory.makeWeakPtr(); }
|
||||
|
||||
void requestRender();
|
||||
|
||||
// Snapshot - requires a RunLoop on the calling thread
|
||||
using SnapshotCallback = std::function<void (PremultipliedImage)>;
|
||||
void requestSnapshot(SnapshotCallback);
|
||||
|
||||
protected:
|
||||
// Called from the GL Thread //
|
||||
|
||||
void scheduleSnapshot(std::unique_ptr<SnapshotCallback>);
|
||||
|
||||
private:
|
||||
struct MailboxData {
|
||||
explicit MailboxData(Scheduler*);
|
||||
std::shared_ptr<Mailbox> getMailbox() const noexcept;
|
||||
|
||||
private:
|
||||
Scheduler* scheduler;
|
||||
mutable std::shared_ptr<Mailbox> mailbox;
|
||||
};
|
||||
// Called from the GL Thread //
|
||||
|
||||
// Resets the renderer
|
||||
void resetRenderer();
|
||||
|
||||
// Renders a frame.
|
||||
void render(JNIEnv&);
|
||||
|
||||
void onSurfaceCreated(JNIEnv&);
|
||||
|
||||
void onSurfaceChanged(JNIEnv&, jint width, jint height);
|
||||
|
||||
void onSurfaceDestroyed(JNIEnv&);
|
||||
|
||||
private:
|
||||
// Called on either Main or GL thread //
|
||||
void onRendererReset(JNIEnv&);
|
||||
|
||||
private:
|
||||
jni::WeakReference<jni::Object<MapRenderer>, jni::EnvAttachingDeleter> javaPeer;
|
||||
|
||||
float pixelRatio;
|
||||
optional<std::string> localIdeographFontFamily;
|
||||
|
||||
std::shared_ptr<ThreadPool> threadPool;
|
||||
const MailboxData mailboxData;
|
||||
|
||||
std::mutex initialisationMutex;
|
||||
std::shared_ptr<RendererObserver> rendererObserver;
|
||||
|
||||
std::unique_ptr<AndroidRendererBackend> backend;
|
||||
std::unique_ptr<Renderer> renderer;
|
||||
std::unique_ptr<ActorRef<Renderer>> rendererRef;
|
||||
|
||||
std::shared_ptr<UpdateParameters> updateParameters;
|
||||
std::mutex updateMutex;
|
||||
|
||||
bool framebufferSizeChanged = false;
|
||||
std::atomic<bool> destroyed {false};
|
||||
|
||||
std::unique_ptr<SnapshotCallback> snapshotCallback;
|
||||
mapbox::base::WeakPtrFactory<Scheduler> weakFactory{this};
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
49
MapboxGLAndroidSDK/src/cpp/map_renderer_runnable.cpp
Normal file
49
MapboxGLAndroidSDK/src/cpp/map_renderer_runnable.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "map_renderer_runnable.hpp"
|
||||
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::function<void()> function_)
|
||||
: function(std::move(function_)) {
|
||||
// Create the Java peer and hold on to a global reference
|
||||
// Not using a weak reference here as this might oerflow
|
||||
// the weak reference table on some devices
|
||||
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 5);
|
||||
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jlong>(env);
|
||||
auto instance = javaClass.New(env, constructor, reinterpret_cast<jlong>(this));
|
||||
javaPeer = jni::NewGlobal(env, instance);
|
||||
}
|
||||
|
||||
MapRendererRunnable::~MapRendererRunnable() = default;
|
||||
|
||||
void MapRendererRunnable::run(jni::JNIEnv&) {
|
||||
if (function) function();
|
||||
}
|
||||
|
||||
jni::Global<jni::Object<MapRendererRunnable>> MapRendererRunnable::peer() {
|
||||
return std::move(javaPeer);
|
||||
}
|
||||
|
||||
// Static methods //
|
||||
|
||||
void MapRendererRunnable::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<MapRendererRunnable>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
std::make_unique<MapRendererRunnable, JNIEnv&>,
|
||||
"nativeInitialize",
|
||||
"finalize",
|
||||
METHOD(&MapRendererRunnable::run, "run"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
47
MapboxGLAndroidSDK/src/cpp/map_renderer_runnable.hpp
Normal file
47
MapboxGLAndroidSDK/src/cpp/map_renderer_runnable.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/mailbox.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* The MapRendererRunnable is a peer class that encapsulates
|
||||
* a scheduled mailbox in a Java Runnable so it can be
|
||||
* scheduled on the map renderer thread.
|
||||
*
|
||||
*/
|
||||
class MapRendererRunnable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRendererRunnable"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
MapRendererRunnable(jni::JNIEnv&, std::function<void()>);
|
||||
|
||||
// Only for jni registration, unused
|
||||
MapRendererRunnable(jni::JNIEnv&) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
~MapRendererRunnable();
|
||||
|
||||
void run(jni::JNIEnv&);
|
||||
|
||||
// Transfers ownership of the Peer object to the caller
|
||||
jni::Global<jni::Object<MapRendererRunnable>> peer();
|
||||
|
||||
private:
|
||||
jni::Global<jni::Object<MapRendererRunnable>> javaPeer;
|
||||
std::function<void()> function;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
23
MapboxGLAndroidSDK/src/cpp/mapbox.cpp
Normal file
23
MapboxGLAndroidSDK/src/cpp/mapbox.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "mapbox.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<AssetManager>> Mapbox::getAssetManager(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<Mapbox>::Singleton(env);
|
||||
auto method = javaClass.GetStaticMethod<jni::Object<AssetManager>()>(env, "getAssetManager");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
jboolean Mapbox::hasInstance(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<Mapbox>::Singleton(env);
|
||||
auto method = javaClass.GetStaticMethod<jboolean()>(env, "hasInstance");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
void Mapbox::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Mapbox>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
19
MapboxGLAndroidSDK/src/cpp/mapbox.hpp
Normal file
19
MapboxGLAndroidSDK/src/cpp/mapbox.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Mapbox {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/Mapbox"; };
|
||||
static jboolean hasInstance(jni::JNIEnv&);
|
||||
static jni::Local<jni::Object<AssetManager>> getAssetManager(jni::JNIEnv&);
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
1263
MapboxGLAndroidSDK/src/cpp/native_map_view.cpp
Normal file
1263
MapboxGLAndroidSDK/src/cpp/native_map_view.cpp
Normal file
File diff suppressed because it is too large
Load Diff
279
MapboxGLAndroidSDK/src/cpp/native_map_view.hpp
Normal file
279
MapboxGLAndroidSDK/src/cpp/native_map_view.hpp
Normal file
@@ -0,0 +1,279 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/map/change.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
|
||||
#include "annotation/marker.hpp"
|
||||
#include "annotation/polygon.hpp"
|
||||
#include "annotation/polyline.hpp"
|
||||
#include "graphics/pointf.hpp"
|
||||
#include "graphics/rectf.hpp"
|
||||
#include "geojson/feature.hpp"
|
||||
#include "geojson/geometry.hpp"
|
||||
#include "geometry/lat_lng.hpp"
|
||||
#include "geometry/projected_meters.hpp"
|
||||
#include "style/layers/layer_manager.hpp"
|
||||
#include "style/sources/source.hpp"
|
||||
#include "geometry/lat_lng_bounds.hpp"
|
||||
#include "map/camera_position.hpp"
|
||||
#include "map/image.hpp"
|
||||
#include "style/light.hpp"
|
||||
#include "bitmap.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <jni.h>
|
||||
#include <android/native_window.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererFrontend;
|
||||
class FileSource;
|
||||
class MapRenderer;
|
||||
|
||||
class NativeMapView : public MapObserver {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/NativeMapView"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
NativeMapView(jni::JNIEnv&,
|
||||
const jni::Object<NativeMapView>&,
|
||||
const jni::Object<FileSource>&,
|
||||
const jni::Object<MapRenderer>&,
|
||||
jni::jfloat,
|
||||
jni::jboolean);
|
||||
|
||||
virtual ~NativeMapView();
|
||||
|
||||
// mbgl::RendererBackend (mbgl::MapObserver) //
|
||||
void onCameraWillChange(MapObserver::CameraChangeMode) override;
|
||||
void onCameraIsChanging() override;
|
||||
void onCameraDidChange(MapObserver::CameraChangeMode) override;
|
||||
void onWillStartLoadingMap() override;
|
||||
void onDidFinishLoadingMap() override;
|
||||
void onDidFailLoadingMap(MapLoadError, const std::string&) override;
|
||||
void onWillStartRenderingFrame() override;
|
||||
void onDidFinishRenderingFrame(MapObserver::RenderFrameStatus) override;
|
||||
void onWillStartRenderingMap() override;
|
||||
void onDidFinishRenderingMap(MapObserver::RenderMode) override;
|
||||
void onDidBecomeIdle() override;
|
||||
void onDidFinishLoadingStyle() override;
|
||||
void onSourceChanged(mbgl::style::Source&) override;
|
||||
void onStyleImageMissing(const std::string&) override;
|
||||
bool onCanRemoveUnusedStyleImage(const std::string&) override;
|
||||
|
||||
// JNI //
|
||||
|
||||
void resizeView(jni::JNIEnv&, int, int);
|
||||
|
||||
jni::Local<jni::String> getStyleUrl(jni::JNIEnv&);
|
||||
|
||||
void setStyleUrl(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::String> getStyleJson(jni::JNIEnv&);
|
||||
|
||||
void setStyleJson(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
void setLatLngBounds(jni::JNIEnv&, const jni::Object<mbgl::android::LatLngBounds>&);
|
||||
|
||||
void cancelTransitions(jni::JNIEnv&);
|
||||
|
||||
void setGestureInProgress(jni::JNIEnv&, jni::jboolean);
|
||||
|
||||
void moveBy(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
void jumpTo(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jdouble, jni::jdouble, const jni::Array<jni::jdouble>&);
|
||||
|
||||
void easeTo(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong, jni::jdouble, jni::jdouble, const jni::Array<jni::jdouble>&, jni::jboolean);
|
||||
|
||||
void flyTo(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong, jni::jdouble, jni::jdouble, const jni::Array<jni::jdouble>&);
|
||||
|
||||
jni::Local<jni::Object<LatLng>> getLatLng(JNIEnv&);
|
||||
|
||||
void setLatLng(jni::JNIEnv&, jni::jdouble, jni::jdouble, const jni::Array<jni::jdouble>&, jni::jlong);
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> getCameraForLatLngBounds(jni::JNIEnv&, const jni::Object<mbgl::android::LatLngBounds>&, double top, double left, double bottom, double right, double bearing, double tilt);
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> getCameraForGeometry(jni::JNIEnv&, const jni::Object<geojson::Geometry>&, double top, double left, double bottom, double right, double bearing, double tilt);
|
||||
|
||||
void setReachability(jni::JNIEnv&, jni::jboolean);
|
||||
|
||||
void resetPosition(jni::JNIEnv&);
|
||||
|
||||
jni::jdouble getPitch(jni::JNIEnv&);
|
||||
|
||||
void setPitch(jni::JNIEnv&, jni::jdouble, jni::jlong);
|
||||
|
||||
void setZoom(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
jni::jdouble getZoom(jni::JNIEnv&);
|
||||
|
||||
void resetZoom(jni::JNIEnv&);
|
||||
|
||||
void setMinZoom(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMinZoom(jni::JNIEnv&);
|
||||
|
||||
void setMaxZoom(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMaxZoom(jni::JNIEnv&);
|
||||
|
||||
void setMinPitch(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMinPitch(jni::JNIEnv&);
|
||||
|
||||
void setMaxPitch(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMaxPitch(jni::JNIEnv&);
|
||||
|
||||
void rotateBy(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
void setBearing(jni::JNIEnv&, jni::jdouble, jni::jlong);
|
||||
|
||||
void setBearingXY(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
jni::jdouble getBearing(jni::JNIEnv&);
|
||||
|
||||
void resetNorth(jni::JNIEnv&);
|
||||
|
||||
void setVisibleCoordinateBounds(JNIEnv&, const jni::Array<jni::Object<LatLng>>&, const jni::Object<RectF>&, jni::jdouble, jni::jlong);
|
||||
|
||||
void getVisibleCoordinateBounds(JNIEnv& env, jni::Array<jdouble>& output);
|
||||
|
||||
void scheduleSnapshot(jni::JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> getCameraPosition(jni::JNIEnv&);
|
||||
|
||||
void updateMarker(jni::JNIEnv&, jni::jlong, jni::jdouble, jni::jdouble, const jni::String&);
|
||||
|
||||
jni::Local<jni::Array<jni::jlong>> addMarkers(jni::JNIEnv&, const jni::Array<jni::Object<Marker>>&);
|
||||
|
||||
void onLowMemory(JNIEnv& env);
|
||||
|
||||
void setDebug(JNIEnv&, jni::jboolean);
|
||||
|
||||
jni::jboolean getDebug(JNIEnv&);
|
||||
|
||||
jni::jboolean isFullyLoaded(JNIEnv&);
|
||||
|
||||
jni::jdouble getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble, jni::jdouble);
|
||||
|
||||
jni::Local<jni::Object<ProjectedMeters>> projectedMetersForLatLng(JNIEnv&, jni::jdouble, jni::jdouble);
|
||||
|
||||
jni::Local<jni::Object<PointF>> pixelForLatLng(JNIEnv&, jdouble, jdouble);
|
||||
|
||||
void pixelsForLatLngs(JNIEnv&, const jni::Array<jdouble>&, jni::Array<jdouble>&, jfloat);
|
||||
|
||||
jni::Local<jni::Object<LatLng>> latLngForProjectedMeters(JNIEnv&, jdouble, jdouble);
|
||||
|
||||
jni::Local<jni::Object<LatLng>> latLngForPixel(JNIEnv&, jfloat, jfloat);
|
||||
|
||||
void latLngsForPixels(JNIEnv&, const jni::Array<jdouble>&, jni::Array<jdouble>&, jfloat);
|
||||
|
||||
jni::Local<jni::Array<jlong>> addPolylines(JNIEnv&, const jni::Array<jni::Object<Polyline>>&);
|
||||
|
||||
jni::Local<jni::Array<jlong>> addPolygons(JNIEnv&, const jni::Array<jni::Object<Polygon>>&);
|
||||
|
||||
void updatePolyline(JNIEnv&, jlong, const jni::Object<Polyline>&);
|
||||
|
||||
void updatePolygon(JNIEnv&, jlong, const jni::Object<Polygon>&);
|
||||
|
||||
void removeAnnotations(JNIEnv&, const jni::Array<jlong>&);
|
||||
|
||||
void addAnnotationIcon(JNIEnv&, const jni::String&, jint, jint, jfloat, const jni::Array<jbyte>&);
|
||||
|
||||
void removeAnnotationIcon(JNIEnv&, const jni::String&);
|
||||
|
||||
jni::jdouble getTopOffsetPixelsForAnnotationSymbol(JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::Object<TransitionOptions>> getTransitionOptions(JNIEnv&);
|
||||
|
||||
void setTransitionOptions(JNIEnv&, const jni::Object<TransitionOptions>&);
|
||||
|
||||
jni::Local<jni::Array<jlong>> queryPointAnnotations(JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
jni::Local<jni::Array<jlong>> queryShapeAnnotations(JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<geojson::Feature>>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat,
|
||||
const jni::Array<jni::String>&,
|
||||
const jni::Array<jni::Object<>>& jfilter);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<geojson::Feature>>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat,
|
||||
jni::jfloat, const jni::Array<jni::String>&,
|
||||
const jni::Array<jni::Object<>>& jfilter);
|
||||
|
||||
jni::Local<jni::Object<Light>> getLight(JNIEnv&);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Layer>>> getLayers(JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<Layer>> getLayer(JNIEnv&, const jni::String&);
|
||||
|
||||
void addLayer(JNIEnv&, jlong, const jni::String&);
|
||||
|
||||
void addLayerAbove(JNIEnv&, jlong, const jni::String&);
|
||||
|
||||
void addLayerAt(JNIEnv&, jni::jlong, jni::jint);
|
||||
|
||||
jni::jboolean removeLayerAt(JNIEnv&, jni::jint);
|
||||
|
||||
jni::jboolean removeLayer(JNIEnv&, jlong);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Source>>> getSources(JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<Source>> getSource(JNIEnv&, const jni::String&);
|
||||
|
||||
void addSource(JNIEnv&, const jni::Object<Source>&, jlong nativePtr);
|
||||
|
||||
jni::jboolean removeSource(JNIEnv&, const jni::Object<Source>&, jlong nativePtr);
|
||||
|
||||
void addImage(JNIEnv&, const jni::String&, const jni::Object<Bitmap>& bitmap, jni::jfloat, jni::jboolean);
|
||||
|
||||
void addImages(JNIEnv&, const jni::Array<jni::Object<mbgl::android::Image>>&);
|
||||
|
||||
void removeImage(JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::Object<Bitmap>> getImage(JNIEnv&, const jni::String&);
|
||||
|
||||
void setPrefetchTiles(JNIEnv&, jni::jboolean);
|
||||
|
||||
jni::jboolean getPrefetchTiles(JNIEnv&);
|
||||
|
||||
void setPrefetchZoomDelta(JNIEnv&, jni::jint);
|
||||
|
||||
jni::jint getPrefetchZoomDelta(JNIEnv&);
|
||||
|
||||
mbgl::Map& getMap();
|
||||
|
||||
void triggerRepaint(JNIEnv&);
|
||||
|
||||
private:
|
||||
std::unique_ptr<AndroidRendererFrontend> rendererFrontend;
|
||||
|
||||
JavaVM *vm = nullptr;
|
||||
jni::WeakReference<jni::Object<NativeMapView>> javaPeer;
|
||||
|
||||
MapRenderer& mapRenderer;
|
||||
|
||||
std::string styleUrl;
|
||||
|
||||
float pixelRatio;
|
||||
|
||||
// Minimum texture size according to OpenGL ES 2.0 specification.
|
||||
int width = 64;
|
||||
int height = 64;
|
||||
|
||||
// Ensure these are initialised last
|
||||
std::unique_ptr<mbgl::Map> map;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
335
MapboxGLAndroidSDK/src/cpp/offline/offline_manager.cpp
Normal file
335
MapboxGLAndroidSDK/src/cpp/offline/offline_manager.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
#include "offline_manager.hpp"
|
||||
|
||||
#include <mbgl/storage/file_source_manager.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
// Reattach, the callback comes from a different thread
|
||||
void handleException(std::exception_ptr exception,
|
||||
const jni::Object<OfflineManager::FileSourceCallback>& callback,
|
||||
android::UniqueEnv env = android::AttachEnv()) {
|
||||
if (exception) {
|
||||
OfflineManager::FileSourceCallback::onError(
|
||||
*env, callback, jni::Make<jni::String>(*env, mbgl::util::toString(exception)));
|
||||
} else {
|
||||
OfflineManager::FileSourceCallback::onSuccess(*env, callback);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// OfflineManager //
|
||||
OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource)
|
||||
: fileSource(std::static_pointer_cast<mbgl::DatabaseFileSource>(
|
||||
std::shared_ptr<mbgl::FileSource>(mbgl::FileSourceManager::get()->getFileSource(
|
||||
mbgl::FileSourceType::Database, FileSource::getSharedResourceOptions(env, jFileSource))))) {
|
||||
if (!fileSource) {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
OfflineManager::~OfflineManager() {}
|
||||
|
||||
void OfflineManager::setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit) {
|
||||
fileSource->setOfflineMapboxTileCountLimit(limit);
|
||||
}
|
||||
|
||||
void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, const jni::Object<FileSource>& jFileSource_, const jni::Object<ListOfflineRegionsCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
|
||||
|
||||
fileSource->listOfflineRegions([
|
||||
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
|
||||
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))
|
||||
](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable {
|
||||
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
if (regions) {
|
||||
OfflineManager::ListOfflineRegionsCallback::onList(
|
||||
*env, *jFileSource, *callback, *regions);
|
||||
} else {
|
||||
OfflineManager::ListOfflineRegionsCallback::onError(
|
||||
*env, *callback, regions.error());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OfflineManager::createOfflineRegion(jni::JNIEnv& env_,
|
||||
const jni::Object<FileSource>& jFileSource_,
|
||||
const jni::Object<OfflineRegionDefinition>& definition_,
|
||||
const jni::Array<jni::jbyte>& metadata_,
|
||||
const jni::Object<CreateOfflineRegionCallback>& callback_) {
|
||||
// Convert
|
||||
auto definition = OfflineRegionDefinition::getDefinition(env_, definition_);
|
||||
|
||||
mbgl::OfflineRegionMetadata metadata;
|
||||
if (metadata_) {
|
||||
metadata = OfflineRegion::metadata(env_, metadata_);
|
||||
}
|
||||
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
|
||||
|
||||
// Create region
|
||||
fileSource->createOfflineRegion(definition, metadata, [
|
||||
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
|
||||
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))
|
||||
](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> region) mutable {
|
||||
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
if (region) {
|
||||
OfflineManager::CreateOfflineRegionCallback::onCreate(
|
||||
*env, *jFileSource, *callback, *region
|
||||
);
|
||||
} else {
|
||||
OfflineManager::CreateOfflineRegionCallback::onError(
|
||||
*env, *callback, region.error());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OfflineManager::mergeOfflineRegions(jni::JNIEnv& env_, const jni::Object<FileSource>& jFileSource_,
|
||||
const jni::String& jString_,
|
||||
const jni::Object<MergeOfflineRegionsCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
|
||||
|
||||
auto path = jni::Make<std::string>(env_, jString_);
|
||||
fileSource->mergeOfflineRegions(path, [
|
||||
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
|
||||
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))
|
||||
](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable {
|
||||
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
if (regions) {
|
||||
OfflineManager::MergeOfflineRegionsCallback::onMerge(
|
||||
*env, *jFileSource, *callback, *regions);
|
||||
} else {
|
||||
OfflineManager::MergeOfflineRegionsCallback::onError(
|
||||
*env, *callback, regions.error());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OfflineManager::resetDatabase(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->resetDatabase(
|
||||
[
|
||||
// Keep a shared ptr to a global reference of the callback so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
|
||||
std::exception_ptr exception) mutable { handleException(exception, *callback); });
|
||||
}
|
||||
|
||||
void OfflineManager::packDatabase(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->packDatabase(
|
||||
[
|
||||
// Keep a shared ptr to a global reference of the callback so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
|
||||
std::exception_ptr exception) mutable { handleException(exception, *callback); });
|
||||
}
|
||||
|
||||
void OfflineManager::invalidateAmbientCache(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->invalidateAmbientCache(
|
||||
[
|
||||
// Keep a shared ptr to a global reference of the callback so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
|
||||
std::exception_ptr exception) mutable { handleException(exception, *callback); });
|
||||
}
|
||||
|
||||
void OfflineManager::clearAmbientCache(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->clearAmbientCache(
|
||||
[
|
||||
// Keep a shared ptr to a global reference of the callback so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
|
||||
std::exception_ptr exception) mutable { handleException(exception, *callback); });
|
||||
}
|
||||
|
||||
void OfflineManager::setMaximumAmbientCacheSize(jni::JNIEnv& env_, const jni::jlong size_, const jni::Object<FileSourceCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->setMaximumAmbientCacheSize(
|
||||
size_,
|
||||
[
|
||||
// Keep a shared ptr to a global reference of the callback so they are not GC'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
|
||||
std::exception_ptr exception) mutable { handleException(exception, *callback); });
|
||||
}
|
||||
|
||||
void OfflineManager::runPackDatabaseAutomatically(jni::JNIEnv&, jboolean autopack) {
|
||||
fileSource->runPackDatabaseAutomatically(autopack);
|
||||
}
|
||||
|
||||
// FileSource::FileSourceCallback //
|
||||
|
||||
void OfflineManager::FileSourceCallback::onSuccess(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineManager::FileSourceCallback>& callback) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::FileSourceCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void ()>(env, "onSuccess");
|
||||
callback.Call(env, method);
|
||||
}
|
||||
|
||||
void OfflineManager::FileSourceCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineManager::FileSourceCallback>& callback,
|
||||
const jni::String& message) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::FileSourceCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
callback.Call(env, method, message);
|
||||
}
|
||||
|
||||
void OfflineManager::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<ListOfflineRegionsCallback>::Singleton(env);
|
||||
jni::Class<CreateOfflineRegionCallback>::Singleton(env);
|
||||
jni::Class<MergeOfflineRegionsCallback>::Singleton(env);
|
||||
jni::Class<FileSourceCallback>::Singleton(env);
|
||||
|
||||
static auto& javaClass = jni::Class<OfflineManager>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<OfflineManager>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
jni::MakePeer<OfflineManager, const jni::Object<FileSource>&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&OfflineManager::setOfflineMapboxTileCountLimit, "setOfflineMapboxTileCountLimit"),
|
||||
METHOD(&OfflineManager::listOfflineRegions, "listOfflineRegions"),
|
||||
METHOD(&OfflineManager::createOfflineRegion, "createOfflineRegion"),
|
||||
METHOD(&OfflineManager::mergeOfflineRegions, "mergeOfflineRegions"),
|
||||
METHOD(&OfflineManager::resetDatabase, "nativeResetDatabase"),
|
||||
METHOD(&OfflineManager::packDatabase, "nativePackDatabase"),
|
||||
METHOD(&OfflineManager::invalidateAmbientCache, "nativeInvalidateAmbientCache"),
|
||||
METHOD(&OfflineManager::clearAmbientCache, "nativeClearAmbientCache"),
|
||||
METHOD(&OfflineManager::setMaximumAmbientCacheSize, "nativeSetMaximumAmbientCacheSize"),
|
||||
METHOD(&OfflineManager::runPackDatabaseAutomatically, "runPackDatabaseAutomatically"),
|
||||
METHOD(&OfflineManager::putResourceWithUrl, "putResourceWithUrl"));
|
||||
}
|
||||
|
||||
// OfflineManager::ListOfflineRegionsCallback //
|
||||
|
||||
void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineManager::ListOfflineRegionsCallback>& callback,
|
||||
std::exception_ptr error) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
|
||||
}
|
||||
|
||||
void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource>& jFileSource,
|
||||
const jni::Object<OfflineManager::ListOfflineRegionsCallback>& callback,
|
||||
mbgl::OfflineRegions& regions) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::Array<jni::Object<OfflineRegion>>)>(env, "onList");
|
||||
|
||||
std::size_t index = 0;
|
||||
auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions.size());
|
||||
for (auto& region : regions) {
|
||||
jregions.Set(env, index, OfflineRegion::New(env, jFileSource, std::move(region)));
|
||||
index++;
|
||||
}
|
||||
|
||||
callback.Call(env, method, jregions);
|
||||
}
|
||||
|
||||
// OfflineManager::CreateOfflineRegionCallback //
|
||||
|
||||
void OfflineManager::CreateOfflineRegionCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback,
|
||||
std::exception_ptr error) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
|
||||
}
|
||||
|
||||
void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource>& jFileSource,
|
||||
const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback,
|
||||
mbgl::OfflineRegion& region) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegion>)>(env, "onCreate");
|
||||
|
||||
callback.Call(env, method, OfflineRegion::New(env, jFileSource, std::move(region)));
|
||||
}
|
||||
|
||||
// OfflineManager::MergeOfflineRegionsCallback //
|
||||
|
||||
void OfflineManager::MergeOfflineRegionsCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineManager::MergeOfflineRegionsCallback>& callback,
|
||||
std::exception_ptr error) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::MergeOfflineRegionsCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
|
||||
}
|
||||
|
||||
void OfflineManager::MergeOfflineRegionsCallback::onMerge(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource>& jFileSource,
|
||||
const jni::Object<MergeOfflineRegionsCallback>& callback,
|
||||
mbgl::OfflineRegions& regions) {
|
||||
static auto& javaClass = jni::Class<OfflineManager::MergeOfflineRegionsCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::Array<jni::Object<OfflineRegion>>)>(env, "onMerge");
|
||||
|
||||
std::size_t index = 0;
|
||||
auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions.size());
|
||||
for (auto& region : regions) {
|
||||
jregions.Set(env, index, OfflineRegion::New(env, jFileSource, std::move(region)));
|
||||
index++;
|
||||
}
|
||||
|
||||
callback.Call(env, method, jregions);
|
||||
}
|
||||
|
||||
void OfflineManager::putResourceWithUrl(jni::JNIEnv& env,
|
||||
const jni::String& url_,
|
||||
const jni::Array<jni::jbyte>& arr,
|
||||
jlong modified,
|
||||
jlong expires,
|
||||
const jni::String& eTag_,
|
||||
jboolean mustRevalidate) {
|
||||
auto url = jni::Make<std::string>(env, url_);
|
||||
auto data = std::make_shared<std::string>(arr.Length(env), char());
|
||||
jni::GetArrayRegion(env, *arr, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
|
||||
mbgl::Resource resource(mbgl::Resource::Kind::Unknown, url);
|
||||
mbgl::Response response;
|
||||
response.data = data;
|
||||
response.mustRevalidate = mustRevalidate;
|
||||
if (eTag_) {
|
||||
response.etag = jni::Make<std::string>(env, eTag_);
|
||||
}
|
||||
if (modified > 0) {
|
||||
response.modified = Timestamp(mbgl::Seconds(modified));
|
||||
}
|
||||
if (expires > 0) {
|
||||
response.expires = Timestamp(mbgl::Seconds(expires));
|
||||
}
|
||||
|
||||
fileSource->put(resource, response);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
111
MapboxGLAndroidSDK/src/cpp/offline/offline_manager.hpp
Normal file
111
MapboxGLAndroidSDK/src/cpp/offline/offline_manager.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/offline.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "../file_source.hpp"
|
||||
#include "offline_region.hpp"
|
||||
#include "offline_region_definition.hpp"
|
||||
#include "../java_types.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace android {
|
||||
|
||||
class OfflineManager {
|
||||
public:
|
||||
|
||||
class ListOfflineRegionsCallback {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$ListOfflineRegionsCallback";}
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineManager::ListOfflineRegionsCallback>&, std::exception_ptr);
|
||||
|
||||
static void onList(jni::JNIEnv&,
|
||||
const jni::Object<FileSource>&,
|
||||
const jni::Object<OfflineManager::ListOfflineRegionsCallback>&,
|
||||
mbgl::OfflineRegions&);
|
||||
};
|
||||
|
||||
class CreateOfflineRegionCallback {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback"; }
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineManager::CreateOfflineRegionCallback>&, std::exception_ptr);
|
||||
|
||||
static void onCreate(jni::JNIEnv&,
|
||||
const jni::Object<FileSource>&,
|
||||
const jni::Object<OfflineManager::CreateOfflineRegionCallback>&,
|
||||
mbgl::OfflineRegion&);
|
||||
};
|
||||
|
||||
class MergeOfflineRegionsCallback {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$MergeOfflineRegionsCallback";}
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineManager::MergeOfflineRegionsCallback>&, std::exception_ptr);
|
||||
|
||||
static void onMerge(jni::JNIEnv&,
|
||||
const jni::Object<FileSource>&,
|
||||
const jni::Object<MergeOfflineRegionsCallback>&,
|
||||
mbgl::OfflineRegions&);
|
||||
};
|
||||
|
||||
struct FileSourceCallback {
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$FileSourceCallback";}
|
||||
|
||||
static void onSuccess(jni::JNIEnv&, const jni::Object<OfflineManager::FileSourceCallback>&);
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineManager::FileSourceCallback>&, const jni::String&);
|
||||
};
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
OfflineManager(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
~OfflineManager();
|
||||
|
||||
void setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit);
|
||||
|
||||
void listOfflineRegions(jni::JNIEnv&, const jni::Object<FileSource>&, const jni::Object<ListOfflineRegionsCallback>& callback);
|
||||
|
||||
void createOfflineRegion(jni::JNIEnv&,
|
||||
const jni::Object<FileSource>& jFileSource_,
|
||||
const jni::Object<OfflineRegionDefinition>& definition,
|
||||
const jni::Array<jni::jbyte>& metadata,
|
||||
const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback);
|
||||
|
||||
void mergeOfflineRegions(jni::JNIEnv&,
|
||||
const jni::Object<FileSource>&,
|
||||
const jni::String&,
|
||||
const jni::Object<MergeOfflineRegionsCallback>&);
|
||||
|
||||
void putResourceWithUrl(jni::JNIEnv&,
|
||||
const jni::String& url,
|
||||
const jni::Array<jni::jbyte>& data,
|
||||
jlong modified,
|
||||
jlong expires,
|
||||
const jni::String& eTag,
|
||||
jboolean mustRevalidate);
|
||||
|
||||
void resetDatabase(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
|
||||
|
||||
void packDatabase(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
|
||||
|
||||
void invalidateAmbientCache(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
|
||||
|
||||
void clearAmbientCache(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
|
||||
|
||||
void setMaximumAmbientCacheSize(jni::JNIEnv&, const jni::jlong size, const jni::Object<FileSourceCallback>& callback_);
|
||||
|
||||
void runPackDatabaseAutomatically(jni::JNIEnv&, jboolean autopack);
|
||||
|
||||
private:
|
||||
std::shared_ptr<mbgl::DatabaseFileSource> fileSource;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
314
MapboxGLAndroidSDK/src/cpp/offline/offline_region.cpp
Normal file
314
MapboxGLAndroidSDK/src/cpp/offline/offline_region.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
#include "offline_region.hpp"
|
||||
|
||||
#include <mbgl/storage/file_source_manager.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
#include "offline_region_definition.hpp"
|
||||
#include "offline_region_error.hpp"
|
||||
#include "offline_region_status.hpp"
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// OfflineRegion //
|
||||
|
||||
OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const jni::Object<FileSource>& jFileSource)
|
||||
: region(reinterpret_cast<mbgl::OfflineRegion*>(offlineRegionPtr)),
|
||||
fileSource(std::static_pointer_cast<mbgl::DatabaseFileSource>(
|
||||
std::shared_ptr<mbgl::FileSource>(mbgl::FileSourceManager::get()->getFileSource(
|
||||
mbgl::FileSourceType::Database, FileSource::getSharedResourceOptions(env, jFileSource))))) {
|
||||
if (!fileSource) {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
OfflineRegion::~OfflineRegion() {}
|
||||
|
||||
void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, const jni::Object<OfflineRegion::OfflineRegionObserver>& callback) {
|
||||
|
||||
// Define the observer
|
||||
class Observer : public mbgl::OfflineRegionObserver {
|
||||
public:
|
||||
Observer(jni::Global<jni::Object<OfflineRegion::OfflineRegionObserver>, jni::EnvAttachingDeleter> callback_)
|
||||
: callback(std::move(callback_)) {
|
||||
}
|
||||
|
||||
void statusChanged(mbgl::OfflineRegionStatus status) override {
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env);
|
||||
static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(*env, "onStatusChanged");
|
||||
|
||||
callback.Call(*env, method, OfflineRegionStatus::New(*env, status));
|
||||
}
|
||||
|
||||
void responseError(mbgl::Response::Error error) override {
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env);
|
||||
static auto method = javaClass.GetMethod<void (jni::Object<mbgl::android::OfflineRegionError>)>(*env, "onError");
|
||||
|
||||
callback.Call(*env, method, OfflineRegionError::New(*env, error));
|
||||
}
|
||||
|
||||
void mapboxTileCountLimitExceeded(uint64_t limit) override {
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env);
|
||||
static auto method = javaClass.GetMethod<void (jni::jlong)>(*env, "mapboxTileCountLimitExceeded");
|
||||
|
||||
callback.Call(*env, method, jlong(limit));
|
||||
}
|
||||
|
||||
jni::Global<jni::Object<OfflineRegion::OfflineRegionObserver>, jni::EnvAttachingDeleter> callback;
|
||||
};
|
||||
|
||||
// Set the observer
|
||||
fileSource->setOfflineRegionObserver(*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback)));
|
||||
}
|
||||
|
||||
void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState) {
|
||||
// State
|
||||
mbgl::OfflineRegionDownloadState state;
|
||||
switch (jState) {
|
||||
case 0:
|
||||
state = mbgl::OfflineRegionDownloadState::Inactive;
|
||||
break;
|
||||
case 1:
|
||||
state = mbgl::OfflineRegionDownloadState::Active;
|
||||
break;
|
||||
default:
|
||||
mbgl::Log::Error(mbgl::Event::JNI, "State can only be 0 (inactive) or 1 (active).");
|
||||
return;
|
||||
}
|
||||
|
||||
fileSource->setOfflineRegionDownloadState(*region, state);
|
||||
}
|
||||
|
||||
void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object<OfflineRegionStatusCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->getOfflineRegionStatus(*region, [
|
||||
//Ensure the object is not gc'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))
|
||||
](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable {
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
if (status) {
|
||||
OfflineRegionStatusCallback::onStatus(*env, *callback, std::move(*status));
|
||||
} else {
|
||||
OfflineRegionStatusCallback::onError(*env, *callback, status.error());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, const jni::Object<OfflineRegionDeleteCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->deleteOfflineRegion(*region,
|
||||
[
|
||||
// Ensure the object is not gc'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(
|
||||
std::move(globalCallback))](std::exception_ptr error) mutable {
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
if (error) {
|
||||
OfflineRegionDeleteCallback::onError(*env, *callback, error);
|
||||
} else {
|
||||
OfflineRegionDeleteCallback::onDelete(*env, *callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OfflineRegion::invalidateOfflineRegion(jni::JNIEnv& env_,
|
||||
const jni::Object<OfflineRegionInvalidateCallback>& callback_) {
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->invalidateOfflineRegion(*region,
|
||||
[
|
||||
// Ensure the object is not gc'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(
|
||||
std::move(globalCallback))](std::exception_ptr error) mutable {
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
if (error) {
|
||||
OfflineRegionInvalidateCallback::onError(*env, *callback, error);
|
||||
} else {
|
||||
OfflineRegionInvalidateCallback::onInvalidate(*env, *callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, const jni::Array<jni::jbyte>& jMetadata, const jni::Object<OfflineRegionUpdateMetadataCallback>& callback_) {
|
||||
auto metadata = OfflineRegion::metadata(env_, jMetadata);
|
||||
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
|
||||
|
||||
fileSource->updateOfflineMetadata(region->getID(), metadata, [
|
||||
//Ensure the object is not gc'd in the meanwhile
|
||||
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))
|
||||
](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable {
|
||||
// Reattach, the callback comes from a different thread
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
if (data) {
|
||||
OfflineRegionUpdateMetadataCallback::onUpdate(*env, *callback, std::move(*data));
|
||||
} else {
|
||||
OfflineRegionUpdateMetadataCallback::onError(*env, *callback, data.error());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<OfflineRegion>> OfflineRegion::New(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource>& jFileSource,
|
||||
mbgl::OfflineRegion region) {
|
||||
// Definition
|
||||
auto definition = region.getDefinition().match(
|
||||
[&](const mbgl::OfflineTilePyramidRegionDefinition def) {
|
||||
return OfflineTilePyramidRegionDefinition::New(env, def);
|
||||
},
|
||||
[&](const mbgl::OfflineGeometryRegionDefinition def) {
|
||||
return OfflineGeometryRegionDefinition::New(env, def);
|
||||
});
|
||||
|
||||
// Create region java object
|
||||
static auto& javaClass = jni::Class<OfflineRegion>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::jlong, jni::Object<FileSource>, jni::jlong, jni::Object<OfflineRegionDefinition>, jni::Array<jni::jbyte>>(env);
|
||||
|
||||
return javaClass.New(env, constructor,
|
||||
reinterpret_cast<jni::jlong>(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap
|
||||
jFileSource,
|
||||
jni::jlong(region.getID()),
|
||||
definition,
|
||||
OfflineRegion::metadata(env, region.getMetadata()));
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::jbyte>> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) {
|
||||
std::vector<jni::jbyte> convertedMetadata(metadata_.begin(), metadata_.end());
|
||||
std::size_t length = static_cast<std::size_t>(convertedMetadata.size());
|
||||
auto metadata = jni::Array<jni::jbyte>::New(env, length);
|
||||
metadata.SetRegion<std::vector<jni::jbyte>>(env, 0, convertedMetadata);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, const jni::Array<jni::jbyte>& metadata_) {
|
||||
std::size_t length = metadata_.Length(env);
|
||||
auto metadata_tmp = std::vector<jni::jbyte>();
|
||||
metadata_tmp.resize(length);
|
||||
metadata_.GetRegion<std::vector<jni::jbyte>>(env, 0, metadata_tmp);
|
||||
auto metadata = std::vector<uint8_t>(metadata_tmp.begin(), metadata_tmp.end());
|
||||
return metadata;
|
||||
}
|
||||
|
||||
void OfflineRegion::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<OfflineRegionObserver>::Singleton(env);
|
||||
jni::Class<OfflineRegionStatusCallback>::Singleton(env);
|
||||
jni::Class<OfflineRegionDeleteCallback>::Singleton(env);
|
||||
jni::Class<OfflineRegionUpdateMetadataCallback>::Singleton(env);
|
||||
jni::Class<OfflineRegionInvalidateCallback>::Singleton(env);
|
||||
|
||||
static auto& javaClass = jni::Class<OfflineRegion>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<OfflineRegion>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
jni::MakePeer<OfflineRegion, jni::jlong, const jni::Object<FileSource>&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&OfflineRegion::setOfflineRegionObserver, "setOfflineRegionObserver"),
|
||||
METHOD(&OfflineRegion::setOfflineRegionDownloadState, "setOfflineRegionDownloadState"),
|
||||
METHOD(&OfflineRegion::getOfflineRegionStatus, "getOfflineRegionStatus"),
|
||||
METHOD(&OfflineRegion::deleteOfflineRegion, "deleteOfflineRegion"),
|
||||
METHOD(&OfflineRegion::invalidateOfflineRegion, "invalidateOfflineRegion"),
|
||||
METHOD(&OfflineRegion::updateOfflineRegionMetadata, "updateOfflineRegionMetadata"));
|
||||
}
|
||||
|
||||
// OfflineRegionObserver //
|
||||
|
||||
// OfflineRegionStatusCallback //
|
||||
|
||||
void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineRegion::OfflineRegionStatusCallback>& callback,
|
||||
std::exception_ptr error) {
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
|
||||
}
|
||||
|
||||
void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineRegion::OfflineRegionStatusCallback>& callback,
|
||||
mbgl::optional<mbgl::OfflineRegionStatus> status) {
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(env, "onStatus");
|
||||
|
||||
callback.Call(env, method, OfflineRegionStatus::New(env, std::move(*status)));
|
||||
}
|
||||
|
||||
// OfflineRegionDeleteCallback //
|
||||
|
||||
void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineRegion::OfflineRegionDeleteCallback>& callback,
|
||||
std::exception_ptr error) {
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
|
||||
}
|
||||
|
||||
void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, const jni::Object<OfflineRegion::OfflineRegionDeleteCallback>& callback) {
|
||||
// Trigger callback
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void ()>(env, "onDelete");
|
||||
|
||||
callback.Call(env, method);
|
||||
}
|
||||
|
||||
// OfflineRegionUpdateMetadataCallback //
|
||||
|
||||
void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback>& callback,
|
||||
std::exception_ptr error) {
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
|
||||
}
|
||||
|
||||
void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback>& callback,
|
||||
mbgl::optional<mbgl::OfflineRegionMetadata> metadata) {
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::Array<jni::jbyte>)>(env, "onUpdate");
|
||||
|
||||
callback.Call(env, method, OfflineRegion::metadata(env, std::move(*metadata)));
|
||||
}
|
||||
|
||||
// OfflineRegionInvalidateCallback //
|
||||
|
||||
void OfflineRegion::OfflineRegionInvalidateCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<OfflineRegion::OfflineRegionInvalidateCallback>& callback,
|
||||
std::exception_ptr error) {
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionInvalidateCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
|
||||
}
|
||||
|
||||
void OfflineRegion::OfflineRegionInvalidateCallback::onInvalidate(jni::JNIEnv& env, const jni::Object<OfflineRegion::OfflineRegionInvalidateCallback>& callback) {
|
||||
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionInvalidateCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void ()>(env, "onInvalidate");
|
||||
callback.Call(env, method);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
92
MapboxGLAndroidSDK/src/cpp/offline/offline_region.hpp
Normal file
92
MapboxGLAndroidSDK/src/cpp/offline/offline_region.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/offline.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "../file_source.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class OfflineRegion {
|
||||
public:
|
||||
class OfflineRegionObserver {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionObserver"; };
|
||||
};
|
||||
|
||||
class OfflineRegionStatusCallback {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionStatusCallback"; };
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionStatusCallback>&, std::exception_ptr);
|
||||
|
||||
static void onStatus(jni::JNIEnv&,
|
||||
const jni::Object<OfflineRegionStatusCallback>&,
|
||||
mbgl::optional<mbgl::OfflineRegionStatus>);
|
||||
};
|
||||
|
||||
class OfflineRegionDeleteCallback {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionDeleteCallback"; };
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&, std::exception_ptr);
|
||||
|
||||
static void onDelete(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&);
|
||||
};
|
||||
|
||||
class OfflineRegionInvalidateCallback {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionInvalidateCallback"; };
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionInvalidateCallback>&, std::exception_ptr);
|
||||
|
||||
static void onInvalidate(jni::JNIEnv&, const jni::Object<OfflineRegionInvalidateCallback>&);
|
||||
};
|
||||
|
||||
class OfflineRegionUpdateMetadataCallback {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionUpdateMetadataCallback"; };
|
||||
|
||||
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionUpdateMetadataCallback>&, std::exception_ptr);
|
||||
|
||||
static void onUpdate(jni::JNIEnv&,
|
||||
const jni::Object<OfflineRegionUpdateMetadataCallback>&,
|
||||
mbgl::optional<mbgl::OfflineRegionMetadata>);
|
||||
};
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion"; };
|
||||
|
||||
OfflineRegion(jni::JNIEnv&, jni::jlong, const jni::Object<FileSource>&);
|
||||
|
||||
~OfflineRegion();
|
||||
|
||||
void setOfflineRegionObserver(jni::JNIEnv&, const jni::Object<OfflineRegion::OfflineRegionObserver>&);
|
||||
|
||||
void setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint);
|
||||
|
||||
void getOfflineRegionStatus(jni::JNIEnv&, const jni::Object<OfflineRegion::OfflineRegionStatusCallback>&);
|
||||
|
||||
void deleteOfflineRegion(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&);
|
||||
|
||||
void invalidateOfflineRegion(jni::JNIEnv&, const jni::Object<OfflineRegionInvalidateCallback>&);
|
||||
|
||||
void updateOfflineRegionMetadata(jni::JNIEnv&, const jni::Array<jni::jbyte>&, const jni::Object<OfflineRegionUpdateMetadataCallback>&);
|
||||
|
||||
static jni::Local<jni::Object<OfflineRegion>> New(jni::JNIEnv&, const jni::Object<FileSource>&, mbgl::OfflineRegion);
|
||||
|
||||
static jni::Local<jni::Array<jni::jbyte>> metadata(jni::JNIEnv&, mbgl::OfflineRegionMetadata);
|
||||
|
||||
static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, const jni::Array<jni::jbyte>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
private:
|
||||
std::unique_ptr<mbgl::OfflineRegion> region;
|
||||
std::shared_ptr<mbgl::DatabaseFileSource> fileSource;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
107
MapboxGLAndroidSDK/src/cpp/offline/offline_region_definition.cpp
Normal file
107
MapboxGLAndroidSDK/src/cpp/offline/offline_region_definition.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "offline_region_definition.hpp"
|
||||
|
||||
#include "../geometry/lat_lng_bounds.hpp"
|
||||
#include "../geojson/geometry.hpp"
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// OfflineRegionDefinition //
|
||||
|
||||
void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<OfflineRegionDefinition>::Singleton(env);
|
||||
}
|
||||
|
||||
mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env,
|
||||
const jni::Object<OfflineRegionDefinition>& jDefinition) {
|
||||
if (jDefinition.IsInstanceOf(env, jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env))) {
|
||||
return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Cast(env, jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env), jDefinition));
|
||||
} else if (jDefinition.IsInstanceOf(env, jni::Class<OfflineGeometryRegionDefinition>::Singleton(env))) {
|
||||
return OfflineGeometryRegionDefinition::getDefinition(env, jni::Cast(env, jni::Class<OfflineGeometryRegionDefinition>::Singleton(env), jDefinition));
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown offline region definition java class");
|
||||
}
|
||||
|
||||
// OfflineTilePyramidRegionDefinition //
|
||||
|
||||
jni::Local<jni::Object<OfflineRegionDefinition>> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) {
|
||||
static auto& javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<LatLngBounds>, jni::jdouble, jni::jdouble, jni::jfloat, jni::jboolean>(env);
|
||||
|
||||
return javaClass.New(env, constructor,
|
||||
jni::Make<jni::String>(env, definition.styleURL),
|
||||
LatLngBounds::New(env, definition.bounds),
|
||||
definition.minZoom,
|
||||
definition.maxZoom,
|
||||
definition.pixelRatio,
|
||||
jni::jboolean(definition.includeIdeographs));
|
||||
}
|
||||
|
||||
mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, const jni::Object<OfflineTilePyramidRegionDefinition>& jDefinition) {
|
||||
// Field references
|
||||
static auto& javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env);
|
||||
static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL");
|
||||
static auto boundsF = javaClass.GetField<jni::Object<LatLngBounds>>(env, "bounds");
|
||||
static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom");
|
||||
static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom");
|
||||
static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio");
|
||||
static auto includeIdeographsF = javaClass.GetField<jni::jboolean >(env, "includeIdeographs");
|
||||
|
||||
return mbgl::OfflineTilePyramidRegionDefinition(
|
||||
jni::Make<std::string>(env, jDefinition.Get(env, styleURLF)),
|
||||
LatLngBounds::getLatLngBounds(env, jDefinition.Get(env, boundsF)),
|
||||
jDefinition.Get(env, minZoomF),
|
||||
jDefinition.Get(env, maxZoomF),
|
||||
jDefinition.Get(env, pixelRatioF),
|
||||
jDefinition.Get(env, includeIdeographsF)
|
||||
);
|
||||
}
|
||||
|
||||
void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env);
|
||||
}
|
||||
|
||||
// OfflineGeometryRegionDefinition //
|
||||
|
||||
jni::Local<jni::Object<OfflineRegionDefinition>> OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) {
|
||||
static auto& javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<geojson::Geometry>, jni::jdouble, jni::jdouble, jni::jfloat, jni::jboolean>(env);
|
||||
|
||||
return javaClass.New(env, constructor,
|
||||
jni::Make<jni::String>(env, definition.styleURL),
|
||||
geojson::Geometry::New(env, definition.geometry),
|
||||
definition.minZoom,
|
||||
definition.maxZoom,
|
||||
definition.pixelRatio,
|
||||
jni::jboolean(definition.includeIdeographs));
|
||||
}
|
||||
|
||||
mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, const jni::Object<OfflineGeometryRegionDefinition>& jDefinition) {
|
||||
// Field references
|
||||
static auto& javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env);
|
||||
static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL");
|
||||
static auto geometryF = javaClass.GetField<jni::Object<geojson::Geometry>>(env, "geometry");
|
||||
static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom");
|
||||
static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom");
|
||||
static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio");
|
||||
static auto includeIdeographsF = javaClass.GetField<jni::jboolean>(env, "includeIdeographs");
|
||||
|
||||
return mbgl::OfflineGeometryRegionDefinition(
|
||||
jni::Make<std::string>(env, jDefinition.Get(env, styleURLF)),
|
||||
geojson::Geometry::convert(env, jDefinition.Get(env, geometryF)),
|
||||
jDefinition.Get(env, minZoomF),
|
||||
jDefinition.Get(env, maxZoomF),
|
||||
jDefinition.Get(env, pixelRatioF),
|
||||
jDefinition.Get(env, includeIdeographsF)
|
||||
);
|
||||
}
|
||||
|
||||
void OfflineGeometryRegionDefinition::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<OfflineGeometryRegionDefinition>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/offline.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class OfflineRegionDefinition {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionDefinition"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, const jni::Object<OfflineRegionDefinition>& jDefinition);
|
||||
};
|
||||
|
||||
class OfflineTilePyramidRegionDefinition {
|
||||
public:
|
||||
using SuperTag = OfflineRegionDefinition;
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition"; };
|
||||
|
||||
static jni::Local<jni::Object<OfflineRegionDefinition>> New(jni::JNIEnv&, const mbgl::OfflineTilePyramidRegionDefinition&);
|
||||
|
||||
static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, const jni::Object<OfflineTilePyramidRegionDefinition>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
class OfflineGeometryRegionDefinition {
|
||||
public:
|
||||
using SuperTag = OfflineRegionDefinition;
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineGeometryRegionDefinition"; };
|
||||
|
||||
static jni::Local<jni::Object<OfflineRegionDefinition>> New(jni::JNIEnv&, const mbgl::OfflineGeometryRegionDefinition&);
|
||||
|
||||
static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, const jni::Object<OfflineGeometryRegionDefinition>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user