[general] moving ios and android project under ./platform folder
This commit is contained in:
2022
platform/android/CHANGELOG.md
Normal file
2022
platform/android/CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
57
platform/android/DISTRIBUTE.md
Normal file
57
platform/android/DISTRIBUTE.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Distributing Mapbox GL Native for Android
|
||||
|
||||
Depending on your use case, you may want to support all or just a subset of [Android ABIs](http://developer.android.com/ndk/guides/abis.html). This document covers building an `.aar` file from the Mapbox Maps SDK for Android and building `.so` files for specific ABIs. In normal circumstances an application developer will use [APK splits](https://developer.android.com/studio/build/configure-apk-splits.html) to optimize this at application level.
|
||||
|
||||
##### Build types
|
||||
|
||||
With a `BUILDTYPE` var you can specify the build type for the `.so` and `.aar` files:
|
||||
|
||||
```bash
|
||||
BUILDTYPE=Debug or BUILDTYPE=Release
|
||||
```
|
||||
|
||||
##### Creating an Android Archive file that supports all ABIs
|
||||
|
||||
```sh
|
||||
BUILDTYPE=Release make apackage
|
||||
```
|
||||
|
||||
This will build native libraries to support following ABIs:
|
||||
- armeabi
|
||||
- armeabi-v7a
|
||||
- arm64-v8a
|
||||
- x86
|
||||
- x86_64
|
||||
- mips
|
||||
|
||||
After succesfully finish building the native libraries, gradle will build the MapboxAndroidSDK module and generate an Android Archive file in `MapboxAndroidSDK/build/outputs/aar `. The packaged native libraries can be found in `MapboxAndroidSDK/src/main/jniLibs/<abi>`.
|
||||
|
||||
##### Build native libraries for a specific ABI
|
||||
|
||||
```sh
|
||||
make android-lib-%%
|
||||
```
|
||||
|
||||
In the command above you'll need to replace `%%` with an ABI key listed below:
|
||||
|
||||
| ABI Key | Android ABI |
|
||||
| ------- | ----------- |
|
||||
| arm-v5 | armeabi |
|
||||
| arm-v7 | armeabi-v7a |
|
||||
| arm-v8 | arm64-v8a |
|
||||
| x86 | x86 |
|
||||
| x86-64 | x86_64 |
|
||||
| mips | mips |
|
||||
|
||||
For example, to build the arm64-v8a ABI the Makefile target would be:
|
||||
|
||||
```sh
|
||||
make android-lib-arm-v8
|
||||
```
|
||||
|
||||
It's also possible to build multiple ABI (without having to build them all) by running the Makefile multiple times. For example to build arm64-v8a and x86_64 in the same project the commands would be:
|
||||
|
||||
```sh
|
||||
make android-lib-arm-v8
|
||||
make android-lib-arm-x86-64
|
||||
```
|
||||
232
platform/android/LICENSE.md
Normal file
232
platform/android/LICENSE.md
Normal file
@@ -0,0 +1,232 @@
|
||||
<!-- This file was generated. Use `make android-license` to update. -->
|
||||
mapbox-gl-native-android copyright 2014-2020 Mapbox.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Arch-Common.
|
||||
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Arch-Runtime.
|
||||
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Lifecycle LiveData.
|
||||
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Lifecycle LiveData Core.
|
||||
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Lifecycle Runtime.
|
||||
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Lifecycle ViewModel.
|
||||
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Lifecycle-Common.
|
||||
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Annotations.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Async Layout Inflater.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library collections.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library compat.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Coordinator Layout.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library core UI.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library core utils.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Cursor Adapter.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Custom View.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Custom View.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Document File.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Drawer Layout.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library fragment.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Interpolators.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library loader.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Local Broadcast Manager.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Print.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library Sliding Pane Layout.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Android Support Library View Pager.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Gson.
|
||||
License: [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Mapbox Accounts SDK for Android.
|
||||
URL: [https://github.com/mapbox/mapbox-accounts-android](https://github.com/mapbox/mapbox-accounts-android)
|
||||
License: [Mapbox Terms of Service](https://www.mapbox.com/tos/)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Mapbox Android Core Library.
|
||||
URL: [https://github.com/mapbox/mapbox-events-android](https://github.com/mapbox/mapbox-events-android)
|
||||
License: [The MIT License](https://opensource.org/licenses/MIT)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Mapbox Android Gestures Library.
|
||||
URL: [https://github.com/mapbox/mapbox-gestures-android](https://github.com/mapbox/mapbox-gestures-android)
|
||||
License: [BSD](https://opensource.org/licenses/BSD-2-Clause)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Mapbox Android Telemetry Library.
|
||||
URL: [https://github.com/mapbox/mapbox-events-android](https://github.com/mapbox/mapbox-events-android)
|
||||
License: [The MIT License](https://opensource.org/licenses/MIT)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Mapbox Java SDK.
|
||||
URL: [https://github.com/mapbox/mapbox-java](https://github.com/mapbox/mapbox-java)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Mapbox Java SDK.
|
||||
URL: [https://github.com/mapbox/mapbox-java](https://github.com/mapbox/mapbox-java)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of OkHttp.
|
||||
License: [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Okio.
|
||||
License: [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of VersionedParcelable and friends.
|
||||
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
Mapbox GL uses portions of Gradle License Plugin.
|
||||
URL: [https://github.com/jaredsburrows/gradle-license-plugin](https://github.com/jaredsburrows/gradle-license-plugin)
|
||||
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
===========================================================================
|
||||
|
||||
350
platform/android/Makefile
Normal file
350
platform/android/Makefile
Normal file
@@ -0,0 +1,350 @@
|
||||
export BUILDTYPE ?= Debug
|
||||
export IS_LOCAL_DEVELOPMENT ?= true
|
||||
export TARGET_BRANCH ?= master
|
||||
|
||||
CMAKE ?= cmake
|
||||
|
||||
|
||||
ifeq ($(BUILDTYPE), Release)
|
||||
else ifeq ($(BUILDTYPE), RelWithDebInfo)
|
||||
else ifeq ($(BUILDTYPE), Sanitize)
|
||||
else ifeq ($(BUILDTYPE), Debug)
|
||||
else
|
||||
$(error BUILDTYPE must be Debug, Sanitize, Release or RelWithDebInfo)
|
||||
endif
|
||||
|
||||
buildtype := $(shell echo "$(BUILDTYPE)" | tr "[A-Z]" "[a-z]")
|
||||
|
||||
ifeq ($(shell uname -s), Darwin)
|
||||
HOST_PLATFORM = macos
|
||||
HOST_PLATFORM_VERSION = $(shell uname -m)
|
||||
export NINJA = platform/macos/ninja
|
||||
export JOBS ?= $(shell sysctl -n hw.ncpu)
|
||||
else ifeq ($(shell uname -s), Linux)
|
||||
HOST_PLATFORM = linux
|
||||
HOST_PLATFORM_VERSION = $(shell uname -m)
|
||||
export NINJA = platform/linux/ninja
|
||||
export JOBS ?= $(shell grep --count processor /proc/cpuinfo)
|
||||
else
|
||||
$(error Cannot determine host platform)
|
||||
endif
|
||||
|
||||
#### Android targets ###########################################################
|
||||
|
||||
MBGL_ANDROID_ABIS = arm-v7;armeabi-v7a
|
||||
MBGL_ANDROID_ABIS += arm-v8;arm64-v8a
|
||||
MBGL_ANDROID_ABIS += x86;x86
|
||||
MBGL_ANDROID_ABIS += x86-64;x86_64
|
||||
|
||||
MBGL_ANDROID_LOCAL_WORK_DIR = /data/local/tmp/core-tests
|
||||
MBGL_ANDROID_LOCAL_BENCHMARK_DIR = /data/local/tmp/benchmark
|
||||
MBGL_ANDROID_LIBDIR = lib$(if $(filter arm-v8 x86-64,$1),64)
|
||||
MBGL_ANDROID_DALVIKVM = dalvikvm$(if $(filter arm-v8 x86-64,$1),64,32)
|
||||
MBGL_ANDROID_APK_SUFFIX = $(if $(filter Release,$(BUILDTYPE)),release,debug)
|
||||
MBGL_ANDROID_CORE_TEST_DIR = MapboxGLAndroidSDK/.externalNativeBuild/cmake/$(buildtype)/$2/core-tests
|
||||
MBGL_ANDROID_BENCHMARK_DIR = MapboxGLAndroidSDK/.externalNativeBuild/cmake/$(buildtype)/$2/benchmark
|
||||
MBGL_ANDROID_STL ?= c++_static
|
||||
MBGL_ANDROID_GRADLE = ./gradlew --parallel --max-workers=$(JOBS) -Pmapbox.buildtype=$(buildtype) -Pmapbox.stl=$(MBGL_ANDROID_STL)
|
||||
|
||||
# Lists all devices, and extracts the identifiers, then obtains the ABI for every one.
|
||||
# Some devices return \r\n, so we'll have to remove the carriage return before concatenating.
|
||||
MBGL_ANDROID_ACTIVE_ARCHS = $(shell adb devices | sed '1d;/^\*/d;s/[[:space:]].*//' | xargs -n 1 -I DEV `type -P adb` -s DEV shell getprop ro.product.cpu.abi | tr -d '\r')
|
||||
|
||||
# Generate code based on the style specification
|
||||
.PHONY: android-style-code
|
||||
android-style-code:
|
||||
node scripts/generate-style-code.js
|
||||
style-code: android-style-code
|
||||
|
||||
# Configuration file for running CMake from Gradle within Android Studio.
|
||||
gradle/configuration.gradle:
|
||||
@printf "ext {\n node = '`command -v node || command -v nodejs`'\n npm = '`command -v npm`'\n ccache = '`command -v ccache`'\n}" > $@
|
||||
|
||||
define ANDROID_RULES
|
||||
# $1 = arm-v7 (short arch)
|
||||
# $2 = armeabi-v7a (internal arch)
|
||||
|
||||
.PHONY: android-test-lib-$1
|
||||
android-test-lib-$1: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 -Pmapbox.with_test=true :MapboxGLAndroidSDKTestApp:assemble$(BUILDTYPE)
|
||||
|
||||
.PHONY: android-benchmark-$1
|
||||
android-benchmark-$1: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 -Pmapbox.with_benchmark=true :MapboxGLAndroidSDKTestApp:assemble$(BUILDTYPE)
|
||||
|
||||
# Build SDK for for specified abi
|
||||
.PHONY: android-lib-$1
|
||||
android-lib-$1: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDK:assemble$(BUILDTYPE)
|
||||
|
||||
# Build test app and SDK for for specified abi
|
||||
.PHONY: android-$1
|
||||
android-$1: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:assemble$(BUILDTYPE)
|
||||
|
||||
# Build the core test for specified abi
|
||||
.PHONY: android-core-test-$1
|
||||
android-core-test-$1: android-test-lib-$1
|
||||
# Compile main sources and extract the classes (using the test app to get all transitive dependencies in one place)
|
||||
mkdir -p $(MBGL_ANDROID_CORE_TEST_DIR)
|
||||
unzip -o MapboxGLAndroidSDKTestApp/build/outputs/apk/$(buildtype)/MapboxGLAndroidSDKTestApp-$(MBGL_ANDROID_APK_SUFFIX).apk classes.dex -d $(MBGL_ANDROID_CORE_TEST_DIR)
|
||||
|
||||
run-android-core-test-$1-%: android-core-test-$1
|
||||
# Ensure clean state on the device
|
||||
adb shell "rm -Rf $(MBGL_ANDROID_LOCAL_WORK_DIR) && mkdir -p $(MBGL_ANDROID_LOCAL_WORK_DIR)/test && mkdir -p $(MBGL_ANDROID_LOCAL_WORK_DIR)/mapbox-gl-js/src/style-spec/reference"
|
||||
|
||||
# Push all needed files to the device
|
||||
adb push $(MBGL_ANDROID_CORE_TEST_DIR)/classes.dex $(MBGL_ANDROID_LOCAL_WORK_DIR) > /dev/null 2>&1
|
||||
adb push MapboxGLAndroidSDK/build/intermediates/intermediate-jars/$(buildtype)/jni/$2/libmapbox-gl.so $(MBGL_ANDROID_LOCAL_WORK_DIR) > /dev/null 2>&1
|
||||
adb push test/fixtures $(MBGL_ANDROID_LOCAL_WORK_DIR)/test > /dev/null 2>&1
|
||||
adb push mapbox-gl-js/src/style-spec/reference/v8.json $(MBGL_ANDROID_LOCAL_WORK_DIR)/mapbox-gl-js/src/style-spec/reference > /dev/null 2>&1
|
||||
adb push MapboxGLAndroidSDK/build/intermediates/cmake/$(buildtype)/obj/$2/mbgl-test $(MBGL_ANDROID_LOCAL_WORK_DIR) > /dev/null 2>&1
|
||||
|
||||
# Create gtest filter for skipped tests.
|
||||
$(eval SKIPPED_TESTS := -$(shell sed -n '/#\|^$$/!p' tests/skipped.txt | sed ':a;$!N;s/\n/:/g;ta'))
|
||||
|
||||
# Kick off the tests
|
||||
adb shell "export LD_LIBRARY_PATH=$(MBGL_ANDROID_LOCAL_WORK_DIR) && cd $(MBGL_ANDROID_LOCAL_WORK_DIR) && chmod +x mbgl-test && ./mbgl-test --class_path=$(MBGL_ANDROID_LOCAL_WORK_DIR)/classes.dex --gtest_filter=$$*:$(SKIPPED_TESTS)"
|
||||
|
||||
# Gather the results and unpack them
|
||||
adb shell "cd $(MBGL_ANDROID_LOCAL_WORK_DIR) && tar -cvzf results.tgz test/fixtures/* > /dev/null 2>&1"
|
||||
adb pull $(MBGL_ANDROID_LOCAL_WORK_DIR)/results.tgz $(MBGL_ANDROID_CORE_TEST_DIR)/ > /dev/null 2>&1
|
||||
rm -rf $(MBGL_ANDROID_CORE_TEST_DIR)/results && mkdir -p $(MBGL_ANDROID_CORE_TEST_DIR)/results
|
||||
tar -xzf $(MBGL_ANDROID_CORE_TEST_DIR)/results.tgz --strip-components=2 -C $(MBGL_ANDROID_CORE_TEST_DIR)/results
|
||||
|
||||
# Run the core test for specified abi
|
||||
.PHONY: run-android-core-test-$1
|
||||
run-android-core-test-$1: run-android-core-test-$1-*
|
||||
|
||||
# Run benchmarks for specified abi
|
||||
.PHONY: run-android-benchmark-$1
|
||||
run-android-benchmark-$1: run-android-benchmark-$1-*
|
||||
|
||||
run-android-benchmark-$1-%: android-benchmark-$1
|
||||
mkdir -p $(MBGL_ANDROID_BENCHMARK_DIR)
|
||||
unzip -o MapboxGLAndroidSDKTestApp/build/outputs/apk/$(buildtype)/MapboxGLAndroidSDKTestApp-$(MBGL_ANDROID_APK_SUFFIX).apk classes.dex -d $(MBGL_ANDROID_BENCHMARK_DIR)
|
||||
|
||||
# Delete old test folder and create new one
|
||||
adb shell "rm -Rf $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR) && mkdir -p $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR)/benchmark && mkdir -p $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR)/test"
|
||||
|
||||
# Push compiled java sources, test data and executable to device
|
||||
adb push $(MBGL_ANDROID_BENCHMARK_DIR)/classes.dex $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR) > /dev/null 2>&1
|
||||
adb push MapboxGLAndroidSDK/build/intermediates/intermediate-jars/$(buildtype)/jni/$2/libmapbox-gl.so $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR) > /dev/null 2>&1
|
||||
adb push benchmark/fixtures $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR)/benchmark > /dev/null 2>&1
|
||||
adb push test/fixtures $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR)/test > /dev/null 2>&1
|
||||
adb push MapboxGLAndroidSDK/build/intermediates/cmake/$(buildtype)/obj/$2/mbgl-benchmark $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR) > /dev/null 2>&1
|
||||
|
||||
# Run benchmark. Number of benchmark iterations can be set by run-android-benchmark-N parameter.
|
||||
adb shell "export LD_LIBRARY_PATH=$(MBGL_ANDROID_LOCAL_BENCHMARK_DIR) && cd $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR) && chmod +x mbgl-benchmark && ./mbgl-benchmark --class_path=$(MBGL_ANDROID_LOCAL_BENCHMARK_DIR)/classes.dex --benchmark_repetitions=$$* --benchmark_format=json --benchmark_out=results.json"
|
||||
|
||||
# Pull results.json from the device
|
||||
rm -rf $(MBGL_ANDROID_BENCHMARK_DIR)/results && mkdir -p $(MBGL_ANDROID_BENCHMARK_DIR)/results
|
||||
adb pull $(MBGL_ANDROID_LOCAL_BENCHMARK_DIR)/results.json $(MBGL_ANDROID_BENCHMARK_DIR)/results > /dev/null 2>&1
|
||||
|
||||
# Run the test app on connected android device with specified abi
|
||||
.PHONY: run-android-$1
|
||||
run-android-$1: gradle/configuration.gradle
|
||||
-adb uninstall com.mapbox.mapboxsdk.testapp 2> /dev/null
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:install$(BUILDTYPE) && adb shell am start -n com.mapbox.mapboxsdk.testapp/.activity.FeatureOverviewActivity
|
||||
|
||||
# Build test app instrumentation tests apk and test app apk for specified abi
|
||||
.PHONY: android-ui-test-$1
|
||||
android-ui-test-$1: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:assembleDebug :MapboxGLAndroidSDKTestApp:assembleAndroidTest
|
||||
|
||||
# Run test app instrumentation tests on a connected android device or emulator with specified abi
|
||||
.PHONY: run-android-ui-test-$1
|
||||
run-android-ui-test-$1: gradle/configuration.gradle
|
||||
-adb uninstall com.mapbox.mapboxsdk.testapp 2> /dev/null
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:connectedAndroidTest
|
||||
|
||||
# Run Java Instrumentation tests on a connected android device or emulator with specified abi and test filter
|
||||
run-android-ui-test-$1-%: gradle/configuration.gradle
|
||||
-adb uninstall com.mapbox.mapboxsdk.testapp 2> /dev/null
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class="$$*"
|
||||
|
||||
# Symbolicate native stack trace with the specified abi
|
||||
.PHONY: android-ndk-stack-$1
|
||||
android-ndk-stack-$1: gradle/configuration.gradle
|
||||
adb logcat | ndk-stack -sym MapboxGLAndroidSDK/build/intermediates/cmake/debug/obj/$2/
|
||||
|
||||
# Run render tests with pixelmatch
|
||||
.PHONY: run-android-render-test-$1
|
||||
run-android-render-test-$1: $(BUILD_DEPS) gradle/configuration.gradle
|
||||
-adb uninstall com.mapbox.mapboxsdk.testapp 2> /dev/null
|
||||
# delete old test results
|
||||
rm -rf build/render-test/mapbox/
|
||||
# copy test definitions & ignore file to test app assets folder, clear old ones first
|
||||
rm -rf MapboxGLAndroidSDKTestApp/src/main/assets/integration
|
||||
cp -r mapbox-gl-js/test/integration MapboxGLAndroidSDKTestApp/src/main/assets
|
||||
cp platform/node/test/ignores.json MapboxGLAndroidSDKTestApp/src/main/assets/integration/ignores.json
|
||||
# run RenderTest.java to generate static map images
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class="com.mapbox.mapboxsdk.testapp.render.RenderTest"
|
||||
# pull generated images from the device
|
||||
adb pull "`adb shell 'printenv EXTERNAL_STORAGE' | tr -d '\r'`/mapbox/render" build/render-test
|
||||
# copy expected result and run pixelmatch
|
||||
python scripts/run-render-test.py
|
||||
# remove test definitions from assets
|
||||
rm -rf MapboxGLAndroidSDKTestApp/src/main/assets/integration
|
||||
|
||||
endef
|
||||
|
||||
# Explodes the arguments into individual variables
|
||||
define ANDROID_RULES_INVOKER
|
||||
$(call ANDROID_RULES,$(word 1,$1),$(word 2,$1))
|
||||
endef
|
||||
|
||||
$(foreach abi,$(MBGL_ANDROID_ABIS),$(eval $(call ANDROID_RULES_INVOKER,$(subst ;, ,$(abi)))))
|
||||
|
||||
# Build the Android SDK and test app with abi set to arm-v7
|
||||
.PHONY: android
|
||||
android: android-arm-v7
|
||||
|
||||
# Build the Android SDK with abi set to arm-v7
|
||||
.PHONY: android-lib
|
||||
android-lib: android-lib-arm-v7
|
||||
|
||||
# Run the test app on connected android device with abi set to arm-v7
|
||||
.PHONY: run-android
|
||||
run-android: run-android-arm-v7
|
||||
|
||||
# Run Java Instrumentation tests on a connected android device or emulator with abi set to arm-v7
|
||||
.PHONY: run-android-ui-test
|
||||
run-android-ui-test: run-android-ui-test-arm-v7
|
||||
run-android-ui-test-%: run-android-ui-test-arm-v7-%
|
||||
|
||||
# Run Java Unit tests on the JVM of the development machine executing this
|
||||
.PHONY: run-android-unit-test
|
||||
run-android-unit-test: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:testDebugUnitTest --info
|
||||
run-android-unit-test-%: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:testDebugUnitTest --info --tests "$*"
|
||||
|
||||
# Run unit test and build a coverage report from .exec file generated by unit tests and .ec file generated by instrumentation tests
|
||||
.PHONY: android-create-jacoco-report
|
||||
android-create-jacoco-report: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:jacocoTestReport
|
||||
|
||||
# Parse merged jacoco report and send it to S3
|
||||
.PHONY: android-parse-and-send-jacoco-report
|
||||
android-parse-and-send-jacoco-report:
|
||||
python scripts/parse-jacoco-report.py
|
||||
|
||||
# Builds a release package of the Android SDK
|
||||
.PHONY: apackage
|
||||
apackage: gradle/configuration.gradle
|
||||
make android-lib-arm-v7 && make android-lib-arm-v8 && make android-lib-x86 && make android-lib-x86-64
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=all assemble$(BUILDTYPE)
|
||||
|
||||
# Build test app instrumentation tests apk and test app apk for all abi's
|
||||
.PHONY: android-ui-test
|
||||
android-ui-test: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=all :MapboxGLAndroidSDKTestApp:assembleDebug :MapboxGLAndroidSDKTestApp:assembleAndroidTest
|
||||
|
||||
#Run instrumentations tests on MicroSoft App Center, ${devices} can be "xiaomi","huawei","OnePlus","htc"
|
||||
.PHONY: run-android-test-app-center
|
||||
run-android-test-app-center:
|
||||
appcenter test run espresso --app "Mapbox-mobile/Maps-sdk" --devices "Mapbox-mobile/${devices}" --app-path MapboxGLAndroidSDKTestApp/build/outputs/apk/debug/MapboxGLAndroidSDKTestApp-debug.apk --test-series "master" --locale "en_US" --build-dir MapboxGLAndroidSDKTestApp/build/outputs/apk/androidTest/debug --token ${APPCENTER_ACCESS_TOKEN}
|
||||
|
||||
# Uploads the compiled Android SDK to Bintray
|
||||
.PHONY: run-android-upload-to-bintray
|
||||
run-android-upload-to-bintray: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=all :MapboxGLAndroidSDK:bintrayUpload
|
||||
|
||||
# Uploads the compiled Android SDK SNAPSHOT to oss.jfrog.org
|
||||
.PHONY: run-android-upload-to-artifactory
|
||||
run-android-upload-to-artifactory: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=all :MapboxGLAndroidSDK:artifactoryPublish
|
||||
|
||||
# Uploads the compiled Android SDK to maven github package registry
|
||||
.PHONY: android-maven-publish
|
||||
android-maven-publish: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=all :MapboxGLAndroidSDK:publish
|
||||
|
||||
# Dump system graphics information for the test app
|
||||
.PHONY: android-gfxinfo
|
||||
android-gfxinfo:
|
||||
adb shell dumpsys gfxinfo com.mapbox.mapboxsdk.testapp reset
|
||||
|
||||
# Generates Activity sanity tests
|
||||
.PHONY: test-code-android
|
||||
test-code-android:
|
||||
node scripts/generate-test-code.js
|
||||
|
||||
# Runs checkstyle and lint on the java code
|
||||
.PHONY: android-check
|
||||
android-check : android-ktlint android-checkstyle android-lint-sdk android-lint-test-app run-android-nitpick
|
||||
|
||||
# Runs checkstyle on the java code
|
||||
.PHONY: android-checkstyle
|
||||
android-checkstyle: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:checkstyle :MapboxGLAndroidSDKTestApp:checkstyle
|
||||
|
||||
# Runs checkstyle on the kotlin code
|
||||
.PHONY: android-ktlint
|
||||
android-ktlint: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none ktlint
|
||||
|
||||
# Runs lint on the Android SDK java code
|
||||
.PHONY: android-lint-sdk
|
||||
android-lint-sdk: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:lint
|
||||
|
||||
# Runs lint on the Android test app java code
|
||||
.PHONY: android-lint-test-app
|
||||
android-lint-test-app: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDKTestApp:lint
|
||||
|
||||
# Generates javadoc from the Android SDK
|
||||
.PHONY: android-javadoc
|
||||
android-javadoc: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:javadocrelease
|
||||
|
||||
# Generates LICENSE.md file based on all Android project dependencies
|
||||
.PHONY: android-license
|
||||
android-license: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:licenseReleaseReport
|
||||
python scripts/generate-license.py
|
||||
|
||||
# Symbolicate ndk stack traces for the arm-v7 abi
|
||||
.PHONY: android-ndk-stack
|
||||
android-ndk-stack: android-ndk-stack-arm-v7
|
||||
|
||||
# Open Android Studio if machine is macos
|
||||
ifeq ($(HOST_PLATFORM), macos)
|
||||
.PHONY: aproj
|
||||
aproj: gradle/configuration.gradle
|
||||
open -b com.google.android.studio
|
||||
endif
|
||||
|
||||
# Creates the configuration needed to build with Android Studio
|
||||
.PHONY: android-configuration
|
||||
android-configuration: gradle/configuration.gradle
|
||||
cat gradle/configuration.gradle
|
||||
|
||||
# Updates Android's vendor submodules
|
||||
.PHONY: android-update-vendor
|
||||
android-update-vendor: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none updateVendorSubmodules
|
||||
|
||||
# Run android nitpick script
|
||||
.PHONY: run-android-nitpick
|
||||
run-android-nitpick: android-update-vendor
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none androidNitpick
|
||||
|
||||
# Creates a dependency graph using Graphviz
|
||||
.PHONY: android-graph
|
||||
android-graph: gradle/configuration.gradle
|
||||
$(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:generateDependencyGraphMapboxLibraries
|
||||
|
||||
#### Miscellaneous targets #####################################################
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -rf ./gradle/configuration.gradle \
|
||||
./MapboxGLAndroidSDK/build \
|
||||
./MapboxGLAndroidSDK/.externalNativeBuild \
|
||||
./MapboxGLAndroidSDKTestApp/build \
|
||||
./MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen \
|
||||
./MapboxGLAndroidSDK/src/main/assets \
|
||||
./MapboxGLAndroidSDKTestApp/src/main/assets/integration
|
||||
2
platform/android/MapboxGLAndroidSDK/.gitignore
vendored
Normal file
2
platform/android/MapboxGLAndroidSDK/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
dependency-graph-mapbox-libraries.png
|
||||
src/test/resources/mobile-event*
|
||||
105
platform/android/MapboxGLAndroidSDK/build.gradle
Normal file
105
platform/android/MapboxGLAndroidSDK/build.gradle
Normal file
@@ -0,0 +1,105 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: "com.jaredsburrows.license"
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "${rootDir}/gradle/native-build.gradle"
|
||||
apply plugin: 'com.mapbox.android.sdk.versions'
|
||||
|
||||
dependencies {
|
||||
lintChecks project(":MapboxGLAndroidSDKLint")
|
||||
api dependenciesList.mapboxAndroidTelemetry
|
||||
api dependenciesList.mapboxJavaGeoJSON
|
||||
api dependenciesList.mapboxAndroidGestures
|
||||
api dependenciesList.mapboxAndroidAccounts
|
||||
implementation dependenciesList.mapboxJavaTurf
|
||||
implementation dependenciesList.supportAnnotations
|
||||
implementation dependenciesList.supportFragmentV4
|
||||
implementation dependenciesList.okhttp3
|
||||
testImplementation dependenciesList.junit
|
||||
testImplementation dependenciesList.mockito
|
||||
testImplementation dependenciesList.mockk
|
||||
testImplementation dependenciesList.robolectric
|
||||
testImplementation dependenciesList.kotlinLib
|
||||
testImplementation dependenciesList.commonsIO
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion androidVersions.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion androidVersions.minSdkVersion
|
||||
targetSdkVersion androidVersions.targetSdkVersion
|
||||
buildConfigField "String", "GIT_REVISION_SHORT", String.format("\"%s\"", getGitRevision())
|
||||
buildConfigField "String", "MAPBOX_SDK_IDENTIFIER", String.format("\"%s\"", "mapbox-maps-android")
|
||||
buildConfigField "String", "MAPBOX_SDK_VERSION", String.format("\"%s\"", project.VERSION_NAME)
|
||||
buildConfigField "String", "MAPBOX_VERSION_STRING", String.format("\"Mapbox/%s\"", project.VERSION_NAME)
|
||||
buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT", String.format("\"mapbox-maps-android/%s\"", project.VERSION_NAME)
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
// build native libraries
|
||||
List nativeTargets = ["mapbox-gl"]
|
||||
if (project.hasProperty("mapbox.with_test")) {
|
||||
nativeTargets.add("mbgl-test")
|
||||
}
|
||||
if (project.hasProperty("mapbox.with_benchmark")) {
|
||||
nativeTargets.add("mbgl-benchmark")
|
||||
}
|
||||
nativeBuild(nativeTargets)
|
||||
|
||||
// avoid naming conflicts, force usage of prefix
|
||||
resourcePrefix 'mapbox_'
|
||||
|
||||
sourceSets {
|
||||
// limit amount of exposed library resources
|
||||
main.res.srcDirs += 'src/main/res-public'
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'MissingTranslation', 'TypographyQuotes', 'ObsoleteLintCustomCheck', 'MissingPermission', 'WrongThreadInterprocedural'
|
||||
checkAllWarnings true
|
||||
warningsAsErrors false
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests {
|
||||
returnDefaultValues true
|
||||
|
||||
// Roboelectric 4.0 required config
|
||||
// http://robolectric.org/migrating/#migrating-to-40
|
||||
includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
testCoverageEnabled true
|
||||
jniDebuggable true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
licenseReport {
|
||||
generateHtmlReport = false
|
||||
generateJsonReport = true
|
||||
copyHtmlReportToAssets = false
|
||||
copyJsonReportToAssets = false
|
||||
}
|
||||
|
||||
def static getGitRevision() {
|
||||
def cmd = "git rev-parse --short HEAD"
|
||||
def proc = cmd.execute()
|
||||
def ref = proc.text.trim()
|
||||
return ref
|
||||
}
|
||||
|
||||
configurations {
|
||||
all*.exclude group: 'commons-logging', module: 'commons-logging'
|
||||
all*.exclude group: 'commons-collections', module: 'commons-collections'
|
||||
}
|
||||
apply from: "${rootDir}/gradle/gradle-javadoc.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-checkstyle.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-dependencies-graph.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-update-vendor-modules.gradle"
|
||||
apply from: "${rootDir}/gradle/android-nitpick.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-gitpackages.gradle"
|
||||
apply from: "${rootDir}/gradle/jacoco-report.gradle"
|
||||
9
platform/android/MapboxGLAndroidSDK/gradle.properties
Normal file
9
platform/android/MapboxGLAndroidSDK/gradle.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
VERSION_NAME=9.1.0-SNAPSHOT
|
||||
|
||||
# Only build native dependencies for the current ABI
|
||||
# See https://code.google.com/p/android/issues/detail?id=221098#c20
|
||||
android.buildOnlyTargetAbi=true
|
||||
|
||||
# Roboelectric 4.0 required config for < Android Studio v3.3.0
|
||||
# http://robolectric.org/migrating/#migrating-to-40
|
||||
android.enableUnitTestBinaryResources=true
|
||||
7
platform/android/MapboxGLAndroidSDK/lint.xml
Normal file
7
platform/android/MapboxGLAndroidSDK/lint.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint>
|
||||
<!-- Ignore errors caused by OkHTTP -->
|
||||
<issue id="InvalidPackage" severity="ignore">
|
||||
<ignore path="*/okio-1.2.0.jar" />
|
||||
</issue>
|
||||
</lint>
|
||||
44
platform/android/MapboxGLAndroidSDK/proguard-rules.pro
vendored
Normal file
44
platform/android/MapboxGLAndroidSDK/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ../sdk/tools/proguard/proguard-android.txt,
|
||||
# contents of this file will be appended into proguard-android.txt
|
||||
-keepattributes Signature, *Annotation*, EnclosingMethod
|
||||
|
||||
# Reflection on classes from native code
|
||||
-keep class com.google.gson.JsonArray { *; }
|
||||
-keep class com.google.gson.JsonElement { *; }
|
||||
-keep class com.google.gson.JsonObject { *; }
|
||||
-keep class com.google.gson.JsonPrimitive { *; }
|
||||
-dontnote com.google.gson.**
|
||||
|
||||
# dontnote for keeps the entry point x but not the descriptor class y
|
||||
-dontnote com.mapbox.mapboxsdk.maps.MapboxMap$OnFpsChangedListener
|
||||
-dontnote com.mapbox.mapboxsdk.style.layers.PropertyValue
|
||||
-dontnote com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
-dontnote com.mapbox.mapboxsdk.maps.MapboxMapOptions
|
||||
-dontnote com.mapbox.mapboxsdk.log.LoggerDefinition
|
||||
-dontnote com.mapbox.android.core.location.LocationEnginePriority
|
||||
|
||||
# config for okhttp 3.11.0, https://github.com/square/okhttp/pull/3354
|
||||
-dontwarn javax.annotation.**
|
||||
-dontnote okhttp3.internal.**
|
||||
-dontwarn org.codehaus.**
|
||||
|
||||
# config for mapbox-sdk-geojson:3.0.1
|
||||
-keep class com.mapbox.geojson.** { *; }
|
||||
-dontwarn com.google.auto.value.**
|
||||
|
||||
# config for telemetry events
|
||||
-keep class com.mapbox.mapboxsdk.module.telemetry.** { *; }
|
||||
|
||||
# config for additional notes
|
||||
-dontnote org.robolectric.Robolectric
|
||||
-dontnote libcore.io.Memory
|
||||
-dontnote com.google.protobuf.**
|
||||
-dontnote android.net.**
|
||||
-dontnote org.apache.http.**
|
||||
|
||||
# config for mapbox-sdk-services
|
||||
# while we don't include this dependency directly
|
||||
# a large amount of users combine it with our SDK
|
||||
# we aren't able to provide a proguard config in that project (jar vs aar)
|
||||
-dontwarn com.sun.xml.internal.ws.spi.db.*
|
||||
212
platform/android/MapboxGLAndroidSDK/src/cpp/CMakeLists.txt
Normal file
212
platform/android/MapboxGLAndroidSDK/src/cpp/CMakeLists.txt
Normal file
@@ -0,0 +1,212 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
add_subdirectory(../../../../../
|
||||
../../../../../${ANDROID_ABI})
|
||||
|
||||
target_compile_options(mbgl-compiler-options INTERFACE -frtti)
|
||||
|
||||
add_library(mapbox-gl SHARED
|
||||
${PROJECT_SOURCE_DIR}/main.cpp
|
||||
${PROJECT_SOURCE_DIR}/jni_native.cpp
|
||||
${PROJECT_SOURCE_DIR}/jni_native.hpp
|
||||
${PROJECT_SOURCE_DIR}/file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/file_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/http_file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/collator.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/collator_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/number_format.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/number_format_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/logger.cpp
|
||||
${PROJECT_SOURCE_DIR}/logger.hpp
|
||||
${PROJECT_SOURCE_DIR}/logging_android.cpp
|
||||
${PROJECT_SOURCE_DIR}/text/local_glyph_rasterizer.cpp
|
||||
${PROJECT_SOURCE_DIR}/text/local_glyph_rasterizer_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_backend.cpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_backend.hpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_frontend.cpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_frontend.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/marker.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/marker.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/multi_point.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polyline.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polyline.hpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager_file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager_file_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/connectivity_listener.cpp
|
||||
${PROJECT_SOURCE_DIR}/connectivity_listener.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/color.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/color.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/constant.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/constant.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/conversion.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature_collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature_collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry_collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry_collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/line_string.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/line_string.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_line_string.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_line_string.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_point.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_point.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/point.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/point.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_bounds.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_bounds.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_quad.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_quad.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/projected_meters.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/projected_meters.hpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/pointf.cpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/pointf.hpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/rectf.cpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/rectf.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_array.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_array.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_element.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_element.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_object.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_object.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_primitive.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_primitive.hpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.cpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.cpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.hpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.cpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.cpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.hpp
|
||||
${PROJECT_SOURCE_DIR}/mapbox.cpp
|
||||
${PROJECT_SOURCE_DIR}/mapbox.hpp
|
||||
${PROJECT_SOURCE_DIR}/map/camera_position.cpp
|
||||
${PROJECT_SOURCE_DIR}/map/camera_position.hpp
|
||||
${PROJECT_SOURCE_DIR}/map/image.cpp
|
||||
${PROJECT_SOURCE_DIR}/map/image.hpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer.cpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer.hpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer_runnable.cpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer_runnable.hpp
|
||||
${PROJECT_SOURCE_DIR}/native_map_view.cpp
|
||||
${PROJECT_SOURCE_DIR}/native_map_view.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_definition.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_definition.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_error.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_error.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_status.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_status.hpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshot.cpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshot.hpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshotter.cpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshotter.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/android_conversion.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/filter.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/filter.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/position.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/position.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/property_expression.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/property_value.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/transition_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/url_or_tileset.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/url_or_tileset.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted_section.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted_section.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/background_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/background_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/heatmap_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/heatmap_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/hillshade_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/hillshade_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/line_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/line_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/raster_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/raster_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/symbol_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/symbol_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/location_indicator_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/location_indicator_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/light.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/light.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/position.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/position.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/custom_geometry_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/custom_geometry_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/geojson_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/geojson_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/image_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/image_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_dem_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_dem_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/unknown_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/unknown_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/vector_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/vector_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/transition_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.hpp)
|
||||
|
||||
target_include_directories(
|
||||
mapbox-gl
|
||||
PRIVATE ${PROJECT_SOURCE_DIR}
|
||||
../../../../../src
|
||||
../../../src
|
||||
../../../../default/include)
|
||||
|
||||
target_compile_options(mapbox-gl
|
||||
PRIVATE $<$<CONFIG:Release>:-Oz>
|
||||
$<$<CONFIG:Release>:-Qunused-arguments>
|
||||
$<$<CONFIG:Release>:-flto>
|
||||
$<$<CONFIG:Release>:-fvisibility=hidden>
|
||||
$<$<CONFIG:Release>:-fvisibility-inlines-hidden>)
|
||||
|
||||
target_link_libraries(mapbox-gl
|
||||
PRIVATE $<$<CONFIG:Release>:-Oz>
|
||||
$<$<CONFIG:Release>:-Wl,--icf=all>
|
||||
$<$<CONFIG:Release>:-Wl,--gc-sections>
|
||||
$<$<CONFIG:Release>:-flto>
|
||||
$<$<CONFIG:Release>:-fuse-ld=gold>
|
||||
Mapbox::Base::jni.hpp
|
||||
mbgl-core
|
||||
mbgl-vendor-unique_resource)
|
||||
|
||||
install(TARGETS mapbox-gl LIBRARY DESTINATION lib)
|
||||
67
platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_backend.cpp
Executable file
67
platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_backend.cpp
Executable file
@@ -0,0 +1,67 @@
|
||||
#include "android_renderer_backend.hpp"
|
||||
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/gl/renderable_resource.hpp>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidGLRenderableResource final : public mbgl::gl::RenderableResource {
|
||||
public:
|
||||
AndroidGLRenderableResource(AndroidRendererBackend& backend_) : backend(backend_) {
|
||||
}
|
||||
|
||||
void bind() override {
|
||||
assert(gfx::BackendScope::exists());
|
||||
backend.setFramebufferBinding(0);
|
||||
backend.setViewport(0, 0, backend.getSize());
|
||||
}
|
||||
|
||||
private:
|
||||
AndroidRendererBackend& backend;
|
||||
};
|
||||
|
||||
AndroidRendererBackend::AndroidRendererBackend()
|
||||
: gl::RendererBackend(gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable({ 64, 64 }, std::make_unique<AndroidGLRenderableResource>(*this)) {
|
||||
}
|
||||
|
||||
AndroidRendererBackend::~AndroidRendererBackend() = default;
|
||||
|
||||
gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) {
|
||||
assert(gfx::BackendScope::exists());
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::updateViewPort() {
|
||||
assert(gfx::BackendScope::exists());
|
||||
setViewport(0, 0, size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::resizeFramebuffer(int width, int height) {
|
||||
size = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
|
||||
}
|
||||
|
||||
PremultipliedImage AndroidRendererBackend::readFramebuffer() {
|
||||
assert(gfx::BackendScope::exists());
|
||||
return gl::RendererBackend::readFramebuffer(size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::updateAssumedState() {
|
||||
assumeFramebufferBinding(0);
|
||||
assumeViewport(0, 0, size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::markContextLost() {
|
||||
if (context) {
|
||||
getContext<gl::Context>().setCleanupOnDestruction(false);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namspace mbgl
|
||||
43
platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_backend.hpp
Executable file
43
platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_backend.hpp
Executable file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/gl/renderer_backend.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererBackend : public gl::RendererBackend, public mbgl::gfx::Renderable {
|
||||
public:
|
||||
AndroidRendererBackend();
|
||||
~AndroidRendererBackend() override;
|
||||
|
||||
void updateViewPort();
|
||||
|
||||
// Ensures the current context is not cleaned up when destroyed
|
||||
void markContextLost();
|
||||
|
||||
void resizeFramebuffer(int width, int height);
|
||||
PremultipliedImage readFramebuffer();
|
||||
|
||||
// mbgl::gfx::RendererBackend implementation
|
||||
public:
|
||||
mbgl::gfx::Renderable& getDefaultRenderable() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void activate() override {
|
||||
// no-op
|
||||
}
|
||||
void deactivate() override {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// mbgl::gl::RendererBackend implementation
|
||||
protected:
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
|
||||
void updateAssumedState() override;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,143 @@
|
||||
#include "android_renderer_frontend.hpp"
|
||||
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/renderer/renderer_observer.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include "android_renderer_backend.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// Forwards RendererObserver signals to the given
|
||||
// Delegate RendererObserver on the given RunLoop
|
||||
class ForwardingRendererObserver : public RendererObserver {
|
||||
public:
|
||||
ForwardingRendererObserver(util::RunLoop& mapRunLoop, RendererObserver& delegate_)
|
||||
: mailbox(std::make_shared<Mailbox>(mapRunLoop))
|
||||
, delegate(delegate_, mailbox) {
|
||||
}
|
||||
|
||||
~ForwardingRendererObserver() {
|
||||
mailbox->close();
|
||||
}
|
||||
|
||||
void onInvalidate() override {
|
||||
delegate.invoke(&RendererObserver::onInvalidate);
|
||||
}
|
||||
|
||||
void onResourceError(std::exception_ptr err) override {
|
||||
delegate.invoke(&RendererObserver::onResourceError, err);
|
||||
}
|
||||
|
||||
void onWillStartRenderingMap() override {
|
||||
delegate.invoke(&RendererObserver::onWillStartRenderingMap);
|
||||
}
|
||||
|
||||
void onWillStartRenderingFrame() override {
|
||||
delegate.invoke(&RendererObserver::onWillStartRenderingFrame);
|
||||
}
|
||||
|
||||
void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded, bool placementChanged) override {
|
||||
delegate.invoke(&RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded, placementChanged);
|
||||
}
|
||||
|
||||
void onDidFinishRenderingMap() override {
|
||||
delegate.invoke(&RendererObserver::onDidFinishRenderingMap);
|
||||
}
|
||||
|
||||
void onStyleImageMissing(const std::string& id, const 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
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/actor.hpp>
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
#include <mbgl/renderer/renderer_frontend.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include "map_renderer.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class RenderedQueryOptions;
|
||||
class SourceQueryOptions;
|
||||
|
||||
namespace util {
|
||||
|
||||
class AsyncTask;
|
||||
|
||||
} // namespace util
|
||||
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererFrontend : public RendererFrontend {
|
||||
public:
|
||||
|
||||
AndroidRendererFrontend(MapRenderer&);
|
||||
~AndroidRendererFrontend() override;
|
||||
|
||||
void reset() override;
|
||||
void setObserver(RendererObserver&) override;
|
||||
|
||||
void update(std::shared_ptr<UpdateParameters>) override;
|
||||
|
||||
// Feature querying
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions&) const;
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions&) const;
|
||||
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
|
||||
AnnotationIDs queryPointAnnotations(const ScreenBox& box) const;
|
||||
AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
|
||||
|
||||
|
||||
// Feature extension query
|
||||
FeatureExtensionValue
|
||||
queryFeatureExtensions(const std::string& sourceID,
|
||||
const Feature& feature,
|
||||
const std::string& extension,
|
||||
const std::string& extensionField,
|
||||
const optional<std::map<std::string, mbgl::Value>>& args) const;
|
||||
|
||||
// Memory
|
||||
void reduceMemoryUse();
|
||||
|
||||
private:
|
||||
MapRenderer& mapRenderer;
|
||||
util::RunLoop* mapRunLoop;
|
||||
std::unique_ptr<util::AsyncTask> updateAsyncTask;
|
||||
std::shared_ptr<UpdateParameters> updateParams;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "marker.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
|
||||
static auto& javaClass = jni::Class<Marker>::Singleton(env);
|
||||
static auto positionField = javaClass.GetField<jni::Object<LatLng>>(env, "position");
|
||||
return LatLng::getGeometry(env, marker.Get(env, positionField));
|
||||
}
|
||||
|
||||
std::string Marker::getIconId(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
|
||||
static auto& javaClass = jni::Class<Marker>::Singleton(env);
|
||||
static auto iconIdField = javaClass.GetField<jni::String>(env, "iconId");
|
||||
return jni::Make<std::string>(env, marker.Get(env, iconIdField));
|
||||
}
|
||||
|
||||
void Marker::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Marker>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Marker : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; };
|
||||
|
||||
static mbgl::Point<double> getPosition(jni::JNIEnv&, const jni::Object<Marker>&);
|
||||
|
||||
static std::string getIconId(jni::JNIEnv&, const jni::Object<Marker>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class MultiPoint : protected mbgl::util::noncopyable {
|
||||
|
||||
protected:
|
||||
|
||||
template <class Geometry>
|
||||
static Geometry toGeometry(JNIEnv& env, const jni::Object<java::util::List>& pointsList) {
|
||||
auto jarray = java::util::List::toArray<LatLng>(env, pointsList);
|
||||
|
||||
std::size_t size = jarray.Length(env);
|
||||
|
||||
Geometry geometry;
|
||||
geometry.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
geometry.push_back(LatLng::getGeometry(env, jarray.Get(env, i)));
|
||||
}
|
||||
|
||||
return geometry;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "polygon.hpp"
|
||||
|
||||
#include "../conversion/color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, const jni::Object<Polygon>& polygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
|
||||
static auto holes = javaClass.GetField<jni::Object<java::util::List>>(env, "holes");
|
||||
static auto alpha = javaClass.GetField<float>(env, "alpha");
|
||||
static auto fillColor = javaClass.GetField<int>(env, "fillColor");
|
||||
static auto strokeColor = javaClass.GetField<int>(env, "strokeColor");
|
||||
|
||||
mbgl::Polygon<double> geometry {
|
||||
MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, polygon.Get(env, points))
|
||||
};
|
||||
|
||||
auto jHoleListsArray = java::util::List::toArray<java::util::List>(env, polygon.Get(env, holes));
|
||||
|
||||
std::size_t jHoleListsSize = jHoleListsArray.Length(env);
|
||||
for (std::size_t i = 0; i < jHoleListsSize; i++) {
|
||||
geometry.push_back(MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, jHoleListsArray.Get(env, i)));
|
||||
}
|
||||
|
||||
mbgl::FillAnnotation annotation { geometry };
|
||||
annotation.opacity = polygon.Get(env, alpha);
|
||||
annotation.color = *conversion::convert<mbgl::Color>(env, polygon.Get(env, fillColor));
|
||||
annotation.outlineColor = *conversion::convert<mbgl::Color>(env, polygon.Get(env, strokeColor));
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
void Polygon::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Polygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
|
||||
#include "multi_point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Polygon : private MultiPoint {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; };
|
||||
|
||||
static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "polyline.hpp"
|
||||
|
||||
#include "../conversion/color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, const jni::Object<Polyline>& polyline) {
|
||||
static auto& javaClass = jni::Class<Polyline>::Singleton(env);
|
||||
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
|
||||
static auto alpha = javaClass.GetField<float>(env, "alpha");
|
||||
static auto color = javaClass.GetField<int>(env, "color");
|
||||
static auto width = javaClass.GetField<float>(env, "width");
|
||||
|
||||
mbgl::LineAnnotation annotation {
|
||||
MultiPoint::toGeometry<mbgl::LineString<double>>(env, polyline.Get(env, points))
|
||||
};
|
||||
|
||||
annotation.opacity = polyline.Get(env, alpha);
|
||||
annotation.color = *conversion::convert<mbgl::Color>(env, polyline.Get(env, color));
|
||||
annotation.width = polyline.Get(env, width);
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
void Polyline::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Polyline>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
|
||||
#include "multi_point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Polyline : private MultiPoint {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; };
|
||||
|
||||
static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polyline>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AssetManager {
|
||||
public:
|
||||
static constexpr auto Name() {
|
||||
return "android/content/res/AssetManager";
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "asset_manager_file_source.hpp"
|
||||
|
||||
#include <mbgl/platform/settings.hpp>
|
||||
#include <mbgl/storage/file_source_request.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/url.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include <android/asset_manager.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class AssetManagerFileSource::Impl {
|
||||
public:
|
||||
Impl(ActorRef<Impl>, AAssetManager* assetManager_) : assetManager(assetManager_) {
|
||||
}
|
||||
|
||||
void request(const std::string& url, ActorRef<FileSourceRequest> req) {
|
||||
// Note: AssetManager already prepends "assets" to the filename.
|
||||
const std::string path = mbgl::util::percentDecode(url.substr(8));
|
||||
|
||||
Response response;
|
||||
|
||||
if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) {
|
||||
response.data = std::make_shared<std::string>(
|
||||
reinterpret_cast<const char*>(AAsset_getBuffer(asset)), AAsset_getLength64(asset));
|
||||
AAsset_close(asset);
|
||||
} else {
|
||||
response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound,
|
||||
"Could not read asset");
|
||||
}
|
||||
|
||||
req.invoke(&FileSourceRequest::setResponse, response);
|
||||
}
|
||||
|
||||
private:
|
||||
AAssetManager* assetManager;
|
||||
};
|
||||
|
||||
AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env,
|
||||
const jni::Object<android::AssetManager>& assetManager_)
|
||||
: assetManager(jni::NewGlobal(env, assetManager_)),
|
||||
impl(std::make_unique<util::Thread<Impl>>(
|
||||
util::makeThreadPrioritySetter(platform::EXPERIMENTAL_THREAD_PRIORITY_FILE),
|
||||
"AssetManagerFileSource",
|
||||
AAssetManager_fromJava(&env, jni::Unwrap(assetManager.get())))) {}
|
||||
|
||||
AssetManagerFileSource::~AssetManagerFileSource() = default;
|
||||
|
||||
std::unique_ptr<AsyncRequest> AssetManagerFileSource::request(const Resource& resource, Callback callback) {
|
||||
auto req = std::make_unique<FileSourceRequest>(std::move(callback));
|
||||
|
||||
impl->actor().invoke(&Impl::request, resource.url, req->actor());
|
||||
|
||||
return std::move(req);
|
||||
}
|
||||
|
||||
bool AssetManagerFileSource::canRequest(const Resource& resource) const {
|
||||
return 0 == resource.url.rfind(mbgl::util::ASSET_PROTOCOL, 0);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace util {
|
||||
template <typename T> class Thread;
|
||||
} // namespace util
|
||||
|
||||
class AssetManagerFileSource : public FileSource {
|
||||
public:
|
||||
AssetManagerFileSource(jni::JNIEnv&, const jni::Object<android::AssetManager>&);
|
||||
~AssetManagerFileSource() override;
|
||||
|
||||
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
|
||||
bool canRequest(const Resource&) const override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
jni::Global<jni::Object<android::AssetManager>> assetManager;
|
||||
std::unique_ptr<util::Thread<Impl>> impl;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "connectivity_listener.hpp"
|
||||
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Invoked when the construction is initiated from the jvm
|
||||
*/
|
||||
ConnectivityListener::ConnectivityListener(jni::JNIEnv&) {}
|
||||
|
||||
ConnectivityListener::~ConnectivityListener() {}
|
||||
|
||||
void ConnectivityListener::onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean connected) {
|
||||
NetworkStatus::Set(connected ? NetworkStatus::Status::Online : NetworkStatus::Status::Offline);
|
||||
}
|
||||
|
||||
void ConnectivityListener::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<ConnectivityListener>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<ConnectivityListener>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
std::make_unique<ConnectivityListener, JNIEnv&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&ConnectivityListener::onConnectivityStateChanged, "nativeOnConnectivityStateChanged")
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class ConnectivityListener : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/net/NativeConnectivityListener"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
/*
|
||||
* Called when a Java object was created from the jvm side
|
||||
*/
|
||||
ConnectivityListener(jni::JNIEnv&);
|
||||
|
||||
~ConnectivityListener();
|
||||
|
||||
void onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean);
|
||||
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "collection.hpp"
|
||||
#include "constant.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array) {
|
||||
std::size_t len = array.Length(env);
|
||||
std::vector<std::string> vector;
|
||||
vector.reserve(len);
|
||||
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
vector.push_back(jni::Make<std::string>(env, array.Get(env, i)));
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>& vector) {
|
||||
auto result = jni::Array<jni::String>::New(env, vector.size());
|
||||
|
||||
for (std::size_t i = 0; i < vector.size(); i++) {
|
||||
result.Set(env, i, jni::Make<jni::String>(env, vector.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array);
|
||||
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>&);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
Result<mbgl::Color> Converter<mbgl::Color, int>::operator()(jni::JNIEnv&, const int& color) const {
|
||||
float r = (color >> 16) & 0xFF;
|
||||
float g = (color >> 8) & 0xFF;
|
||||
float b = (color) & 0xFF;
|
||||
float a = (color >> 24) & 0xFF;
|
||||
return { mbgl::Color( r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f ) };
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
template <>
|
||||
struct Converter<mbgl::Color, int> {
|
||||
Result<mbgl::Color> operator()(jni::JNIEnv&, const int& color) const;
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,76 @@
|
||||
#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<>>, std::vector<double>>::operator()(jni::JNIEnv& env, const std::vector<double>& value) const {
|
||||
auto result = jni::Array<jni::Double>::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());
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, mbgl::style::Rotation>::operator()(jni::JNIEnv& env, const mbgl::style::Rotation& value) const {
|
||||
return jni::Box(env, value.getAngle());
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,132 @@
|
||||
#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>
|
||||
#include <mbgl/style/rotation.hpp>
|
||||
|
||||
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 <std::size_t N>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::array<double, N>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::array<double, N>& value) const {
|
||||
std::vector<double> v;
|
||||
for (const double& id : value) {
|
||||
v.push_back(id);
|
||||
}
|
||||
return convert<jni::Local<jni::Object<>>, std::vector<double>>(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 <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<double>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<double>& 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;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, mbgl::style::Rotation> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const mbgl::style::Rotation& value) const;
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/variant.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
struct Error { std::string message; };
|
||||
|
||||
template <class T>
|
||||
class Result : private variant<T, Error> {
|
||||
public:
|
||||
using variant<T, Error>::variant;
|
||||
|
||||
explicit operator bool() const {
|
||||
return this->template is<T>();
|
||||
}
|
||||
|
||||
T& operator*() {
|
||||
assert(this->template is<T>());
|
||||
return this->template get<T>();
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
assert(this->template is<T>());
|
||||
return this->template get<T>();
|
||||
}
|
||||
|
||||
const Error& error() const {
|
||||
assert(this->template is<Error>());
|
||||
return this->template get<Error>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class V, class Enable = void>
|
||||
struct Converter;
|
||||
|
||||
template <class T, typename V, class...Args>
|
||||
Result<T> convert(jni::JNIEnv& env, const V& value, Args&&...args) {
|
||||
return Converter<T, V>()(env, value, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
243
platform/android/MapboxGLAndroidSDK/src/cpp/file_source.cpp
Normal file
243
platform/android/MapboxGLAndroidSDK/src/cpp/file_source.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
#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)
|
||||
:activationCounter( optional<int>(1)) {
|
||||
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;
|
||||
}
|
||||
|
||||
activationCounter.value()++;
|
||||
if (activationCounter == 1) {
|
||||
resourceLoader->resume();
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::pause(jni::JNIEnv&) {
|
||||
if (!resourceLoader) {
|
||||
return;
|
||||
}
|
||||
|
||||
activationCounter.value()--;
|
||||
if (activationCounter == 0) {
|
||||
resourceLoader->pause();
|
||||
}
|
||||
}
|
||||
|
||||
jni::jboolean FileSource::isResumed(jni::JNIEnv &) {
|
||||
return (jboolean) (activationCounter > 0);
|
||||
}
|
||||
|
||||
FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
|
||||
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
|
||||
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
|
||||
return reinterpret_cast<FileSource *>(jFileSource.Get(env, field));
|
||||
}
|
||||
|
||||
mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource>& jFileSource) {
|
||||
FileSource* fileSource = FileSource::getNativePeer(env, jFileSource);
|
||||
// Core could be compiled without support for any sources.
|
||||
if (fileSource) {
|
||||
return fileSource->resourceOptions.clone();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// FileSource::ResourcesCachePathChangeCallback //
|
||||
|
||||
void FileSource::ResourcesCachePathChangeCallback::onSuccess(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
|
||||
const jni::String& path) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onSuccess");
|
||||
|
||||
callback.Call(env, method, path);
|
||||
}
|
||||
|
||||
void FileSource::ResourcesCachePathChangeCallback::onError(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
|
||||
const jni::String& message) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, message);
|
||||
}
|
||||
|
||||
void FileSource::registerNative(jni::JNIEnv& env) {
|
||||
// Ensure the classes are cached. If they're requested for the
|
||||
// first time on a background thread, Android's class loader heuristics will fail.
|
||||
// https://developer.android.com/training/articles/perf-jni#faq_FindClass
|
||||
jni::Class<ResourceTransformCallback>::Singleton(env);
|
||||
jni::Class<ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
|
||||
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<FileSource>(env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
jni::MakePeer<FileSource, const jni::String&, const jni::String&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&FileSource::getAccessToken, "getAccessToken"),
|
||||
METHOD(&FileSource::setAccessToken, "setAccessToken"),
|
||||
METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"),
|
||||
METHOD(&FileSource::setResourceTransform, "setResourceTransform"),
|
||||
METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"),
|
||||
METHOD(&FileSource::resume, "activate"),
|
||||
METHOD(&FileSource::pause, "deactivate"),
|
||||
METHOD(&FileSource::isResumed, "isActivated"));
|
||||
}
|
||||
|
||||
|
||||
// FileSource::ResourceTransformCallback //
|
||||
|
||||
std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& callback, int kind, std::string url_) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourceTransformCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String (jni::jint, jni::String)>(env, "onURL");
|
||||
|
||||
return jni::Make<std::string>(env,
|
||||
callback.Call(env, method, kind,
|
||||
jni::Make<jni::String>(env, url_)));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
83
platform/android/MapboxGLAndroidSDK/src/cpp/file_source.hpp
Normal file
83
platform/android/MapboxGLAndroidSDK/src/cpp/file_source.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/database_file_source.hpp>
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/resource_transform.hpp>
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <typename T> class Actor;
|
||||
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Peer class for the Android FileSource holder. Ensures that a single core FileSource
|
||||
* of a ResourceLoader type is used.
|
||||
*/
|
||||
class FileSource {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource"; };
|
||||
|
||||
struct ResourceTransformCallback {
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourceTransformCallback"; }
|
||||
|
||||
static std::string onURL(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&, int, std::string);
|
||||
};
|
||||
|
||||
struct ResourcesCachePathChangeCallback {
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourcesCachePathChangeCallback";}
|
||||
|
||||
static void onSuccess(jni::JNIEnv&,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
|
||||
const jni::String&);
|
||||
|
||||
static void onError(jni::JNIEnv&,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
|
||||
const jni::String&);
|
||||
};
|
||||
|
||||
FileSource(jni::JNIEnv&, const jni::String&, const jni::String&);
|
||||
|
||||
~FileSource();
|
||||
|
||||
jni::Local<jni::String> getAccessToken(jni::JNIEnv&);
|
||||
|
||||
void setAccessToken(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
void setAPIBaseUrl(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
void setResourceTransform(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&);
|
||||
|
||||
void setResourceCachePath(jni::JNIEnv&, const jni::String&, const jni::Object<FileSource::ResourcesCachePathChangeCallback>&);
|
||||
|
||||
void resume(jni::JNIEnv&);
|
||||
|
||||
void pause(jni::JNIEnv&);
|
||||
|
||||
jni::jboolean isResumed(jni::JNIEnv&);
|
||||
|
||||
static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
|
||||
static mbgl::ResourceOptions getSharedResourceOptions(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
private:
|
||||
const std::string DATABASE_FILE = "/mbgl-offline.db";
|
||||
optional<int> activationCounter;
|
||||
mbgl::ResourceOptions resourceOptions;
|
||||
std::unique_ptr<Actor<ResourceTransform::TransformCallback>> resourceTransform;
|
||||
std::function<void()> pathChangeCallback;
|
||||
std::shared_ptr<mbgl::DatabaseFileSource> databaseSource;
|
||||
std::shared_ptr<mbgl::FileSource> onlineSource;
|
||||
std::shared_ptr<mbgl::FileSource> resourceLoader;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "feature.hpp"
|
||||
#include "geometry.hpp"
|
||||
#include "../gson/json_object.hpp"
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
using namespace gson;
|
||||
|
||||
mbgl::GeoJSONFeature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFeature) {
|
||||
static auto& javaClass = jni::Class<Feature>::Singleton(env);
|
||||
static auto id = javaClass.GetMethod<jni::String ()>(env, "id");
|
||||
static auto geometry = javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry");
|
||||
static auto properties = javaClass.GetMethod<jni::Object<gson::JsonObject> ()>(env, "properties");
|
||||
|
||||
auto jId = jFeature.Call(env, id);
|
||||
|
||||
using mbid = mapbox::feature::identifier;
|
||||
|
||||
return mbgl::GeoJSONFeature{Geometry::convert(env, jFeature.Call(env, geometry)),
|
||||
JsonObject::convert(env, jFeature.Call(env, properties)),
|
||||
jId ? mbid{jni::Make<std::string>(env, jId)} : mbid{mapbox::feature::null_value}};
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn feature identifier into std::string
|
||||
*/
|
||||
class FeatureIdVisitor {
|
||||
public:
|
||||
template<class T>
|
||||
std::string operator()(const T& i) const {
|
||||
return util::toString(i);
|
||||
}
|
||||
|
||||
std::string operator()(const std::string& i) const {
|
||||
return i;
|
||||
}
|
||||
|
||||
std::string operator()(const std::nullptr_t&) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string operator()(const mapbox::feature::null_value_t&) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::GeoJSONFeature& value) {
|
||||
static auto& javaClass = jni::Class<Feature>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<JsonObject>, jni::String)>(env, "fromGeometry");
|
||||
|
||||
return javaClass.Call(env, method,
|
||||
Geometry::New(env, value.geometry),
|
||||
JsonObject::New(env, value.properties),
|
||||
jni::Make<jni::String>(env, value.id.is<mbgl::NullValue>() ? std::string {} : value.id.match(FeatureIdVisitor())));
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) {
|
||||
auto features = jni::Array<jni::Object<Feature>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
features.Set(env, i, convertFeature(env, static_cast<mbgl::GeoJSONFeature>(value.at(i))));
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env,
|
||||
const std::vector<mbgl::GeoJSONFeature>& value) {
|
||||
auto features = jni::Array<jni::Object<Feature>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
features.Set(env, i, convertFeature(env, value.at(i)));
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
void Feature::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Feature>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/feature.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Feature {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Feature"; };
|
||||
|
||||
static mbgl::GeoJSONFeature convert(jni::JNIEnv&, const jni::Object<Feature>&);
|
||||
static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::Feature>&);
|
||||
static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::GeoJSONFeature>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "feature_collection.hpp"
|
||||
|
||||
#include "feature.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) {
|
||||
auto collection = mbgl::FeatureCollection();
|
||||
|
||||
if (jCollection) {
|
||||
auto jFeatureList = FeatureCollection::features(env, jCollection);
|
||||
auto jFeatures = java::util::List::toArray<Feature>(env, jFeatureList);
|
||||
auto size = size_t(jFeatures.Length(env));
|
||||
collection.reserve(size);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
collection.push_back(Feature::convert(env, jFeatures.Get(env, i)));
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> FeatureCollection::features(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) {
|
||||
static auto& javaClass = jni::Class<FeatureCollection>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "features");
|
||||
return jCollection.Call(env, method);
|
||||
}
|
||||
|
||||
void FeatureCollection::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<FeatureCollection>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class FeatureCollection {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/FeatureCollection"; };
|
||||
|
||||
static mbgl::FeatureCollection convert(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> features(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include "point.hpp"
|
||||
#include "multi_point.hpp"
|
||||
#include "line_string.hpp"
|
||||
#include "multi_line_string.hpp"
|
||||
#include "polygon.hpp"
|
||||
#include "multi_polygon.hpp"
|
||||
#include "geometry_collection.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
/**
|
||||
* Turn mapbox::geometry type into Java GeoJson Geometries
|
||||
*/
|
||||
class GeometryEvaluator {
|
||||
public:
|
||||
|
||||
jni::JNIEnv& env;
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::EmptyGeometry &) const {
|
||||
// FIXME: mapbox-java needs to have its own Empty type.
|
||||
return GeometryCollection::New(env, {});
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Point<double> &geometry) const {
|
||||
return Point::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::LineString<double> &geometry) const {
|
||||
return LineString::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiLineString<double> &geometry) const {
|
||||
return MultiLineString::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPoint<double> &geometry) const {
|
||||
return MultiPoint::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Polygon<double> &geometry) const {
|
||||
return Polygon::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPolygon<double> &geometry) const {
|
||||
return MultiPolygon::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const {
|
||||
return GeometryCollection::New(env, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
jni::Local<jni::Object<Geometry>> Geometry::New(jni::JNIEnv& env, mbgl::Geometry<double> geometry) {
|
||||
GeometryEvaluator evaluator { env } ;
|
||||
return mbgl::Geometry<double>::visit(geometry, evaluator);
|
||||
}
|
||||
|
||||
mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) {
|
||||
auto type = Geometry::getType(env, jGeometry);
|
||||
if (type == Point::Type()) {
|
||||
return { Point::convert(env, jni::Cast(env, jni::Class<Point>::Singleton(env), jGeometry)) };
|
||||
} else if (type == MultiPoint::Type()) {
|
||||
return { MultiPoint::convert(env, jni::Cast(env, jni::Class<MultiPoint>::Singleton(env), jGeometry)) };
|
||||
} else if (type == LineString::Type()) {
|
||||
return { LineString::convert(env, jni::Cast(env, jni::Class<LineString>::Singleton(env), jGeometry)) };
|
||||
} else if (type == MultiLineString::Type()) {
|
||||
return { MultiLineString::convert(env, jni::Cast(env, jni::Class<MultiLineString>::Singleton(env), jGeometry)) };
|
||||
} else if (type == Polygon::Type()) {
|
||||
return { Polygon::convert(env, jni::Cast(env, jni::Class<Polygon>::Singleton(env), jGeometry)) };
|
||||
} else if (type == MultiPolygon::Type()) {
|
||||
return { MultiPolygon::convert(env, jni::Cast(env, jni::Class<MultiPolygon>::Singleton(env), jGeometry)) };
|
||||
} else if (type == GeometryCollection::Type()) {
|
||||
return { GeometryCollection::convert(env, jni::Cast(env, jni::Class<GeometryCollection>::Singleton(env), jGeometry)) };
|
||||
}
|
||||
|
||||
throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type);
|
||||
}
|
||||
|
||||
std::string Geometry::getType(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) {
|
||||
static auto& javaClass = jni::Class<Geometry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String ()>(env, "type");
|
||||
return jni::Make<std::string>(env, jGeometry.Call(env, method));
|
||||
}
|
||||
|
||||
void Geometry::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Geometry>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Geometry {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; };
|
||||
|
||||
static jni::Local<jni::Object<Geometry>> New(jni::JNIEnv&, mbgl::Geometry<double>);
|
||||
|
||||
static mbgl::Geometry<double> convert(jni::JNIEnv&, const jni::Object<Geometry>&);
|
||||
|
||||
static std::string getType(jni::JNIEnv&, const jni::Object<Geometry>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "geometry_collection.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<GeometryCollection>> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) {
|
||||
// Create an array of geometries
|
||||
auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size());
|
||||
|
||||
for (size_t i = 0; i < collection.size(); i++) {
|
||||
jarray.Set(env, i, Geometry::New(env, collection.at(i)));
|
||||
}
|
||||
|
||||
// create the GeometryCollection
|
||||
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection> (jni::Object<java::util::List>)>(env, "fromGeometries");
|
||||
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
|
||||
}
|
||||
|
||||
mapbox::geometry::geometry_collection<double> GeometryCollection::convert(jni::JNIEnv &env, const jni::Object<GeometryCollection>& jCollection) {
|
||||
// Get geometries
|
||||
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
|
||||
static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "geometries");
|
||||
|
||||
// Turn into array
|
||||
auto jarray = java::util::List::toArray<Geometry>(env, jCollection.Call(env, getGeometries));
|
||||
|
||||
// Convert each geometry
|
||||
mapbox::geometry::geometry_collection<double> collection{};
|
||||
|
||||
auto size = jarray.Length(env);
|
||||
for (jni::jsize i = 0; i < size; i++) {
|
||||
collection.push_back(Geometry::convert(env, jarray.Get(env, i)));
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
void GeometryCollection::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<GeometryCollection>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class GeometryCollection {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/GeometryCollection"; };
|
||||
static constexpr auto Type() { return "GeometryCollection"; };
|
||||
|
||||
static jni::Local<jni::Object<GeometryCollection>> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection<double>&);
|
||||
|
||||
static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, const jni::Object<GeometryCollection>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "line_string.hpp"
|
||||
#include "point.hpp"
|
||||
#include "util.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<LineString>> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) {
|
||||
static auto& javaClass = jni::Class<LineString>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsList(env, lineString));
|
||||
}
|
||||
|
||||
mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) {
|
||||
mapbox::geojson::line_string lineString;
|
||||
|
||||
if (jLineString) {
|
||||
lineString = LineString::convert(env, LineString::coordinates(env, jLineString));
|
||||
}
|
||||
|
||||
return lineString;
|
||||
}
|
||||
|
||||
mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<Point>*/>& jPointList) {
|
||||
mapbox::geojson::line_string lineString;
|
||||
|
||||
if (jPointList) {
|
||||
auto jPointArray = java::util::List::toArray<Point>(env, jPointList);
|
||||
auto size = jPointArray.Length(env);
|
||||
lineString.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
lineString.push_back(Point::convert(env, jPointArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return lineString;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> LineString::coordinates(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) {
|
||||
static auto& javaClass = jni::Class<LineString>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jLineString.Call(env, method);
|
||||
}
|
||||
|
||||
void LineString::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<LineString>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
|
||||
class LineString {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/LineString"; };
|
||||
static constexpr auto Type() { return "LineString"; };
|
||||
|
||||
static jni::Local<jni::Object<LineString>> New(jni::JNIEnv&, const mbgl::LineString<double>&);
|
||||
|
||||
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<LineString>&);
|
||||
|
||||
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<Point>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<LineString>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "multi_line_string.hpp"
|
||||
|
||||
#include "line_string.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiLineString>> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) {
|
||||
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString> (jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsListsList(env, multiLineString));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<MultiLineString>& jMultiLineString) {
|
||||
mapbox::geojson::multi_line_string multiLineString;
|
||||
|
||||
if (jMultiLineString) {
|
||||
multiLineString = MultiLineString::convert(env, MultiLineString::coordinates(env, jMultiLineString));
|
||||
}
|
||||
|
||||
return multiLineString;
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) {
|
||||
mapbox::geojson::multi_line_string multiLineString;
|
||||
|
||||
if (jPointListsList) {
|
||||
auto jPositionListsArray = java::util::List::toArray<java::util::List>(env, jPointListsList);
|
||||
|
||||
auto size = jPositionListsArray.Length(env);
|
||||
multiLineString.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
multiLineString.push_back(LineString::convert(env, jPositionListsArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return multiLineString;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiLineString::coordinates(jni::JNIEnv &env, const jni::Object<MultiLineString>& jLineString) {
|
||||
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jLineString.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiLineString::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<MultiLineString>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiLineString {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiLineString"; };
|
||||
static constexpr auto Type() { return "MultiLineString"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiLineString>> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&);
|
||||
|
||||
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<MultiLineString>&);
|
||||
|
||||
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiLineString>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "multi_point.hpp"
|
||||
|
||||
#include "line_string.hpp"
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiPoint>> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) {
|
||||
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsList(env, multiPoint));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) {
|
||||
mapbox::geojson::multi_point multiPoint;
|
||||
|
||||
if (jMultiPoint) {
|
||||
multiPoint = convertExplicit<mapbox::geojson::multi_point>(
|
||||
LineString::convert(env, MultiPoint::coordinates(env, jMultiPoint)));
|
||||
}
|
||||
|
||||
return multiPoint;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiPoint::coordinates(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) {
|
||||
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jMultiPoint.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiPoint::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<MultiPoint>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiPoint {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiPoint"; };
|
||||
static constexpr auto Type() { return "MultiPoint"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiPoint>> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&);
|
||||
|
||||
static mapbox::geojson::multi_point convert(jni::JNIEnv&, const jni::Object<MultiPoint>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPoint>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "multi_polygon.hpp"
|
||||
|
||||
#include "polygon.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiPolygon>> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) {
|
||||
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size());
|
||||
|
||||
for (size_t i = 0; i < multiPolygon.size(); i++) {
|
||||
jarray.Set(env, i, asPointsListsList(env, multiPolygon.at(i)));
|
||||
}
|
||||
|
||||
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jMultiPolygon) {
|
||||
mapbox::geojson::multi_polygon multiPolygon;
|
||||
|
||||
if (jMultiPolygon) {
|
||||
auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon);
|
||||
auto jPointListsListArray = java::util::List::toArray<java::util::List>(env, jPointListsListList);
|
||||
|
||||
auto size = jPointListsListArray.Length(env);
|
||||
multiPolygon.reserve(size);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
multiPolygon.push_back(Polygon::convert(env, jPointListsListArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return multiPolygon;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiPolygon::coordinates(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jPolygon) {
|
||||
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jPolygon.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiPolygon::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<MultiPolygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiPolygon {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiPolygon"; };
|
||||
static constexpr auto Type() { return "MultiPolygon"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiPolygon>> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&);
|
||||
|
||||
static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<Point>> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) {
|
||||
static auto& javaClass = jni::Class<Point>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Point> (jni::jdouble, jni::jdouble)>(env, "fromLngLat");
|
||||
return javaClass.Call(env, method, point.x, point.y);
|
||||
}
|
||||
|
||||
mbgl::Point<double> Point::convert(jni::JNIEnv &env, const jni::Object<Point>& jPoint) {
|
||||
static auto& javaClass = jni::Class<Point>::Singleton(env);
|
||||
static auto longitude = javaClass.GetMethod<jni::jdouble ()>(env, "longitude");
|
||||
static auto latitude = javaClass.GetMethod<jni::jdouble ()>(env, "latitude");
|
||||
|
||||
if (!jPoint) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
jPoint.Call(env, longitude),
|
||||
jPoint.Call(env, latitude)
|
||||
};
|
||||
}
|
||||
|
||||
void Point::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Point>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Point {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Point"; };
|
||||
static constexpr auto Type() { return "Point"; };
|
||||
|
||||
static jni::Local<jni::Object<Point>> New(jni::JNIEnv&, const mbgl::Point<double>&);
|
||||
static mbgl::Point<double> convert(jni::JNIEnv&, const jni::Object<Point>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "polygon.hpp"
|
||||
|
||||
#include "multi_line_string.hpp"
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<Polygon>> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Polygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsListsList(env, polygon));
|
||||
}
|
||||
|
||||
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) {
|
||||
mapbox::geojson::polygon polygon;
|
||||
|
||||
if (jPolygon) {
|
||||
polygon = Polygon::convert(env, Polygon::coordinates(env, jPolygon));
|
||||
}
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) {
|
||||
mapbox::geojson::polygon polygon;
|
||||
|
||||
if (jPointListsList) {
|
||||
auto multiLine = MultiLineString::convert(env, jPointListsList);
|
||||
polygon.reserve(multiLine.size());
|
||||
for (auto&& line : multiLine) {
|
||||
polygon.emplace_back(convertExplicit<mapbox::geojson::linear_ring>(std::move(line)));
|
||||
}
|
||||
}
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> Polygon::coordinates(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
|
||||
return jPolygon.Call(env, method);
|
||||
}
|
||||
|
||||
void Polygon::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Polygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Polygon {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Polygon"; };
|
||||
static constexpr auto Type() { return "Polygon"; };
|
||||
|
||||
static jni::Local<jni::Object<Polygon>> New(jni::JNIEnv&, const mbgl::Polygon<double>&);
|
||||
|
||||
static mapbox::geojson::polygon convert(jni::JNIEnv &, const jni::Object<Polygon>&);
|
||||
|
||||
static mapbox::geojson::polygon convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<Polygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv &);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
52
platform/android/MapboxGLAndroidSDK/src/cpp/geojson/util.hpp
Normal file
52
platform/android/MapboxGLAndroidSDK/src/cpp/geojson/util.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "point.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
// Clang 3.8 fails to implicitly convert matching types, so we'll have to do it explicitly.
|
||||
template <typename To, typename From>
|
||||
To convertExplicit(From&& src) {
|
||||
static_assert(std::is_same<typename std::decay_t<From>::container_type,
|
||||
typename To::container_type>::value,
|
||||
"container types do not match");
|
||||
static_assert(std::is_rvalue_reference<From&&>::value,
|
||||
"argument must be rvalue reference");
|
||||
return *reinterpret_cast<std::add_pointer_t<To>>(&src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geometry -> List<Point>
|
||||
*/
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<java::util::List>> asPointsList(jni::JNIEnv& env, const T& pointsList) {
|
||||
auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size());
|
||||
|
||||
for (jni::jsize i = 0; i < pointsList.size(); i++) {
|
||||
jarray.Set(env, i, Point::New(env, pointsList.at(i)));
|
||||
}
|
||||
|
||||
return java::util::Arrays::asList(env, jarray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geometry -> List<List<Point>>
|
||||
*/
|
||||
template <class SHAPE>
|
||||
static jni::Local<jni::Object<java::util::List>> asPointsListsList(JNIEnv& env, const SHAPE& value) {
|
||||
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); i++) {
|
||||
jarray.Set(env, i, asPointsList(env, value[i]));
|
||||
}
|
||||
|
||||
return java::util::Arrays::asList(env, jarray);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLng>> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) {
|
||||
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double>(env);
|
||||
return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude());
|
||||
}
|
||||
|
||||
mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
|
||||
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
|
||||
static auto latitudeField = javaClass.GetField<jni::jdouble>(env, "latitude");
|
||||
static auto longitudeField = javaClass.GetField<jni::jdouble>(env, "longitude");
|
||||
return mbgl::Point<double>(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField));
|
||||
}
|
||||
|
||||
mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
|
||||
auto point = LatLng::getGeometry(env, latLng);
|
||||
return mbgl::LatLng(point.y, point.x);
|
||||
}
|
||||
|
||||
void LatLng::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLng>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLng : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLng"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLng>> New(jni::JNIEnv&, const mbgl::LatLng&);
|
||||
|
||||
static mbgl::Point<double> getGeometry(jni::JNIEnv&, const jni::Object<LatLng>&);
|
||||
|
||||
static mbgl::LatLng getLatLng(jni::JNIEnv&, const jni::Object<LatLng>&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "lat_lng_bounds.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLngBounds>> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) {
|
||||
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double, double, double>(env);
|
||||
return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west());
|
||||
}
|
||||
|
||||
mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& bounds) {
|
||||
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
|
||||
static auto swLatField = javaClass.GetField<jni::jdouble>(env, "latitudeSouth");
|
||||
static auto swLonField = javaClass.GetField<jni::jdouble>(env, "longitudeWest");
|
||||
static auto neLatField = javaClass.GetField<jni::jdouble>(env, "latitudeNorth");
|
||||
static auto neLonField = javaClass.GetField<jni::jdouble>(env, "longitudeEast");
|
||||
|
||||
mbgl::LatLng sw = { bounds.Get(env, swLatField), bounds.Get(env, swLonField) };
|
||||
mbgl::LatLng ne = { bounds.Get(env, neLatField), bounds.Get(env, neLonField) };
|
||||
|
||||
return mbgl::LatLngBounds::hull(sw, ne);
|
||||
}
|
||||
|
||||
void LatLngBounds::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLngBounds>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLngBounds : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngBounds"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLngBounds>> New(jni::JNIEnv&, mbgl::LatLngBounds);
|
||||
|
||||
static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, const jni::Object<LatLngBounds>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "lat_lng_quad.hpp"
|
||||
#include "lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLngQuad>> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLng, 4> coordinates) {
|
||||
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
|
||||
static auto quadConstructor = javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(env);
|
||||
return javaClass.New(env, quadConstructor,
|
||||
LatLng::New(env, coordinates[0]),
|
||||
LatLng::New(env, coordinates[1]),
|
||||
LatLng::New(env, coordinates[2]),
|
||||
LatLng::New(env, coordinates[3]));
|
||||
}
|
||||
|
||||
std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, const jni::Object<LatLngQuad>& quad) {
|
||||
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
|
||||
static auto topLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "topLeft");
|
||||
static auto topRightField = javaClass.GetField <jni::Object<LatLng>>(env, "topRight");
|
||||
static auto bottomRightField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomRight");
|
||||
static auto bottomLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomLeft");
|
||||
|
||||
return std::array < mbgl::LatLng, 4 > {{
|
||||
LatLng::getLatLng(env, quad.Get(env, topLeftField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, topRightField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, bottomRightField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, bottomLeftField))
|
||||
}};
|
||||
}
|
||||
|
||||
void LatLngQuad::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLngQuad>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLngQuad : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngQuad"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLngQuad>> New(jni::JNIEnv&, std::array<mbgl::LatLng, 4>);
|
||||
|
||||
static std::array<mbgl::LatLng, 4> getLatLngArray(jni::JNIEnv&, const jni::Object<LatLngQuad>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "projected_meters.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<ProjectedMeters>> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) {
|
||||
static auto& javaClass = jni::Class<ProjectedMeters>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double>(env);
|
||||
return javaClass.New(env, constructor, northing, easting);
|
||||
}
|
||||
|
||||
void ProjectedMeters::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<ProjectedMeters>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class ProjectedMeters : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/ProjectedMeters"; };
|
||||
|
||||
static jni::Local<jni::Object<ProjectedMeters>> New(jni::JNIEnv&, double, double);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,25 @@
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include "pointf.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<PointF>> PointF::New(jni::JNIEnv& env, float x, float y) {
|
||||
static auto& javaClass = jni::Class<PointF>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<float, float>(env);
|
||||
return javaClass.New(env, constructor, x, y);
|
||||
}
|
||||
|
||||
mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, const jni::Object<PointF>& point) {
|
||||
static auto& javaClass = jni::Class<PointF>::Singleton(env);
|
||||
static auto xField = javaClass.GetField<jni::jfloat>(env, "x");
|
||||
static auto yField = javaClass.GetField<jni::jfloat>(env, "y");
|
||||
return mbgl::ScreenCoordinate{point.Get(env, xField), point.Get(env, yField)};
|
||||
}
|
||||
|
||||
void PointF::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<PointF>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class PointF : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "android/graphics/PointF"; };
|
||||
|
||||
static jni::Local<jni::Object<PointF>> New(jni::JNIEnv&, float, float);
|
||||
|
||||
static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, const jni::Object<PointF>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "rectf.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
float RectF::getLeft(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "left");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getTop(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "top");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getRight(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "right");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getBottom(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "bottom");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
void RectF::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<RectF>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class RectF : private mbgl::util::noncopyable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "android/graphics/RectF"; };
|
||||
|
||||
static float getLeft(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getTop(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getRight(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getBottom(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "json_array.hpp"
|
||||
#include "json_element.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
jni::Local<jni::Object<JsonArray>> JsonArray::New(jni::JNIEnv& env, const std::vector<mbgl::Value>& values){
|
||||
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor(env);
|
||||
static auto addMethod = javaClass.GetMethod<void (jni::Object<JsonElement>)>(env, "add");
|
||||
|
||||
auto jsonArray = javaClass.New(env, constructor);
|
||||
|
||||
for (const auto &v : values) {
|
||||
jsonArray.Call(env, addMethod, JsonElement::New(env, v));
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
std::vector<mbgl::Value> JsonArray::convert(jni::JNIEnv& env, const jni::Object<JsonArray>& jsonArray) {
|
||||
std::vector<mbgl::Value> values;
|
||||
|
||||
if (jsonArray) {
|
||||
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
|
||||
static auto getMethod = javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get");
|
||||
static auto sizeMethod = javaClass.GetMethod<jni::jint ()>(env, "size");
|
||||
|
||||
int size = jsonArray.Call(env, sizeMethod);
|
||||
values.reserve(uint(size));
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
auto entry = jsonArray.Call(env, getMethod, i);
|
||||
if (entry) {
|
||||
values.push_back(JsonElement::convert(env, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
void JsonArray::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<JsonArray>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonArray {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonArray"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonArray>> New(jni::JNIEnv&, const std::vector<mbgl::Value>&);
|
||||
static std::vector<mbgl::Value> convert(JNIEnv&, const jni::Object<JsonArray>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "json_element.hpp"
|
||||
#include "json_array.hpp"
|
||||
#include "json_object.hpp"
|
||||
#include "json_primitive.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
jni::Local<jni::Object<JsonElement>> JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) {
|
||||
static auto& primitive = jni::Class<JsonPrimitive>::Singleton(env);
|
||||
static auto stringConstructor = primitive.GetConstructor<jni::String>(env);
|
||||
static auto numberConstructor = primitive.GetConstructor<jni::Number>(env);
|
||||
static auto booleanConstructor = primitive.GetConstructor<jni::Boolean>(env);
|
||||
|
||||
return value.match(
|
||||
[&] (const mbgl::NullValue&) {
|
||||
return jni::Local<jni::Object<JsonElement>>();
|
||||
},
|
||||
[&] (const std::string& value) {
|
||||
return primitive.New(env, stringConstructor, jni::Make<jni::String>(env, value));
|
||||
},
|
||||
[&] (const double value) {
|
||||
return primitive.New(env, numberConstructor, jni::Box(env, value));
|
||||
},
|
||||
[&] (const int64_t value) {
|
||||
return primitive.New(env, numberConstructor, jni::Box(env, value));
|
||||
},
|
||||
[&] (const uint64_t value) {
|
||||
return primitive.New(env, numberConstructor, jni::Box(env, int64_t(value))); // TODO: should use BigInteger
|
||||
},
|
||||
[&] (const bool value) {
|
||||
return primitive.New(env, booleanConstructor, jni::Box(env, value ? jni::jni_true : jni::jni_false));
|
||||
},
|
||||
[&] (const std::vector<mbgl::Value>& values) {
|
||||
return JsonArray::New(env, values);
|
||||
},
|
||||
[&] (const mbgl::PropertyMap& values) {
|
||||
return JsonObject::New(env, values);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
mbgl::Value JsonElement::convert(jni::JNIEnv &env, const jni::Object<JsonElement>& jsonElement) {
|
||||
if (!jsonElement) {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
|
||||
static auto& elementClass = jni::Class<JsonElement>::Singleton(env);
|
||||
static auto isJsonObject = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonObject");
|
||||
static auto isJsonArray = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonArray");
|
||||
static auto isJsonPrimitive = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive");
|
||||
|
||||
static auto& primitiveClass = jni::Class<JsonPrimitive>::Singleton(env);
|
||||
static auto isBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "isBoolean");
|
||||
static auto isString = primitiveClass.GetMethod<jni::jboolean ()>(env, "isString");
|
||||
static auto isNumber = primitiveClass.GetMethod<jni::jboolean ()>(env, "isNumber");
|
||||
static auto getAsBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean");
|
||||
static auto getAsString = primitiveClass.GetMethod<jni::String ()>(env, "getAsString");
|
||||
static auto getAsDouble = primitiveClass.GetMethod<jni::jdouble ()>(env, "getAsDouble");
|
||||
|
||||
if (jsonElement.Call(env, isJsonPrimitive)) {
|
||||
auto primitive = jni::Cast(env, primitiveClass, jsonElement);
|
||||
if (primitive.Call(env, isBoolean)) {
|
||||
return bool(primitive.Call(env, getAsBoolean));
|
||||
} else if (primitive.Call(env, isNumber)) {
|
||||
return primitive.Call(env, getAsDouble);
|
||||
} else if (primitive.Call(env, isString)) {
|
||||
return jni::Make<std::string>(env, primitive.Call(env, getAsString));
|
||||
} else {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
} else if (jsonElement.Call(env, isJsonObject)) {
|
||||
return JsonObject::convert(env, jni::Cast(env, jni::Class<JsonObject>::Singleton(env), jsonElement));
|
||||
} else if (jsonElement.Call(env, isJsonArray)) {
|
||||
return JsonArray::convert(env, jni::Cast(env, jni::Class<JsonArray>::Singleton(env), jsonElement));
|
||||
} else {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonElement::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<JsonElement>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/feature.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonElement {
|
||||
public:
|
||||
using SuperTag = jni::ObjectTag;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonElement"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonElement>> New(jni::JNIEnv&, const mbgl::Value&);
|
||||
static mbgl::Value convert(JNIEnv&, const jni::Object<JsonElement>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "json_object.hpp"
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
|
||||
jni::Local<jni::Object<JsonObject>> JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) {
|
||||
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor(env);
|
||||
static auto addMethod = javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add");
|
||||
|
||||
auto jsonObject = javaClass.New(env, constructor);
|
||||
|
||||
for (auto &item : values) {
|
||||
jsonObject.Call(env, addMethod,
|
||||
jni::Make<jni::String>(env, item.first),
|
||||
JsonElement::New(env, item.second));
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
template <typename F> // void (jni::String, jni::Object<gson::JsonElement>)
|
||||
static void iterateEntrySet(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject, F callback) {
|
||||
// Get Set<Map.Entry<String, JsonElement>>
|
||||
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet");
|
||||
|
||||
auto entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, jsonObject.Call(env, method));
|
||||
|
||||
size_t size = entryArray.Length(env);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
auto entry = entryArray.Get(env, i);
|
||||
if (entry) {
|
||||
callback(
|
||||
java::util::Map::Entry::getKey<jni::StringTag>(env, entry),
|
||||
java::util::Map::Entry::getValue<gson::JsonElement>(env, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mbgl::PropertyMap JsonObject::convert(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject) {
|
||||
mbgl::PropertyMap map;
|
||||
|
||||
if (jsonObject) {
|
||||
iterateEntrySet(env, jsonObject, [&map, &env](const jni::String& jId, const jni::Object<gson::JsonElement>& jsonElement) {
|
||||
map[jni::Make<std::string>(env, jId)] = JsonElement::convert(env, jsonElement);
|
||||
});
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void JsonObject::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<JsonObject>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonObject {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonObject"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonObject>> New(jni::JNIEnv&, const mbgl::PropertyMap&);
|
||||
static mbgl::PropertyMap convert(JNIEnv&, const jni::Object<JsonObject>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "json_primitive.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
void JsonPrimitive::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<JsonPrimitive>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonPrimitive {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
195
platform/android/MapboxGLAndroidSDK/src/cpp/http_file_source.cpp
Normal file
195
platform/android/MapboxGLAndroidSDK/src/cpp/http_file_source.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <mbgl/storage/http_file_source.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <mbgl/util/async_request.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/http_header.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class HTTPFileSource::Impl {
|
||||
public:
|
||||
android::UniqueEnv env { android::AttachEnv() };
|
||||
};
|
||||
|
||||
class HTTPRequest : public AsyncRequest {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/http/NativeHttpRequest"; };
|
||||
|
||||
HTTPRequest(jni::JNIEnv&, const Resource&, FileSource::Callback);
|
||||
~HTTPRequest();
|
||||
|
||||
void onFailure(jni::JNIEnv&, int type, const jni::String& message);
|
||||
void onResponse(jni::JNIEnv&, int code,
|
||||
const jni::String& etag, const jni::String& modified,
|
||||
const jni::String& cacheControl, const jni::String& expires,
|
||||
const jni::String& retryAfter, const jni::String& xRateLimitReset,
|
||||
const jni::Array<jni::jbyte>& body);
|
||||
|
||||
jni::Global<jni::Object<HTTPRequest>> javaRequest;
|
||||
|
||||
private:
|
||||
Resource resource;
|
||||
FileSource::Callback callback;
|
||||
Response response;
|
||||
|
||||
util::AsyncTask async { [this] {
|
||||
// Calling `callback` may result in deleting `this`. Copy data to temporaries first.
|
||||
auto callback_ = callback;
|
||||
auto response_ = response;
|
||||
callback_(response_);
|
||||
} };
|
||||
|
||||
static const int connectionError = 0;
|
||||
static const int temporaryError = 1;
|
||||
static const int permanentError = 2;
|
||||
};
|
||||
|
||||
namespace android {
|
||||
|
||||
void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<HTTPRequest>(env, javaClass, "nativePtr",
|
||||
METHOD(&HTTPRequest::onFailure, "nativeOnFailure"),
|
||||
METHOD(&HTTPRequest::onResponse, "nativeOnResponse"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource::Callback callback_)
|
||||
: resource(resource_),
|
||||
callback(callback_) {
|
||||
std::string etagStr;
|
||||
std::string modifiedStr;
|
||||
|
||||
if (resource.priorEtag) {
|
||||
etagStr = *resource.priorEtag;
|
||||
} else if (resource.priorModified) {
|
||||
modifiedStr = util::rfc1123(*resource.priorModified);
|
||||
}
|
||||
|
||||
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10);
|
||||
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
|
||||
static auto constructor =
|
||||
javaClass.GetConstructor<jni::jlong, jni::String, jni::String, jni::String, jni::jboolean>(env);
|
||||
|
||||
javaRequest = jni::NewGlobal(env,
|
||||
javaClass.New(env, constructor,
|
||||
reinterpret_cast<jlong>(this),
|
||||
jni::Make<jni::String>(env, resource.url),
|
||||
jni::Make<jni::String>(env, etagStr),
|
||||
jni::Make<jni::String>(env, modifiedStr),
|
||||
(jboolean) (resource_.usage == Resource::Usage::Offline)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(*env);
|
||||
static auto cancel = javaClass.GetMethod<void ()>(*env, "cancel");
|
||||
|
||||
javaRequest.Call(*env, cancel);
|
||||
}
|
||||
|
||||
void HTTPRequest::onResponse(jni::JNIEnv& env, int code,
|
||||
const jni::String& etag, const jni::String& modified,
|
||||
const jni::String& cacheControl, const jni::String& expires,
|
||||
const jni::String& jRetryAfter, const jni::String& jXRateLimitReset,
|
||||
const jni::Array<jni::jbyte>& body) {
|
||||
|
||||
using Error = Response::Error;
|
||||
|
||||
if (etag) {
|
||||
response.etag = jni::Make<std::string>(env, etag);
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
response.modified = util::parseTimestamp(jni::Make<std::string>(env, modified).c_str());
|
||||
}
|
||||
|
||||
if (cacheControl) {
|
||||
const auto cc = http::CacheControl::parse(jni::Make<std::string>(env, cacheControl).c_str());
|
||||
response.expires = cc.toTimePoint();
|
||||
response.mustRevalidate = cc.mustRevalidate;
|
||||
}
|
||||
|
||||
if (expires) {
|
||||
response.expires = util::parseTimestamp(jni::Make<std::string>(env, expires).c_str());
|
||||
}
|
||||
|
||||
if (code == 200) {
|
||||
if (body) {
|
||||
auto data = std::make_shared<std::string>(body.Length(env), char());
|
||||
jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
|
||||
response.data = data;
|
||||
} else {
|
||||
response.data = std::make_shared<std::string>();
|
||||
}
|
||||
} else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) {
|
||||
response.noContent = true;
|
||||
} else if (code == 304) {
|
||||
response.notModified = true;
|
||||
} else if (code == 404) {
|
||||
response.error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
|
||||
} else if (code == 429) {
|
||||
optional<std::string> retryAfter;
|
||||
optional<std::string> xRateLimitReset;
|
||||
if (jRetryAfter) {
|
||||
retryAfter = jni::Make<std::string>(env, jRetryAfter);
|
||||
}
|
||||
if (jXRateLimitReset) {
|
||||
xRateLimitReset = jni::Make<std::string>(env, jXRateLimitReset);
|
||||
}
|
||||
response.error = std::make_unique<Error>(Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset));
|
||||
} else if (code >= 500 && code < 600) {
|
||||
response.error = std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } + util::toString(code));
|
||||
} else {
|
||||
response.error = std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } + util::toString(code));
|
||||
}
|
||||
|
||||
async.send();
|
||||
}
|
||||
|
||||
void HTTPRequest::onFailure(jni::JNIEnv& env, int type, const jni::String& message) {
|
||||
std::string messageStr = jni::Make<std::string>(env, message);
|
||||
|
||||
using Error = Response::Error;
|
||||
|
||||
switch (type) {
|
||||
case connectionError:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Connection, messageStr);
|
||||
break;
|
||||
case temporaryError:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Server, messageStr);
|
||||
break;
|
||||
default:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Other, messageStr);
|
||||
}
|
||||
|
||||
async.send();
|
||||
}
|
||||
|
||||
HTTPFileSource::HTTPFileSource()
|
||||
: impl(std::make_unique<Impl>()) {
|
||||
}
|
||||
|
||||
HTTPFileSource::~HTTPFileSource() = default;
|
||||
|
||||
std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, Callback callback) {
|
||||
return std::make_unique<HTTPRequest>(*impl->env, resource, callback);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
192
platform/android/MapboxGLAndroidSDK/src/cpp/i18n/collator.cpp
Normal file
192
platform/android/MapboxGLAndroidSDK/src/cpp/i18n/collator.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
#include <mbgl/i18n/collator.hpp>
|
||||
#include <mbgl/text/language_tag.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "collator_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void Collator::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Collator>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Collator>> Collator::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Collator> (jni::Object<Locale>)>(env, "getInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
void Collator::setStrength(jni::JNIEnv& env, const jni::Object<Collator>& collator, jni::jint strength) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setStrength");
|
||||
collator.Call(env, method, strength);
|
||||
}
|
||||
|
||||
jni::jint Collator::compare(jni::JNIEnv& env, const jni::Object<Collator>& collator, const jni::String& lhs, const jni::String& rhs) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::jint (jni::String, jni::String)>(env, "compare");
|
||||
return collator.Call(env, method, lhs, rhs);
|
||||
}
|
||||
|
||||
void StringUtils::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<StringUtils>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> StringUtils::unaccent(jni::JNIEnv& env, const jni::String& value) {
|
||||
static auto& javaClass = jni::Class<StringUtils>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::String (jni::String)>(env, "unaccent");
|
||||
return javaClass.Call(env, method, value);
|
||||
}
|
||||
|
||||
void Locale::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Locale>::Singleton(env);
|
||||
}
|
||||
|
||||
/*
|
||||
We would prefer to use for/toLanguageTag, but they're only available in API level 21+
|
||||
|
||||
jni::Object<Locale> Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) {
|
||||
using Signature = jni::Object<Locale>(jni::String);
|
||||
auto method = javaClass.GetStaticMethod<Signature>(env, "forLanguageTag");
|
||||
return javaClass.Call(env, method, languageTag);
|
||||
}
|
||||
|
||||
jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object<Locale> locale) {
|
||||
using Signature = jni::String();
|
||||
auto static method = javaClass.GetMethod<Signature>(env, "toLanguageTag");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
*/
|
||||
|
||||
jni::Local<jni::String> Locale::getLanguage(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String ()>(env, "getLanguage");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> Locale::getCountry(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String ()>(env, "getCountry");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::getDefault(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Locale> ()>(env, "getDefault");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String>(env);
|
||||
return javaClass.New(env, constructor, language);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language, const jni::String& region) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env);
|
||||
return javaClass.New(env, constructor, language, region);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
namespace platform {
|
||||
|
||||
class Collator::Impl {
|
||||
public:
|
||||
Impl(bool caseSensitive_, bool diacriticSensitive_, optional<std::string> locale_)
|
||||
: caseSensitive(caseSensitive_)
|
||||
, diacriticSensitive(diacriticSensitive_)
|
||||
, env(android::AttachEnv())
|
||||
{
|
||||
LanguageTag languageTag = locale_ ? LanguageTag::fromBCP47(*locale_) : LanguageTag();
|
||||
if (!languageTag.language) {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::getDefault(*env));
|
||||
} else if (!languageTag.region) {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
|
||||
} else {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language),
|
||||
jni::Make<jni::String>(*env, *languageTag.region)));
|
||||
}
|
||||
collator = jni::NewGlobal(*env, android::Collator::getInstance(*env, locale));
|
||||
if (!diacriticSensitive && !caseSensitive) {
|
||||
android::Collator::setStrength(*env, collator, 0 /*PRIMARY*/);
|
||||
} else if (diacriticSensitive && !caseSensitive) {
|
||||
android::Collator::setStrength(*env, collator, 1 /*SECONDARY*/);
|
||||
} else if (caseSensitive) {
|
||||
// If we're case-sensitive and diacritic-sensitive, we use a case-sensitive collator
|
||||
// and a fallback implementation of diacritic-insensitivity.
|
||||
android::Collator::setStrength(*env, collator, 2 /*TERTIARY*/);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Impl& other) const {
|
||||
return caseSensitive == other.caseSensitive &&
|
||||
diacriticSensitive == other.diacriticSensitive &&
|
||||
resolvedLocale() == other.resolvedLocale();
|
||||
}
|
||||
|
||||
int compare(const std::string& lhs, const std::string& rhs) const {
|
||||
bool useUnaccent = !diacriticSensitive && caseSensitive;
|
||||
// java.text.Collator doesn't support a diacritic-insensitive/case-sensitive collation
|
||||
// order, so we have to compromise here. We use Android's case-sensitive Collator
|
||||
// against strings that have been "unaccented" using non-locale-aware nunicode logic.
|
||||
// Because of the difference in locale-awareness, this means turning on case-sensitivity
|
||||
// can _potentially_ change compare results for strings that don't actually have any case
|
||||
// differences.
|
||||
jni::Local<jni::String> jlhs = useUnaccent
|
||||
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, lhs))
|
||||
: jni::Make<jni::String>(*env, lhs);
|
||||
jni::Local<jni::String> jrhs = useUnaccent
|
||||
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, rhs))
|
||||
: jni::Make<jni::String>(*env, rhs);
|
||||
|
||||
jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string resolvedLocale() const {
|
||||
std::string language = jni::Make<std::string>(*env, android::Locale::getLanguage(*env, locale));
|
||||
std::string region = jni::Make<std::string>(*env, android::Locale::getCountry(*env, locale));
|
||||
|
||||
optional<std::string> resultLanguage;
|
||||
if (!language.empty()) resultLanguage = language;
|
||||
optional<std::string> resultRegion;
|
||||
if (!region.empty()) resultRegion = region;
|
||||
|
||||
return LanguageTag(resultLanguage, {}, resultRegion).toBCP47();
|
||||
}
|
||||
|
||||
private:
|
||||
bool caseSensitive;
|
||||
bool diacriticSensitive;
|
||||
|
||||
android::UniqueEnv env;
|
||||
jni::Global<jni::Object<android::Collator>> collator;
|
||||
jni::Global<jni::Object<android::Locale>> locale;
|
||||
};
|
||||
|
||||
Collator::Collator(bool caseSensitive, bool diacriticSensitive, const optional<std::string>& locale_)
|
||||
: impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, locale_)) {}
|
||||
|
||||
bool Collator::operator==(const Collator& other) const {
|
||||
return *impl == *(other.impl);
|
||||
}
|
||||
|
||||
int Collator::compare(const std::string& lhs, const std::string& rhs) const {
|
||||
return impl->compare(lhs, rhs);
|
||||
}
|
||||
|
||||
std::string Collator::resolvedLocale() const {
|
||||
return impl->resolvedLocale();
|
||||
}
|
||||
|
||||
} // namespace platform
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
/*
|
||||
android::Collator and android::Locale are
|
||||
the JNI wrappers of
|
||||
java/text/Collator and java/util/Locale
|
||||
|
||||
mbgl::Collator is the portable interface
|
||||
Both implementations are in collator.cpp
|
||||
*/
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Locale {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Locale"; };
|
||||
|
||||
/* Requires API level 21+ in order to support script/variant
|
||||
static jni::Object<Locale> forLanguageTag(jni::JNIEnv&, jni::String);
|
||||
static jni::String toLanguageTag(jni::JNIEnv&, jni::Object<Locale>);
|
||||
*/
|
||||
static jni::Local<jni::Object<Locale>> getDefault(jni::JNIEnv&);
|
||||
static jni::Local<jni::String> getLanguage(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::String> getCountry(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
|
||||
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&);
|
||||
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&, const jni::String&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
class Collator {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/text/Collator"; };
|
||||
|
||||
static jni::Local<jni::Object<Collator>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
|
||||
static void setStrength(jni::JNIEnv&, const jni::Object<Collator>&, jni::jint);
|
||||
|
||||
static jni::jint compare(jni::JNIEnv&, const jni::Object<Collator>&, const jni::String&, const jni::String&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
|
||||
class StringUtils {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/utils/StringUtils"; };
|
||||
|
||||
static jni::Local<jni::String> unaccent(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <mbgl/i18n/number_format.hpp>
|
||||
#include <mbgl/text/language_tag.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "number_format_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void NumberFormat::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<NumberFormat>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<NumberFormat>> NumberFormat::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat> (jni::Object<Locale>)>(env, "getInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<NumberFormat>> NumberFormat::getCurrencyInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat> (jni::Object<Locale>)>(env, "getCurrencyInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> NumberFormat::format(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jdouble number) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String (jni::jdouble)>(env, "format");
|
||||
return nf.Call(env, method, number);
|
||||
}
|
||||
|
||||
void NumberFormat::setMinimumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setMinimumFractionDigits");
|
||||
return nf.Call(env, method, value);
|
||||
}
|
||||
|
||||
void NumberFormat::setMaximumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setMaximumFractionDigits");
|
||||
return nf.Call(env, method, value);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
namespace platform {
|
||||
|
||||
std::string formatNumber(double number, const std::string& localeId, const std::string& currency,
|
||||
uint8_t minFractionDigits, uint8_t maxFractionDigits) {
|
||||
|
||||
auto env{ android::AttachEnv() };
|
||||
|
||||
jni::Global<jni::Object<android::Locale>> locale;
|
||||
LanguageTag languageTag = !localeId.empty() ? LanguageTag::fromBCP47(localeId) : LanguageTag();
|
||||
if (!languageTag.language) {
|
||||
locale = jni::NewGlobal(*env, android::Locale::getDefault(*env));
|
||||
} else if (!languageTag.region) {
|
||||
locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
|
||||
} else {
|
||||
locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language),
|
||||
jni::Make<jni::String>(*env, *languageTag.region)));
|
||||
}
|
||||
|
||||
jni::Global<jni::Object<android::NumberFormat>> formatter;
|
||||
if (currency.empty()) {
|
||||
formatter = jni::NewGlobal(*env, android::NumberFormat::getInstance(*env, locale));
|
||||
android::NumberFormat::setMinimumFractionDigits(*env, formatter, static_cast<jni::jint>(minFractionDigits));
|
||||
android::NumberFormat::setMaximumFractionDigits(*env, formatter, static_cast<jni::jint>(maxFractionDigits));
|
||||
} else {
|
||||
formatter = jni::NewGlobal(*env, android::NumberFormat::getCurrencyInstance(*env, locale));
|
||||
}
|
||||
|
||||
auto result = android::NumberFormat::format(*env, formatter, static_cast<jni::jdouble>(number));
|
||||
return jni::Make<std::string>(*env, result);
|
||||
}
|
||||
|
||||
} // namespace platform
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "collator_jni.hpp"
|
||||
|
||||
/*
|
||||
android::NumberFormat is the JNI wrapper
|
||||
of java/text/NumberFormat.
|
||||
*/
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class NumberFormat {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/text/NumberFormat"; };
|
||||
|
||||
static jni::Local<jni::Object<NumberFormat>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::Object<NumberFormat>> getCurrencyInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::String> format(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jdouble);
|
||||
static void setMinimumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
|
||||
static void setMaximumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
19
platform/android/MapboxGLAndroidSDK/src/cpp/java/util.cpp
Normal file
19
platform/android/MapboxGLAndroidSDK/src/cpp/java/util.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
namespace util {
|
||||
|
||||
void registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Arrays>::Singleton(env);
|
||||
jni::Class<List>::Singleton(env);
|
||||
jni::Class<Set>::Singleton(env);
|
||||
jni::Class<Map>::Singleton(env);
|
||||
jni::Class<Map::Entry>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
81
platform/android/MapboxGLAndroidSDK/src/cpp/java/util.hpp
Normal file
81
platform/android/MapboxGLAndroidSDK/src/cpp/java/util.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
namespace util {
|
||||
|
||||
class List : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/List"; };
|
||||
|
||||
template<class T>
|
||||
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<List>& list) {
|
||||
static auto& javaClass = jni::Class<List>::Singleton(env);
|
||||
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray");
|
||||
|
||||
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
|
||||
};
|
||||
};
|
||||
|
||||
class Arrays : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Arrays"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<List>> asList(jni::JNIEnv& env, const jni::Array<jni::Object<T>>& array) {
|
||||
static auto& javaClass = jni::Class<Arrays>::Singleton(env);
|
||||
static auto asList = javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList");
|
||||
|
||||
auto typeErasedArray = jni::Local<jni::Array<jni::Object<>>>(env, jni::NewLocal(env, array).release());
|
||||
return javaClass.Call(env, asList, typeErasedArray);
|
||||
}
|
||||
};
|
||||
|
||||
class Set : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Set"; };
|
||||
|
||||
template<class T>
|
||||
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<Set>& list) {
|
||||
static auto& javaClass = jni::Class<Set>::Singleton(env);
|
||||
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray");
|
||||
|
||||
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
|
||||
};
|
||||
};
|
||||
|
||||
class Map : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Map"; };
|
||||
|
||||
class Entry : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Map$Entry"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<T>> getKey(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
|
||||
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getKey");
|
||||
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<T>> getValue(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
|
||||
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getValue");
|
||||
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void registerNative(jni::JNIEnv&);
|
||||
|
||||
} // namespace util
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
49
platform/android/MapboxGLAndroidSDK/src/cpp/java_types.cpp
Normal file
49
platform/android/MapboxGLAndroidSDK/src/cpp/java_types.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "java_types.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
|
||||
jni::jclass* ObjectArray::jclass;
|
||||
|
||||
jni::jclass* String::jclass;
|
||||
|
||||
jni::jclass* Boolean::jclass;
|
||||
jni::jmethodID* Boolean::booleanValueMethodId;
|
||||
|
||||
jni::jclass* Number::jclass;
|
||||
jni::jmethodID* Number::floatValueMethodId;
|
||||
jni::jmethodID* Number::doubleValueMethodId;
|
||||
jni::jmethodID* Number::longValueMethodId;
|
||||
|
||||
jni::jclass* Map::jclass;
|
||||
jni::jmethodID* Map::getMethodId;
|
||||
jni::jmethodID* Map::keySetMethodId;
|
||||
|
||||
jni::jclass* Set::jclass;
|
||||
jni::jmethodID* Set::toArrayMethodId;
|
||||
|
||||
void registerNatives(JNIEnv& env) {
|
||||
ObjectArray::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "[Ljava/lang/Object;")).release();
|
||||
|
||||
String::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release();
|
||||
|
||||
Boolean::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release();
|
||||
Boolean::booleanValueMethodId = &jni::GetMethodID(env, *Boolean::jclass, "booleanValue", "()Z");
|
||||
|
||||
Number::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Number")).release();
|
||||
Number::floatValueMethodId = &jni::GetMethodID(env, *Number::jclass, "floatValue", "()F");
|
||||
Number::doubleValueMethodId = &jni::GetMethodID(env, *Number::jclass, "doubleValue", "()D");
|
||||
Number::longValueMethodId = &jni::GetMethodID(env, *Number::jclass, "longValue", "()J");
|
||||
|
||||
Map::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Map")).release();
|
||||
Map::getMethodId = &jni::GetMethodID(env, *Map::jclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
Map::keySetMethodId = &jni::GetMethodID(env, *Map::jclass, "keySet", "()Ljava/util/Set;");
|
||||
|
||||
Set::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Set")).release();
|
||||
Set::toArrayMethodId = &jni::GetMethodID(env, *Set::jclass, "toArray", "()[Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
43
platform/android/MapboxGLAndroidSDK/src/cpp/java_types.hpp
Normal file
43
platform/android/MapboxGLAndroidSDK/src/cpp/java_types.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
|
||||
struct ObjectArray {
|
||||
static jni::jclass* jclass;
|
||||
};
|
||||
|
||||
struct String {
|
||||
static jni::jclass* jclass;
|
||||
};
|
||||
|
||||
struct Boolean {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* booleanValueMethodId;
|
||||
};
|
||||
|
||||
struct Number {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* floatValueMethodId;
|
||||
static jni::jmethodID* doubleValueMethodId;
|
||||
static jni::jmethodID* longValueMethodId;
|
||||
};
|
||||
|
||||
struct Map {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* getMethodId;
|
||||
static jni::jmethodID* keySetMethodId;
|
||||
};
|
||||
|
||||
struct Set {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* toArrayMethodId;
|
||||
};
|
||||
|
||||
void registerNatives(JNIEnv&);
|
||||
}
|
||||
}
|
||||
}
|
||||
168
platform/android/MapboxGLAndroidSDK/src/cpp/jni_native.cpp
Normal file
168
platform/android/MapboxGLAndroidSDK/src/cpp/jni_native.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "jni_native.hpp"
|
||||
|
||||
#include "annotation/marker.hpp"
|
||||
#include "annotation/polygon.hpp"
|
||||
#include "annotation/polyline.hpp"
|
||||
#include "bitmap.hpp"
|
||||
#include "bitmap_factory.hpp"
|
||||
#include "connectivity_listener.hpp"
|
||||
#include "conversion/collection.hpp"
|
||||
#include "conversion/conversion.hpp"
|
||||
#include "file_source.hpp"
|
||||
#include "geojson/feature.hpp"
|
||||
#include "geojson/feature_collection.hpp"
|
||||
#include "geojson/geometry.hpp"
|
||||
#include "geojson/geometry_collection.hpp"
|
||||
#include "geojson/line_string.hpp"
|
||||
#include "geojson/multi_line_string.hpp"
|
||||
#include "geojson/multi_point.hpp"
|
||||
#include "geojson/multi_polygon.hpp"
|
||||
#include "geojson/point.hpp"
|
||||
#include "geojson/polygon.hpp"
|
||||
#include "geometry/lat_lng.hpp"
|
||||
#include "geometry/lat_lng_bounds.hpp"
|
||||
#include "geometry/lat_lng_quad.hpp"
|
||||
#include "geometry/projected_meters.hpp"
|
||||
#include "graphics/pointf.hpp"
|
||||
#include "graphics/rectf.hpp"
|
||||
#include "gson/json_array.hpp"
|
||||
#include "gson/json_element.hpp"
|
||||
#include "gson/json_object.hpp"
|
||||
#include "gson/json_primitive.hpp"
|
||||
#include "java_types.hpp"
|
||||
#include "map_renderer.hpp"
|
||||
#include "map_renderer_runnable.hpp"
|
||||
#include "mapbox.hpp"
|
||||
#include "native_map_view.hpp"
|
||||
#ifndef MBGL_MODULE_OFFLINE_DISABLE
|
||||
#include "offline/offline_manager.hpp"
|
||||
#include "offline/offline_region.hpp"
|
||||
#include "offline/offline_region_definition.hpp"
|
||||
#include "offline/offline_region_error.hpp"
|
||||
#include "offline/offline_region_status.hpp"
|
||||
#endif
|
||||
#include "style/transition_options.hpp"
|
||||
#include "style/layers/layer_manager.hpp"
|
||||
#include "style/sources/source.hpp"
|
||||
#include "style/light.hpp"
|
||||
#include "style/formatted.hpp"
|
||||
#include "style/formatted_section.hpp"
|
||||
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
|
||||
#include "snapshotter/map_snapshotter.hpp"
|
||||
#include "snapshotter/map_snapshot.hpp"
|
||||
#endif
|
||||
#include "i18n/collator_jni.hpp"
|
||||
#include "i18n/number_format_jni.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "text/local_glyph_rasterizer_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void RegisterNativeHTTPRequest(JNIEnv&);
|
||||
|
||||
void registerNatives(JavaVM *vm) {
|
||||
theJVM = vm;
|
||||
|
||||
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
|
||||
|
||||
// For the FileSource
|
||||
static mbgl::util::RunLoop mainRunLoop;
|
||||
FileSource::registerNative(env);
|
||||
|
||||
// Basic types
|
||||
java::registerNatives(env);
|
||||
java::util::registerNative(env);
|
||||
PointF::registerNative(env);
|
||||
RectF::registerNative(env);
|
||||
|
||||
// GeoJSON
|
||||
geojson::Feature::registerNative(env);
|
||||
geojson::FeatureCollection::registerNative(env);
|
||||
geojson::Geometry::registerNative(env);
|
||||
geojson::GeometryCollection::registerNative(env);
|
||||
geojson::LineString::registerNative(env);
|
||||
geojson::MultiLineString::registerNative(env);
|
||||
geojson::MultiPoint::registerNative(env);
|
||||
geojson::MultiPolygon::registerNative(env);
|
||||
geojson::Point::registerNative(env);
|
||||
geojson::Polygon::registerNative(env);
|
||||
|
||||
// Geometry
|
||||
LatLng::registerNative(env);
|
||||
LatLngBounds::registerNative(env);
|
||||
LatLngQuad::registerNative(env);
|
||||
ProjectedMeters::registerNative(env);
|
||||
|
||||
// GSon
|
||||
gson::JsonArray::registerNative(env);
|
||||
gson::JsonElement::registerNative(env);
|
||||
gson::JsonObject::registerNative(env);
|
||||
gson::JsonPrimitive::registerNative(env);
|
||||
|
||||
//Annotation
|
||||
Marker::registerNative(env);
|
||||
Polygon::registerNative(env);
|
||||
Polyline::registerNative(env);
|
||||
|
||||
// Map
|
||||
MapRenderer::registerNative(env);
|
||||
MapRendererRunnable::registerNative(env);
|
||||
NativeMapView::registerNative(env);
|
||||
|
||||
// Http
|
||||
RegisterNativeHTTPRequest(env);
|
||||
|
||||
// Bitmap
|
||||
Bitmap::registerNative(env);
|
||||
BitmapFactory::registerNative(env);
|
||||
|
||||
// Style
|
||||
TransitionOptions::registerNative(env);
|
||||
LayerManagerAndroid::get()->registerNative(env);
|
||||
Source::registerNative(env);
|
||||
Light::registerNative(env);
|
||||
Position::registerNative(env);
|
||||
Formatted::registerNative(env);
|
||||
FormattedSection::registerNative(env);
|
||||
|
||||
// Map
|
||||
CameraPosition::registerNative(env);
|
||||
Image::registerNative(env);
|
||||
|
||||
// Connectivity
|
||||
ConnectivityListener::registerNative(env);
|
||||
|
||||
// Offline
|
||||
#ifndef MBGL_MODULE_OFFLINE_DISABLE
|
||||
OfflineManager::registerNative(env);
|
||||
OfflineRegion::registerNative(env);
|
||||
OfflineRegionDefinition::registerNative(env);
|
||||
OfflineTilePyramidRegionDefinition::registerNative(env);
|
||||
OfflineGeometryRegionDefinition::registerNative(env);
|
||||
OfflineRegionError::registerNative(env);
|
||||
OfflineRegionStatus::registerNative(env);
|
||||
#endif
|
||||
|
||||
// Snapshotter
|
||||
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
|
||||
MapSnapshotter::registerNative(env);
|
||||
MapSnapshot::registerNative(env);
|
||||
#endif
|
||||
|
||||
// text
|
||||
LocalGlyphRasterizer::registerNative(env);
|
||||
Locale::registerNative(env);
|
||||
Collator::registerNative(env);
|
||||
StringUtils::registerNative(env);
|
||||
NumberFormat::registerNative(env);
|
||||
|
||||
// Logger
|
||||
Logger::registerNative(env);
|
||||
|
||||
// AssetManager
|
||||
Mapbox::registerNative(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
13
platform/android/MapboxGLAndroidSDK/src/cpp/jni_native.hpp
Normal file
13
platform/android/MapboxGLAndroidSDK/src/cpp/jni_native.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include "jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MBGL_EXPORT void registerNatives(JavaVM* vm);
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
34
platform/android/MapboxGLAndroidSDK/src/cpp/logger.cpp
Normal file
34
platform/android/MapboxGLAndroidSDK/src/cpp/logger.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "logger.hpp"
|
||||
#include "java_types.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void Logger::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Logger>::Singleton(env);
|
||||
}
|
||||
|
||||
void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) {
|
||||
static auto& _class = jni::Class<Logger>::Singleton(env);
|
||||
|
||||
auto tag = jni::Make<jni::String>(env, "Mbgl");
|
||||
auto message = jni::Make<jni::String>(env, msg);
|
||||
using Signature = void(jni::String, jni::String);
|
||||
|
||||
if (severity == EventSeverity::Debug) {
|
||||
auto static debug = _class.GetStaticMethod<Signature>(env, "d");
|
||||
_class.Call(env, debug, tag, message);
|
||||
} else if (severity == EventSeverity::Info) {
|
||||
auto static info = _class.GetStaticMethod<Signature>(env, "i");
|
||||
_class.Call(env, info, tag, message);
|
||||
} else if(severity == EventSeverity::Warning) {
|
||||
auto static warning = _class.GetStaticMethod<Signature>(env, "w");
|
||||
_class.Call(env, warning, tag, message);
|
||||
} else {
|
||||
auto static error = _class.GetStaticMethod<Signature>(env, "e");
|
||||
_class.Call(env, error, tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
21
platform/android/MapboxGLAndroidSDK/src/cpp/logger.hpp
Normal file
21
platform/android/MapboxGLAndroidSDK/src/cpp/logger.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/event.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
#include "bitmap.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
static constexpr auto Name() {
|
||||
return "com/mapbox/mapboxsdk/log/Logger";
|
||||
};
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
static void log(jni::JNIEnv&, EventSeverity severity, const std::string &msg);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include "logger.hpp"
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
void Log::platformRecord(EventSeverity severity, const std::string &msg) {
|
||||
auto env{ android::AttachEnv() };
|
||||
android::Logger::log(*env, severity, msg);
|
||||
}
|
||||
|
||||
}
|
||||
9
platform/android/MapboxGLAndroidSDK/src/cpp/main.cpp
Normal file
9
platform/android/MapboxGLAndroidSDK/src/cpp/main.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "jni.hpp"
|
||||
#include "jni_native.hpp"
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) {
|
||||
assert(vm != nullptr);
|
||||
mbgl::android::registerNatives(vm);
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "camera_position.hpp"
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options, float pixelRatio) {
|
||||
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::Object<LatLng>, double, double, double, jni::Array<jni::jdouble>>(env);
|
||||
|
||||
// wrap LatLng values coming from core
|
||||
auto center = options.center.value();
|
||||
center.wrap();
|
||||
|
||||
// convert bearing, measured in radians counterclockwise from true north.
|
||||
// Wrapped to [−π rad, π rad). Android binding from 0 to 360 degrees
|
||||
double bearing_degrees = options.bearing.value_or(0);
|
||||
while (bearing_degrees > 360) {
|
||||
bearing_degrees -= 360;
|
||||
}
|
||||
while (bearing_degrees < 0) {
|
||||
bearing_degrees += 360;
|
||||
}
|
||||
|
||||
// convert tilt, core ranges from [0 rad, 1,0472 rad], android ranges from 0 to 60
|
||||
double tilt_degrees = options.pitch.value_or(0);
|
||||
|
||||
std::vector<jdouble> paddingVect;
|
||||
auto insets = options.padding.value_or(EdgeInsets {0, 0, 0, 0});
|
||||
auto padding = jni::Array<jni::jdouble>::New(env, 4);
|
||||
paddingVect.push_back(insets.left() * pixelRatio);
|
||||
paddingVect.push_back(insets.top() * pixelRatio);
|
||||
paddingVect.push_back(insets.right() * pixelRatio);
|
||||
paddingVect.push_back(insets.bottom() * pixelRatio);
|
||||
padding.SetRegion<std::vector<jni::jdouble>>(env, 0, paddingVect);
|
||||
|
||||
return javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees, padding);
|
||||
}
|
||||
|
||||
mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, const jni::Object<CameraPosition>& position, float pixelRatio) {
|
||||
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
|
||||
static auto bearing = javaClass.GetField<jni::jdouble>(env, "bearing");
|
||||
static auto target = javaClass.GetField<jni::Object<LatLng>>(env, "target");
|
||||
static auto tilt = javaClass.GetField<jni::jdouble>(env, "tilt");
|
||||
static auto zoom = javaClass.GetField<jni::jdouble>(env, "zoom");
|
||||
static auto paddingField = javaClass.GetField<jni::Array<jni::jdouble>>(env, "padding");
|
||||
|
||||
auto padding = position.Get(env, paddingField);
|
||||
auto center = LatLng::getLatLng(env, position.Get(env, target));
|
||||
|
||||
return mbgl::CameraOptions{center,
|
||||
padding && padding.Length(env) == 4 ? EdgeInsets{padding.Get(env, 1) * pixelRatio,
|
||||
padding.Get(env, 0) * pixelRatio,
|
||||
padding.Get(env, 3) * pixelRatio,
|
||||
padding.Get(env, 2) * pixelRatio}
|
||||
: (EdgeInsets){},
|
||||
{},
|
||||
position.Get(env, zoom),
|
||||
position.Get(env, bearing),
|
||||
position.Get(env, tilt)};
|
||||
}
|
||||
|
||||
void CameraPosition::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<CameraPosition>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mb
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class CameraPosition : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/camera/CameraPosition"; };
|
||||
|
||||
static jni::Local<jni::Object<CameraPosition>> New(jni::JNIEnv&, mbgl::CameraOptions, float pixelRatio);
|
||||
|
||||
static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, const jni::Object<CameraPosition>&, float pixelRatio);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
76
platform/android/MapboxGLAndroidSDK/src/cpp/map/image.cpp
Normal file
76
platform/android/MapboxGLAndroidSDK/src/cpp/map/image.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#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");
|
||||
static auto contentField = javaClass.GetField<jni::Array<jfloat >>(env, "content");
|
||||
static auto stretchXField = javaClass.GetField<jni::Array<jfloat>>(env, "stretchX");
|
||||
static auto stretchYField = javaClass.GetField<jni::Array<jfloat>>(env, "stretchY");
|
||||
|
||||
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);
|
||||
auto content = image.Get(env, contentField);
|
||||
auto stretchX = image.Get(env, stretchXField);
|
||||
auto stretchY = image.Get(env, stretchYField);
|
||||
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()));
|
||||
|
||||
style::ImageStretches imageStretchesX = {};
|
||||
style::ImageStretches imageStretchesY = {};
|
||||
if (stretchX.get()) {
|
||||
std::size_t sizeX = stretchX.Length(env);
|
||||
for (jni::jsize i = 0; i < sizeX - 1; i += 2) {
|
||||
imageStretchesX.push_back({stretchX.Get(env, i), stretchX.Get(env, i + 1)});
|
||||
}
|
||||
}
|
||||
if (stretchY.get()) {
|
||||
std::size_t sizeY = stretchY.Length(env);
|
||||
for (jni::jsize i = 0; i < sizeY - 1; i += 2) {
|
||||
imageStretchesY.push_back({stretchY.Get(env, i), stretchY.Get(env, i + 1)});
|
||||
}
|
||||
}
|
||||
|
||||
if (content) {
|
||||
const style::ImageContent imageContent = style::ImageContent{content.Get(env, 0),
|
||||
content.Get(env, 1),
|
||||
content.Get(env, 2),
|
||||
content.Get(env, 3)};
|
||||
return mbgl::style::Image{name, std::move(premultipliedImage), pixelRatio, sdf,
|
||||
imageStretchesX,
|
||||
imageStretchesY,
|
||||
std::move(imageContent)};
|
||||
}
|
||||
|
||||
return mbgl::style::Image{name, std::move(premultipliedImage), pixelRatio, sdf,
|
||||
imageStretchesX,
|
||||
imageStretchesY};
|
||||
}
|
||||
|
||||
void Image::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Image>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mb
|
||||
21
platform/android/MapboxGLAndroidSDK/src/cpp/map/image.hpp
Normal file
21
platform/android/MapboxGLAndroidSDK/src/cpp/map/image.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include <mbgl/style/image.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Image : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/Image"; };
|
||||
|
||||
static mbgl::style::Image getImage(jni::JNIEnv&, const jni::Object<Image>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
269
platform/android/MapboxGLAndroidSDK/src/cpp/map_renderer.cpp
Normal file
269
platform/android/MapboxGLAndroidSDK/src/cpp/map_renderer.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
#include "map_renderer.hpp"
|
||||
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/logging.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() {
|
||||
try {
|
||||
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();
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, "MapRenderer::reset failed: %s", exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
ActorRef<Renderer> MapRenderer::actor() const {
|
||||
return *rendererRef;
|
||||
}
|
||||
|
||||
void MapRenderer::schedule(std::function<void()> scheduled) {
|
||||
try {
|
||||
// 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();
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, "MapRenderer::schedule failed: %s", exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::requestRender() {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, "MapRenderer::requestRender failed: %s", exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::update(std::shared_ptr<UpdateParameters> params) {
|
||||
try {
|
||||
// Lock on the parameters
|
||||
std::lock_guard<std::mutex> lock(updateMutex);
|
||||
updateParameters = std::move(params);
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, "MapRenderer::update failed: %s", exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::setObserver(std::shared_ptr<RendererObserver> _rendererObserver) {
|
||||
try {
|
||||
// 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());
|
||||
}
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, "MapRenderer::setObserver failed: %s", exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
backend.reset();
|
||||
}
|
||||
|
||||
void MapRenderer::scheduleSnapshot(std::unique_ptr<SnapshotCallback> callback) {
|
||||
snapshotCallback = std::move(callback);
|
||||
requestRender();
|
||||
}
|
||||
|
||||
void MapRenderer::render(JNIEnv&) {
|
||||
assert (renderer);
|
||||
|
||||
std::shared_ptr<UpdateParameters> params;
|
||||
{
|
||||
// Lock on the parameters
|
||||
std::unique_lock<std::mutex> lock(updateMutex);
|
||||
if (!updateParameters) return;
|
||||
|
||||
// Hold on to the update parameters during render
|
||||
params = updateParameters;
|
||||
}
|
||||
|
||||
// Activate the backend
|
||||
gfx::BackendScope backendGuard { *backend };
|
||||
|
||||
// Ensure that the "current" scheduler on the render thread is
|
||||
// this scheduler.
|
||||
Scheduler::SetCurrent(this);
|
||||
|
||||
if (framebufferSizeChanged) {
|
||||
backend->updateViewPort();
|
||||
framebufferSizeChanged = false;
|
||||
}
|
||||
|
||||
renderer->render(params);
|
||||
|
||||
// Deliver the snapshot if requested
|
||||
if (snapshotCallback) {
|
||||
snapshotCallback->operator()(backend->readFramebuffer());
|
||||
snapshotCallback.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::onSurfaceCreated(JNIEnv&) {
|
||||
// Lock as the initialization can come from the main thread or the GL thread first
|
||||
std::lock_guard<std::mutex> lock(initialisationMutex);
|
||||
|
||||
// The GL context is already active if get a new surface.
|
||||
gfx::BackendScope backendGuard { *backend, gfx::BackendScope::ScopeType::Implicit };
|
||||
|
||||
// The android system will have already destroyed the underlying
|
||||
// GL resources if this is not the first initialization and an
|
||||
// attempt to clean them up will fail
|
||||
if (backend) backend->markContextLost();
|
||||
if (renderer) renderer->markContextLost();
|
||||
|
||||
// Reset in opposite order
|
||||
renderer.reset();
|
||||
backend.reset();
|
||||
|
||||
// Create the new backend and renderer
|
||||
backend = std::make_unique<AndroidRendererBackend>();
|
||||
renderer = std::make_unique<Renderer>(*backend, pixelRatio, localIdeographFontFamily);
|
||||
rendererRef = std::make_unique<ActorRef<Renderer>>(*renderer, mailboxData.getMailbox());
|
||||
|
||||
// Set the observer on the new Renderer implementation
|
||||
if (rendererObserver) {
|
||||
renderer->setObserver(rendererObserver.get());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::onSurfaceChanged(JNIEnv& env, jint width, jint height) {
|
||||
if (!renderer) {
|
||||
// In case the surface has been destroyed (due to app back-grounding)
|
||||
onSurfaceCreated(env);
|
||||
}
|
||||
|
||||
backend->resizeFramebuffer(width, height);
|
||||
framebufferSizeChanged = true;
|
||||
requestRender();
|
||||
}
|
||||
|
||||
void MapRenderer::onRendererReset(JNIEnv&) {
|
||||
// Make sure to destroy the renderer on the GL Thread
|
||||
auto self = ActorRef<MapRenderer>(*this, mailboxData.getMailbox());
|
||||
self.ask(&MapRenderer::resetRenderer).wait();
|
||||
}
|
||||
|
||||
// needs to be called on GL thread
|
||||
void MapRenderer::onSurfaceDestroyed(JNIEnv&) {
|
||||
resetRenderer();
|
||||
}
|
||||
|
||||
// Static methods //
|
||||
|
||||
void MapRenderer::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<MapRenderer>(env, javaClass, "nativePtr",
|
||||
jni::MakePeer<MapRenderer, const jni::Object<MapRenderer>&, jni::jfloat, const jni::String&>,
|
||||
"nativeInitialize", "finalize",
|
||||
METHOD(&MapRenderer::render, "nativeRender"),
|
||||
METHOD(&MapRenderer::onRendererReset, "nativeReset"),
|
||||
METHOD(&MapRenderer::onSurfaceCreated,
|
||||
"nativeOnSurfaceCreated"),
|
||||
METHOD(&MapRenderer::onSurfaceChanged,
|
||||
"nativeOnSurfaceChanged"),
|
||||
METHOD(&MapRenderer::onSurfaceDestroyed,
|
||||
"nativeOnSurfaceDestroyed"));
|
||||
}
|
||||
|
||||
MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, const jni::Object<MapRenderer>& jObject) {
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
|
||||
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
|
||||
MapRenderer* mapRenderer = reinterpret_cast<MapRenderer*>(jObject.Get(env, field));
|
||||
assert(mapRenderer != nullptr);
|
||||
return *mapRenderer;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
138
platform/android/MapboxGLAndroidSDK/src/cpp/map_renderer.hpp
Normal file
138
platform/android/MapboxGLAndroidSDK/src/cpp/map_renderer.hpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/actor_ref.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <class>
|
||||
class ActorRef;
|
||||
class Mailbox;
|
||||
class Renderer;
|
||||
class RendererBackend;
|
||||
class RendererObserver;
|
||||
class ThreadPool;
|
||||
class UpdateParameters;
|
||||
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererBackend;
|
||||
|
||||
/**
|
||||
* The MapRenderer is a peer class that encapsulates the actions
|
||||
* performed on the GL Thread.
|
||||
*
|
||||
* The public methods are safe to call from the main thread, others are not.
|
||||
*/
|
||||
class MapRenderer : public Scheduler {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRenderer"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
static MapRenderer& getNativePeer(JNIEnv&, const jni::Object<MapRenderer>&);
|
||||
|
||||
MapRenderer(jni::JNIEnv& _env,
|
||||
const jni::Object<MapRenderer>&,
|
||||
jni::jfloat pixelRatio,
|
||||
const jni::String& localIdeographFontFamily);
|
||||
|
||||
~MapRenderer() override;
|
||||
|
||||
// Resets the renderer to clean up on the calling thread
|
||||
void reset();
|
||||
|
||||
// Takes the RendererObserver by shared_ptr so we
|
||||
// don't have to make the header public. Use
|
||||
// this instead of Renderer#setObserver directly
|
||||
void setObserver(std::shared_ptr<RendererObserver>);
|
||||
|
||||
// Sets the new update parameters to use on subsequent
|
||||
// renders. Be sure to trigger a render with
|
||||
// requestRender().
|
||||
void update(std::shared_ptr<UpdateParameters>);
|
||||
|
||||
// Gives a handle to the Renderer to enable actions on
|
||||
// any thread.
|
||||
ActorRef<Renderer> actor() const;
|
||||
|
||||
// From Scheduler. Schedules by using callbacks to the
|
||||
// JVM to process the mailbox on the right thread.
|
||||
void schedule(std::function<void()> scheduled) override;
|
||||
mapbox::base::WeakPtr<Scheduler> makeWeakPtr() override { return weakFactory.makeWeakPtr(); }
|
||||
|
||||
void requestRender();
|
||||
|
||||
// Snapshot - requires a RunLoop on the calling thread
|
||||
using SnapshotCallback = std::function<void (PremultipliedImage)>;
|
||||
void requestSnapshot(SnapshotCallback);
|
||||
|
||||
protected:
|
||||
// Called from the GL Thread //
|
||||
|
||||
void scheduleSnapshot(std::unique_ptr<SnapshotCallback>);
|
||||
|
||||
private:
|
||||
struct MailboxData {
|
||||
explicit MailboxData(Scheduler*);
|
||||
std::shared_ptr<Mailbox> getMailbox() const noexcept;
|
||||
|
||||
private:
|
||||
Scheduler* scheduler;
|
||||
mutable std::shared_ptr<Mailbox> mailbox;
|
||||
};
|
||||
// Called from the GL Thread //
|
||||
|
||||
// Resets the renderer
|
||||
void resetRenderer();
|
||||
|
||||
// Renders a frame.
|
||||
void render(JNIEnv&);
|
||||
|
||||
void onSurfaceCreated(JNIEnv&);
|
||||
|
||||
void onSurfaceChanged(JNIEnv&, jint width, jint height);
|
||||
|
||||
void onSurfaceDestroyed(JNIEnv&);
|
||||
|
||||
private:
|
||||
// Called on either Main or GL thread //
|
||||
void onRendererReset(JNIEnv&);
|
||||
|
||||
private:
|
||||
jni::WeakReference<jni::Object<MapRenderer>, jni::EnvAttachingDeleter> javaPeer;
|
||||
|
||||
float pixelRatio;
|
||||
optional<std::string> localIdeographFontFamily;
|
||||
|
||||
std::shared_ptr<ThreadPool> threadPool;
|
||||
const MailboxData mailboxData;
|
||||
|
||||
std::mutex initialisationMutex;
|
||||
std::shared_ptr<RendererObserver> rendererObserver;
|
||||
|
||||
std::unique_ptr<AndroidRendererBackend> backend;
|
||||
std::unique_ptr<Renderer> renderer;
|
||||
std::unique_ptr<ActorRef<Renderer>> rendererRef;
|
||||
|
||||
std::shared_ptr<UpdateParameters> updateParameters;
|
||||
std::mutex updateMutex;
|
||||
|
||||
bool framebufferSizeChanged = false;
|
||||
std::atomic<bool> destroyed {false};
|
||||
|
||||
std::unique_ptr<SnapshotCallback> snapshotCallback;
|
||||
mapbox::base::WeakPtrFactory<Scheduler> weakFactory{this};
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "map_renderer_runnable.hpp"
|
||||
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::function<void()> function_)
|
||||
: function(std::move(function_)) {
|
||||
// Create the Java peer and hold on to a global reference
|
||||
// Not using a weak reference here as this might oerflow
|
||||
// the weak reference table on some devices
|
||||
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 5);
|
||||
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jlong>(env);
|
||||
auto instance = javaClass.New(env, constructor, reinterpret_cast<jlong>(this));
|
||||
javaPeer = jni::NewGlobal(env, instance);
|
||||
}
|
||||
|
||||
MapRendererRunnable::~MapRendererRunnable() = default;
|
||||
|
||||
void MapRendererRunnable::run(jni::JNIEnv&) {
|
||||
if (function) function();
|
||||
}
|
||||
|
||||
jni::Global<jni::Object<MapRendererRunnable>> MapRendererRunnable::peer() {
|
||||
return std::move(javaPeer);
|
||||
}
|
||||
|
||||
// Static methods //
|
||||
|
||||
void MapRendererRunnable::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<MapRendererRunnable>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
std::make_unique<MapRendererRunnable, JNIEnv&>,
|
||||
"nativeInitialize",
|
||||
"finalize",
|
||||
METHOD(&MapRendererRunnable::run, "run"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/mailbox.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* The MapRendererRunnable is a peer class that encapsulates
|
||||
* a scheduled mailbox in a Java Runnable so it can be
|
||||
* scheduled on the map renderer thread.
|
||||
*
|
||||
*/
|
||||
class MapRendererRunnable {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRendererRunnable"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
MapRendererRunnable(jni::JNIEnv&, std::function<void()>);
|
||||
|
||||
// Only for jni registration, unused
|
||||
MapRendererRunnable(jni::JNIEnv&) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
~MapRendererRunnable();
|
||||
|
||||
void run(jni::JNIEnv&);
|
||||
|
||||
// Transfers ownership of the Peer object to the caller
|
||||
jni::Global<jni::Object<MapRendererRunnable>> peer();
|
||||
|
||||
private:
|
||||
jni::Global<jni::Object<MapRendererRunnable>> javaPeer;
|
||||
std::function<void()> function;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
23
platform/android/MapboxGLAndroidSDK/src/cpp/mapbox.cpp
Normal file
23
platform/android/MapboxGLAndroidSDK/src/cpp/mapbox.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "mapbox.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<AssetManager>> Mapbox::getAssetManager(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<Mapbox>::Singleton(env);
|
||||
auto method = javaClass.GetStaticMethod<jni::Object<AssetManager>()>(env, "getAssetManager");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
jboolean Mapbox::hasInstance(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<Mapbox>::Singleton(env);
|
||||
auto method = javaClass.GetStaticMethod<jboolean()>(env, "hasInstance");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
void Mapbox::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Mapbox>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user