[android] [build] [ci] Move Android JNI bindings code to mapbox-gl-native-android repo. (#16356)

This commit is contained in:
Igor Tarasov
2020-04-02 18:36:55 +03:00
committed by GitHub
parent b7728d222c
commit 338cfd1b33
182 changed files with 17 additions and 14124 deletions

View File

@@ -30,7 +30,7 @@ workflows:
requires:
- sanity-checks
config_params: '-G Ninja -DCMAKE_INSTALL_PREFIX=/tmp/workspace/install/$CIRCLE_JOB -DCMAKE_TOOLCHAIN_FILE=/opt/android/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_CCACHE=/usr/bin/ccache -DANDROID_ABI=arm64-v8a'
build_params: '--target libmapbox-gl.so'
build_params: '--target libmbgl-render-test-runner.so'
install: true
- build-template:
name: android-x86-release
@@ -39,7 +39,7 @@ workflows:
requires:
- sanity-checks
config_params: '-G Ninja -DCMAKE_INSTALL_PREFIX=/tmp/workspace/install/$CIRCLE_JOB -DCMAKE_TOOLCHAIN_FILE=/opt/android/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_CCACHE=/usr/bin/ccache -DANDROID_ABI=x86'
build_params: '--target libmapbox-gl.so'
build_params: '--target libmbgl-render-test-runner.so'
install: true
- build-template:
name: android-x86_64-release
@@ -48,7 +48,7 @@ workflows:
requires:
- sanity-checks
config_params: '-G Ninja -DCMAKE_INSTALL_PREFIX=/tmp/workspace/install/$CIRCLE_JOB -DCMAKE_TOOLCHAIN_FILE=/opt/android/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_CCACHE=/usr/bin/ccache -DANDROID_ABI=x86_64'
build_params: '--target libmapbox-gl.so'
build_params: '--target libmbgl-render-test-runner.so'
install: true
- build-template:
name: linux-gcc8-release

View File

@@ -2,8 +2,8 @@
"file-size": [
[
"android-arm64-v8a",
"/tmp/attach/install/android-arm64-v8a-release/lib/libmapbox-gl.so",
1972354
"/tmp/attach/install/android-arm64-v8a-release/lib/libmbgl-render-test-runner.so",
1828611
]
]
}

View File

@@ -3,7 +3,7 @@
"metadata": {
"test": {
"operations": [
["probeFileSize", "android-arm64-v8a", "/tmp/attach/install/android-arm64-v8a-release/lib/libmapbox-gl.so", 0.01, "compressed"]
["probeFileSize", "android-arm64-v8a", "/tmp/attach/install/android-arm64-v8a-release/lib/libmbgl-render-test-runner.so", 0.01, "compressed"]
],
"width": 64,
"height": 64

View File

@@ -2,8 +2,8 @@
"file-size": [
[
"android-armeabi-v7a",
"/tmp/attach/install/android-armeabi-v7a-release/lib/libmapbox-gl.so",
1664652
"/tmp/attach/install/android-armeabi-v7a-release/lib/libmbgl-render-test-runner.so",
1532970
]
]
}

View File

@@ -3,7 +3,7 @@
"metadata": {
"test": {
"operations": [
["probeFileSize", "android-armeabi-v7a", "/tmp/attach/install/android-armeabi-v7a-release/lib/libmapbox-gl.so", 0.01, "compressed"]
["probeFileSize", "android-armeabi-v7a", "/tmp/attach/install/android-armeabi-v7a-release/lib/libmbgl-render-test-runner.so", 0.01, "compressed"]
],
"width": 64,
"height": 64

View File

@@ -2,8 +2,8 @@
"file-size": [
[
"android-x86",
"/tmp/attach/install/android-x86-release/lib/libmapbox-gl.so",
1997677
"/tmp/attach/install/android-x86-release/lib/libmbgl-render-test-runner.so",
1870315
]
]
}

View File

@@ -3,7 +3,7 @@
"metadata": {
"test": {
"operations": [
["probeFileSize", "android-x86", "/tmp/attach/install/android-x86-release/lib/libmapbox-gl.so", 0.01, "compressed"]
["probeFileSize", "android-x86", "/tmp/attach/install/android-x86-release/lib/libmbgl-render-test-runner.so", 0.01, "compressed"]
],
"width": 64,
"height": 64

View File

@@ -2,8 +2,8 @@
"file-size": [
[
"android-x86_64",
"/tmp/attach/install/android-x86_64-release/lib/libmapbox-gl.so",
2008352
"/tmp/attach/install/android-x86_64-release/lib/libmbgl-render-test-runner.so",
1867102
]
]
}

View File

@@ -3,7 +3,7 @@
"metadata": {
"test": {
"operations": [
["probeFileSize", "android-x86_64", "/tmp/attach/install/android-x86_64-release/lib/libmapbox-gl.so", 0.01, "compressed"]
["probeFileSize", "android-x86_64", "/tmp/attach/install/android-x86_64-release/lib/libmbgl-render-test-runner.so", 0.01, "compressed"]
],
"width": 64,
"height": 64

View File

@@ -30,20 +30,6 @@ target_link_libraries(
target_sources(
mbgl-core
PRIVATE
${PROJECT_SOURCE_DIR}/platform/android/src/android_renderer_backend.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/android_renderer_backend.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/android_renderer_frontend.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/android_renderer_frontend.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/annotation/marker.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/annotation/marker.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/annotation/multi_point.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/annotation/polygon.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/annotation/polygon.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/annotation/polyline.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/annotation/polyline.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/asset_manager.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/asset_manager_file_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/asset_manager_file_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/async_task.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/attach_env.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/attach_env.hpp
@@ -51,158 +37,13 @@ target_sources(
${PROJECT_SOURCE_DIR}/platform/android/src/bitmap.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/bitmap_factory.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/bitmap_factory.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/connectivity_listener.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/connectivity_listener.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/conversion/collection.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/conversion/collection.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/conversion/color.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/conversion/color.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/conversion/constant.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/conversion/constant.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/conversion/conversion.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/feature.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/feature.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/feature_collection.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/feature_collection.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/geometry.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/geometry.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/geometry_collection.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/geometry_collection.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/line_string.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/line_string.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/multi_line_string.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/multi_line_string.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/multi_point.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/multi_point.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/multi_polygon.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/multi_polygon.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/point.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/point.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/polygon.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/polygon.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geojson/util.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/lat_lng.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/lat_lng.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/lat_lng_bounds.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/lat_lng_bounds.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/lat_lng_quad.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/lat_lng_quad.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/projected_meters.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/geometry/projected_meters.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/gl_functions.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/graphics/pointf.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/graphics/pointf.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/graphics/rectf.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/graphics/rectf.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_array.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_array.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_element.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_element.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_object.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_object.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_primitive.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/gson/json_primitive.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/image.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/java/util.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/java/util.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/java_types.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/java_types.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/jni.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/jni.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/jni_native.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/jni_native.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/mapbox.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/mapbox.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/map/camera_position.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/map/camera_position.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/map/image.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/map/image.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/map_renderer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/map_renderer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/map_renderer_runnable.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/map_renderer_runnable.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/native_map_view.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/native_map_view.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_manager.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_manager.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region_definition.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region_definition.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region_error.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region_error.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region_status.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/offline/offline_region_status.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/run_loop.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/run_loop_impl.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/snapshotter/map_snapshot.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/snapshotter/map_snapshot.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/snapshotter/map_snapshotter.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/snapshotter/map_snapshotter.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/string_util.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/android_conversion.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/filter.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/filter.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/position.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/position.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/property_expression.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/property_value.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/transition_options.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/transition_options.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/url_or_tileset.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/conversion/url_or_tileset.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/formatted.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/formatted.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/formatted_section.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/formatted_section.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/background_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/background_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/circle_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/circle_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/custom_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/custom_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/fill_extrusion_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/fill_extrusion_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/fill_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/fill_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/heatmap_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/heatmap_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/hillshade_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/hillshade_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/layer_manager.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/layer_manager.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/line_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/line_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/raster_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/raster_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/symbol_layer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/layers/symbol_layer.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/light.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/light.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/position.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/position.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/custom_geometry_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/custom_geometry_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/geojson_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/geojson_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/image_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/image_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/raster_dem_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/raster_dem_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/raster_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/raster_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/unknown_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/unknown_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/vector_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/sources/vector_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/transition_options.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/transition_options.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/value.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/style/value.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/thread.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/timer.cpp
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gfx/headless_backend.cpp
@@ -227,6 +68,7 @@ target_sources(
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/util/png_writer.cpp
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/util/thread_local.cpp
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/util/utf.cpp
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/layermanager/layer_manager.cpp
${PROJECT_SOURCE_DIR}/platform/linux/src/headless_backend_egl.cpp
)
@@ -250,51 +92,6 @@ target_link_libraries(
z
)
add_library(
mbgl-core-android STATIC
${PROJECT_SOURCE_DIR}/platform/android/src/file_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/file_source.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/http_file_source.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/i18n/collator.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/i18n/collator_jni.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/i18n/number_format.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/i18n/number_format_jni.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/logger.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/logger.hpp
${PROJECT_SOURCE_DIR}/platform/android/src/logging_android.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/text/local_glyph_rasterizer.cpp
${PROJECT_SOURCE_DIR}/platform/android/src/text/local_glyph_rasterizer_jni.hpp
)
target_include_directories(
mbgl-core-android
PRIVATE ${PROJECT_SOURCE_DIR}/platform/default/include ${PROJECT_SOURCE_DIR}/src
)
target_link_libraries(
mbgl-core-android
PRIVATE Mapbox::Base::jni.hpp mbgl-compiler-options mbgl-core
)
add_library(
mapbox-gl SHARED
${PROJECT_SOURCE_DIR}/platform/android/src/main.cpp
)
target_include_directories(
mapbox-gl
PRIVATE ${PROJECT_SOURCE_DIR}/platform/default/include ${PROJECT_SOURCE_DIR}/src
)
target_link_libraries(
mapbox-gl
PRIVATE
Mapbox::Base::jni.hpp
mbgl-compiler-options
mbgl-core
mbgl-core-android
)
add_library(
example-custom-layer MODULE
${PROJECT_SOURCE_DIR}/platform/android/src/example_custom_layer.cpp
@@ -470,4 +267,4 @@ add_custom_command(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
install(TARGETS mapbox-gl LIBRARY DESTINATION lib)
install(TARGETS mbgl-render-test-runner LIBRARY DESTINATION lib)

View File

@@ -1,67 +0,0 @@
#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

View File

@@ -1,43 +0,0 @@
#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

View File

@@ -1,143 +0,0 @@
#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

View File

@@ -1,68 +0,0 @@
#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

View File

@@ -1,23 +0,0 @@
#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

View File

@@ -1,28 +0,0 @@
#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

View File

@@ -1,34 +0,0 @@
#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

View File

@@ -1,40 +0,0 @@
#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

View File

@@ -1,21 +0,0 @@
#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

View File

@@ -1,31 +0,0 @@
#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

View File

@@ -1,21 +0,0 @@
#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

View File

@@ -1,14 +0,0 @@
#pragma once
namespace mbgl {
namespace android {
class AssetManager {
public:
static constexpr auto Name() {
return "android/content/res/AssetManager";
};
};
} // namespace android
} // namespace mbgl

View File

@@ -1,65 +0,0 @@
#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

View File

@@ -1,30 +0,0 @@
#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

View File

@@ -1,41 +0,0 @@
#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

View File

@@ -1,29 +0,0 @@
#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

View File

@@ -1,32 +0,0 @@
#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;
}
}
}
}

View File

@@ -1,18 +0,0 @@
#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>&);
}
}
}

View File

@@ -1,17 +0,0 @@
#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

View File

@@ -1,18 +0,0 @@
#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

View File

@@ -1,62 +0,0 @@
#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

View File

@@ -1,110 +0,0 @@
#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

View File

@@ -1,50 +0,0 @@
#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

View File

@@ -1,252 +0,0 @@
#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

View File

@@ -1,83 +0,0 @@
#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

View File

@@ -1,88 +0,0 @@
#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

View File

@@ -1,24 +0,0 @@
#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

View File

@@ -1,37 +0,0 @@
#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

View File

@@ -1,26 +0,0 @@
#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

View File

@@ -1,97 +0,0 @@
#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

View File

@@ -1,28 +0,0 @@
#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

View File

@@ -1,47 +0,0 @@
#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

View File

@@ -1,26 +0,0 @@
#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

View File

@@ -1,55 +0,0 @@
#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

View File

@@ -1,36 +0,0 @@
#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

View File

@@ -1,56 +0,0 @@
#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

View File

@@ -1,34 +0,0 @@
#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

View File

@@ -1,41 +0,0 @@
#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

View File

@@ -1,33 +0,0 @@
#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

View File

@@ -1,53 +0,0 @@
#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

View File

@@ -1,32 +0,0 @@
#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

View File

@@ -1,34 +0,0 @@
#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

View File

@@ -1,27 +0,0 @@
#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

View File

@@ -1,55 +0,0 @@
#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

View File

@@ -1,35 +0,0 @@
#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

View File

@@ -1,52 +0,0 @@
#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

View File

@@ -1,29 +0,0 @@
#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

View File

@@ -1,29 +0,0 @@
#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

View File

@@ -1,30 +0,0 @@
#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

View File

@@ -1,26 +0,0 @@
#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

View File

@@ -1,37 +0,0 @@
#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

View File

@@ -1,27 +0,0 @@
#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

View File

@@ -1,17 +0,0 @@
#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

View File

@@ -1,21 +0,0 @@
#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

View File

@@ -1,25 +0,0 @@
#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

View File

@@ -1,24 +0,0 @@
#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

View File

@@ -1,35 +0,0 @@
#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

View File

@@ -1,28 +0,0 @@
#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

View File

@@ -1,50 +0,0 @@
#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

View File

@@ -1,24 +0,0 @@
#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

View File

@@ -1,88 +0,0 @@
#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

View File

@@ -1,24 +0,0 @@
#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

View File

@@ -1,65 +0,0 @@
#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

View File

@@ -1,24 +0,0 @@
#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

View File

@@ -1,13 +0,0 @@
#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

View File

@@ -1,21 +0,0 @@
#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

View File

@@ -1,195 +0,0 @@
#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

View File

@@ -1,192 +0,0 @@
#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

View File

@@ -1,62 +0,0 @@
#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

View File

@@ -1,80 +0,0 @@
#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

View File

@@ -1,29 +0,0 @@
#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

View File

@@ -1,19 +0,0 @@
#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

View File

@@ -1,81 +0,0 @@
#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

View File

@@ -1,49 +0,0 @@
#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;");
}
}
}
}

View File

@@ -1,43 +0,0 @@
#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&);
}
}
}

View File

@@ -1,168 +0,0 @@
#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

View File

@@ -1,13 +0,0 @@
#pragma once
#include <mbgl/util/util.hpp>
#include "jni.hpp"
namespace mbgl {
namespace android {
MBGL_EXPORT void registerNatives(JavaVM* vm);
} // namespace android
} // namespace mbgl

View File

@@ -1,34 +0,0 @@
#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

View File

@@ -1,21 +0,0 @@
#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

View File

@@ -1,13 +0,0 @@
#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);
}
}

View File

@@ -1,9 +0,0 @@
#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;
}

View File

@@ -1,69 +0,0 @@
#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

View File

@@ -1,23 +0,0 @@
#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

View File

@@ -1,41 +0,0 @@
#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

View File

@@ -1,21 +0,0 @@
#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

View File

@@ -1,247 +0,0 @@
#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

View File

@@ -1,138 +0,0 @@
#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

View File

@@ -1,49 +0,0 @@
#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

View File

@@ -1,47 +0,0 @@
#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

View File

@@ -1,23 +0,0 @@
#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

Some files were not shown because too many files have changed in this diff Show More