Replacing hardcoded configuration with configurable API and removing Mapbox assets (#90)

* Refactoring online file source so that tile server configuration is not hardcoded - part 1

* Added default templates

* Update from master

* Renaming MGLAccountManager to MGLSettings. Passing ResourceOptions and TileServerOptions to relevant classes and method in order to remove mapbox hardocded configuration

* Fixing build

* Addedm missing theme

* Unit tests fixes

* Fixing unit tests, adding factory methods for creating predefined configuration.

* Fixing mapbox unit tests

* Additional unit test fixes

* Making MapboxConfiguration default

* Making get/set resource options available in all classes that inherits from FileSource

* Making get/set resource options available in all classes that inherits from FileSource - part 2

* Fixes for Android

* Disable test coverage reports

* Disable test coverage reports

* Disable test coverage reports

* Disable test coverage reports

* Removing hardcoded configuration in iOS project - part 1

* Fixing wrong file extension, making use of tile server options.

* Use apiKey and MGL_API_KEY everywhere

* Just a rename

* Re-enabling tests and improving MGLSettings init

* Removing mapbox hardcoded configuration, using api key everywhere, implementing JNI conversion for TileServerOptions

* Lint issues.

* Integrating configurable tile server properties into Android SDK - part 2

* Removing mabox accounts

* Exposing multiple configurations to Android SDK - bug fixes

* Removing TileServerOptions from public interface - native methods dont work before mapbox-gl library is loaded

* Adding support for configurable predefined styles

* Migrating predefined styles in test app + cleanup

* Parameter fix

* Bug fixes

* Fixing render test build

* Fixing offline tester

* Fixing benchmark tool

* Fix: typo in method name

* Adding code for public access to TileServerOptions

* Bug fixes and debug code removal

* Fixes for macOS, adding unit tests from MapLibre, removing redundant members from OnlineFileSource

* Unit test fixes

* MacOS test app - migrating to configurable tile server options, part 1

* Fixing offline maps

* Migrating macOS test app to MapTiler

* Minor improvements

* Putting back apiKey test

* Added unit tests for MapTiler configuration

* Migrating test resources to MapTiler

* minor fix

* A few fixes

* Fixing macOS tests, removing feedback functionality

* Migrating ios test app to MapTiler

* Migrating ui tests

* UI tests fix

* Benchmarking app fix

* Cleanup and strings updates

* Migrating benchmark app to maptiler

* API key injection in benchmark app

* Putting back release configuration

* Additional tests and fixing issues identified by thread sanitizer.

* Removing test filters

* Fixes and addressing lint issues

* More Maptiler tests + minro fix

* Android instrumentation test migration to MapTiler. Exposing missing TileServerOptions in Android SDK. Minor fixes.

* No requirements on API key format.

* Fixing offline cache test tool

* Adding configurable domain name for sources, adding source domain int MapTiler configuration, cleanup

* Migrating tests to MapTiler, adding code for canonicalizing URLs, removing mapbox stuff from comments, cleanup

* More tests

* Updated database size

* Lint issues

* Fixed test

* Updating developer config API key

* Fixes for Android, propagaing updated tileServerOptions to native file sources, more tests

* Just a few more fixes

* Propagating updated settings to file sources + additional unit test

* Lint issues

* Removing test filter and fixing incorrect uri

* Release preparation

* macos release notes
This commit is contained in:
Petr Pokorny
2021-06-29 12:44:51 +02:00
committed by GitHub
parent 9a49fa16c9
commit d62ff400c6
398 changed files with 107907 additions and 184517 deletions

View File

@@ -96,12 +96,12 @@ jobs:
- name: Build Test APK
run: |
MAPBOX_DEVELOPER_CONFIG_XML='${{ secrets.MAPBOX_DEVELOPER_CONFIG_XML }}'
if [ -n "${MAPBOX_DEVELOPER_CONFIG_XML}" ]; then
echo "${MAPBOX_DEVELOPER_CONFIG_XML}" > MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml
MAPLIBRE_DEVELOPER_CONFIG_XML='${{ secrets.MAPLIBRE_DEVELOPER_CONFIG_XML }}'
if [ -n "${MAPLIBRE_DEVELOPER_CONFIG_XML}" ]; then
echo "${MAPLIBRE_DEVELOPER_CONFIG_XML}" > MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml
make android-ui-test-arm-v8
else
echo "No secrets.MAPBOX_DEVELOPER_CONFIG_XML variable set, skipping apk build..."
echo "No secrets.MAPLIBRE_DEVELOPER_CONFIG_XML variable set, skipping apk build..."
fi
shell: bash
@@ -127,7 +127,7 @@ jobs:
--app MapboxGLAndroidSDKTestApp/build/outputs/apk/debug/MapboxGLAndroidSDKTestApp-debug.apk \
--test MapboxGLAndroidSDKTestApp/build/outputs/apk/androidTest/debug/MapboxGLAndroidSDKTestApp-debug-androidTest.apk \
--device-ids sailfish --os-version-ids 26 --locales en --orientations portrait --timeout 20m \
--environment-variables coverage=true,coverageFile="/sdcard/coverage.ec" --directories-to-pull /sdcard --results-dir mapbox-android-sdk-${CIRCLE_BUILD_NUM}
--environment-variables coverage=true,coverageFile="/sdcard/coverage.ec" --directories-to-pull /sdcard --results-dir maplibre-android-sdk-${{ github.run_number }}
else
echo "No secrets.GLCLOUD_SERVICE_JSON variable set, skipping instrumentation tests..."
fi

View File

@@ -98,12 +98,12 @@ jobs:
- name: Build release Test App
run: |
MAPBOX_DEVELOPER_CONFIG_XML='${{ secrets.MAPBOX_DEVELOPER_CONFIG_XML }}'
if [ -n "${MAPBOX_DEVELOPER_CONFIG_XML}" ]; then
echo "${MAPBOX_DEVELOPER_CONFIG_XML}" > MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml
MAPLIBRE_DEVELOPER_CONFIG_XML='${{ secrets.MAPLIBRE_DEVELOPER_CONFIG_XML }}'
if [ -n "${MAPLIBRE_DEVELOPER_CONFIG_XML}" ]; then
echo "${MAPLIBRE_DEVELOPER_CONFIG_XML}" > MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml
make android
else
echo "No secrets.MAPBOX_DEVELOPER_CONFIG_XML variable set, skipping apk build..."
echo "No secrets.MAPLIBRE_DEVELOPER_CONFIG_XML variable set, skipping apk build..."
fi
shell: bash

9
.gitignore vendored
View File

@@ -25,4 +25,13 @@
/new_offline.db
*.gpg
/.vscode
/platform/android/node_modules
/platform/android/signing-key.text
/platform/android/.java-version
*.hprof
/platform/ios/platform/ios/benchmark/assets/tiles/tiles
/platform/ios/platform/ios/benchmark/assets/glyphs/Roboto Regular,Noto Sans Regular
/platform/ios/platform/ios/benchmark/assets/glyphs/Roboto Medium,Noto Sans Regular
/platform/ios/platform/ios/benchmark/assets/glyphs/Roboto Condensed Italic,Noto Sans Italic
/platform/ios/platform/ios/benchmark/assets/glyphs/Noto Sans Regular
/platform/android/key.json

View File

@@ -267,6 +267,8 @@ add_library(
${PROJECT_SOURCE_DIR}/include/mbgl/util/run_loop.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/size.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/string.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/default_style.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/tile_server_options.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/thread.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/tileset.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/timer.hpp
@@ -529,7 +531,7 @@ add_library(
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_parser.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_parser.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/storage/asset_file_source.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/storage/mbtiles_file_source.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/storage/mbtiles_file_source.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/storage/file_source_manager.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/storage/http_file_source.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/storage/local_file_source.hpp
@@ -810,6 +812,8 @@ add_library(
${PROJECT_SOURCE_DIR}/src/mbgl/util/tile_cover_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/util/tile_cover_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/util/tile_range.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/util/default_style.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/util/tile_server_options.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/util/tiny_sdf.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/util/tiny_sdf.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/util/token.hpp

View File

@@ -32,7 +32,7 @@ public:
HeadlessFrontend frontend { { 1000, 1000 }, 1 };
Map map { frontend, MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()),
ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withAccessToken("foobar") };
ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withApiKey("foobar") };
ScreenBox box{{ 0, 0 }, { 1000, 1000 }};
};

View File

@@ -57,7 +57,7 @@ static void API_renderStill_reuse_map(::benchmark::State& state) {
HeadlessFrontend frontend { size, pixelRatio };
Map map { frontend, MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
ResourceOptions().withCachePath(cachePath).withApiKey("foobar") };
prepare(map);
for (auto _ : state) {
@@ -70,7 +70,7 @@ static void API_renderStill_reuse_map_formatted_labels(::benchmark::State& state
HeadlessFrontend frontend { size, pixelRatio };
Map map { frontend, MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
ResourceOptions().withCachePath(cachePath).withApiKey("foobar") };
prepare(map, util::read_file("benchmark/fixtures/api/style_formatted_labels.json"));
for (auto _ : state) {
@@ -83,7 +83,7 @@ static void API_renderStill_reuse_map_switch_styles(::benchmark::State& state) {
HeadlessFrontend frontend { size, pixelRatio };
Map map { frontend, MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
ResourceOptions().withCachePath(cachePath).withApiKey("foobar") };
for (auto _ : state) {
prepare(map, { "{}" });
@@ -100,7 +100,7 @@ static void API_renderStill_recreate_map(::benchmark::State& state) {
HeadlessFrontend frontend { size, pixelRatio };
Map map { frontend, MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
ResourceOptions().withCachePath(cachePath).withApiKey("foobar") };
prepare(map);
frontend.render(map);
}
@@ -114,7 +114,7 @@ static void API_renderStill_recreate_map_2(::benchmark::State& state) {
Map map{frontend,
MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
ResourceOptions().withCachePath(cachePath).withAccessToken("foobar")};
ResourceOptions().withCachePath(cachePath).withApiKey("foobar")};
prepare_map2(map);
frontend.render(map);
}
@@ -127,7 +127,7 @@ static void API_renderStill_multiple_sources(::benchmark::State& state) {
Map map{frontend,
MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
ResourceOptions().withCachePath(cachePath).withAccessToken("foobar")};
ResourceOptions().withCachePath(cachePath).withApiKey("foobar")};
prepare(map);
auto& style = map.getStyle();
const int kSourcesCount = 50;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -56,7 +56,7 @@ public:
}
mbgl::Response response;
mbgl::OfflineDatabase db{":memory:"};
mbgl::OfflineDatabase db{":memory:", mbgl::TileServerOptions::DefaultConfiguration()};
const unsigned tileCount = 100;
int64_t regionID = 0;

View File

@@ -36,7 +36,7 @@ install(TARGETS mbgl-offline mbgl-render RUNTIME DESTINATION bin)
# FIXME: CI must have a valid token
#
# add_test(NAME mbgl-offline-tool-test COMMAND mbgl-offline -s mapbox://styles/mapbox/satellite-v9 --maxZoom=0 WORKING_DIRECTORY
# add_test(NAME mbgl-offline-tool-test COMMAND mbgl-offline -s maptiler://maps/hybrid --maxZoom=0 WORKING_DIRECTORY
# ${PROJECT_SOURCE_DIR} )
#
# add_test(NAME mbgl-render-tool-test COMMAND mbgl-render WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} )

View File

@@ -1,4 +1,3 @@
#include <mbgl/util/default_styles.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/geojson.hpp>
@@ -6,6 +5,7 @@
#include <mbgl/storage/database_file_source.hpp>
#include <mbgl/storage/file_source_manager.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/util/tile_server_options.hpp>
#include <args.hxx>
@@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
args::ArgumentParser argumentParser("Mapbox GL offline tool");
args::HelpFlag helpFlag(argumentParser, "help", "Display this help menu", {'h', "help"});
args::ValueFlag<std::string> tokenValue(argumentParser, "key", "Mapbox access token", {'t', "token"});
args::ValueFlag<std::string> tokenValue(argumentParser, "key", "API Key", {'t', "token"});
args::ValueFlag<std::string> styleValue(argumentParser, "URL", "Map stylesheet", {'s', "style"});
args::ValueFlag<std::string> outputValue(argumentParser, "file", "Output database file name", {'o', "output"});
args::ValueFlag<std::string> apiBaseValue(argumentParser, "URL", "API Base URL", {'a', "apiBaseURL"});
@@ -120,8 +120,11 @@ int main(int argc, char *argv[]) {
exit(2);
}
std::string style = styleValue ? args::get(styleValue) : mbgl::util::default_styles::streets.url;
auto mapTilerConfiguration = mbgl::TileServerOptions::MapTilerConfiguration();
std::string style = styleValue ? args::get(styleValue) : mapTilerConfiguration.defaultStyles().at(0).getUrl();
std::cout << " Style: " << style << std::endl;
mbgl::optional<std::string> mergePath = {};
if (mergePathValue) mergePath = args::get(mergePathValue);
mbgl::optional<std::string> inputDb = {};
@@ -156,17 +159,20 @@ int main(int argc, char *argv[]) {
}
}();
const char* tokenEnv = getenv("MAPBOX_ACCESS_TOKEN");
const std::string token = tokenValue ? args::get(tokenValue) : (tokenEnv ? tokenEnv : std::string());
const char* apiEnv = getenv("MGL_API_KEY");
const std::string apiKey = tokenValue ? args::get(tokenValue) : (apiEnv ? apiEnv : std::string());
const std::string apiBaseURL = apiBaseValue ? args::get(apiBaseValue) : mbgl::util::API_BASE_URL;
if (apiBaseValue) {
mapTilerConfiguration.withBaseURL(args::get(apiBaseValue));
}
util::RunLoop loop;
std::shared_ptr<DatabaseFileSource> fileSource = std::static_pointer_cast<DatabaseFileSource>(
std::shared_ptr<FileSource>(FileSourceManager::get()->getFileSource(
FileSourceType::Database,
ResourceOptions().withAccessToken(token).withBaseURL(apiBaseURL).withCachePath(output))));
ResourceOptions().withApiKey(apiKey)
.withTileServerOptions(mapTilerConfiguration)
.withCachePath(output))));
std::unique_ptr<OfflineRegion> region;

View File

@@ -3,16 +3,16 @@
set -e
set -o pipefail
OFFLINE=./build/macos/Release/mbgl-offline
OFFLINE=../platform/ios/build/macos/Debug/mbgl-offline
# Barcelona
$OFFLINE --north 41.4664 --west 2.0407 --south 41.2724 --east 2.2680 --output barcelona.db
$OFFLINE --north 41.4664 --west 2.0407 --south 41.2724 --east 2.2680 --output barcelona_sat.db --style mapbox://styles/mapbox/satellite-v8
$OFFLINE --north 41.4664 --west 2.0407 --south 41.2724 --east 2.2680 --output barcelona_sat.db --style maptiler://maps/hybrid
# Greater London within the M25 at zoom levels 0–15
$OFFLINE --north 51.6777 --west -0.5026 --south 51.3237 --east 0.2527 --maxZoom 15 --output london.db
$OFFLINE --north 51.6777 --west -0.5026 --south 51.3237 --east 0.2527 --maxZoom 15 --output london_sat.db --style mapbox://styles/mapbox/satellite-v8
$OFFLINE --north 51.6777 --west -0.5026 --south 51.3237 --east 0.2527 --maxZoom 15 --output london_sat.db --style maptiler://maps/hybrid
# The contiguous United States at zoom levels 0–9
$OFFLINE --north 49.6107 --west -125.5078 --south 24.2870 --east -66.3574 --maxZoom 9 --output us.db
$OFFLINE --north 49.6107 --west -125.5078 --south 24.2870 --east -66.3574 --maxZoom 9 --output us_sat.db --style mapbox://styles/mapbox/satellite-v8
$OFFLINE --north 49.6107 --west -125.5078 --south 24.2870 --east -66.3574 --maxZoom 9 --output us_sat.db --style maptiler://maps/hybrid

View File

@@ -19,7 +19,7 @@ int main(int argc, char *argv[]) {
args::HelpFlag helpFlag(argumentParser, "help", "Display this help menu", {"help"});
args::ValueFlag<std::string> backendValue(argumentParser, "Backend", "Rendering backend", {"backend"});
args::ValueFlag<std::string> tokenValue(argumentParser, "key", "Mapbox access token", {'t', "token"});
args::ValueFlag<std::string> apikeyValue(argumentParser, "key", "API key", {'t', "apikey"});
args::ValueFlag<std::string> styleValue(argumentParser, "URL", "Map stylesheet", {'s', "style"});
args::ValueFlag<std::string> outputValue(argumentParser, "file", "Output file name", {'o', "output"});
args::ValueFlag<std::string> cacheValue(argumentParser, "file", "Cache database file name", {'c', "cache"});
@@ -67,9 +67,9 @@ int main(int argc, char *argv[]) {
const std::string cache_file = cacheValue ? args::get(cacheValue) : "cache.sqlite";
const std::string asset_root = assetsValue ? args::get(assetsValue) : ".";
// Try to load the token from the environment.
const char* tokenEnv = getenv("MAPBOX_ACCESS_TOKEN");
const std::string token = tokenValue ? args::get(tokenValue) : (tokenEnv ? tokenEnv : std::string());
// Try to load the apikey from the environment.
const char* apikeyEnv = getenv("MGL_API_KEY");
const std::string apikey = apikeyValue ? args::get(apikeyValue) : (apikeyEnv ? apikeyEnv : std::string());
const bool debug = debugFlag ? args::get(debugFlag) : false;
@@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
HeadlessFrontend frontend({ width, height }, pixelRatio);
Map map(frontend, MapObserver::nullObserver(),
MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()).withPixelRatio(pixelRatio),
ResourceOptions().withCachePath(cache_file).withAssetPath(asset_root).withAccessToken(std::string(token)));
ResourceOptions().withCachePath(cache_file).withAssetPath(asset_root).withApiKey(std::string(apikey)));
if (style.find("://") == std::string::npos) {
style = std::string("file://") + style;

View File

@@ -4,6 +4,7 @@
#include <mbgl/storage/offline.hpp>
#include <mbgl/util/expected.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/storage/resource_options.hpp>
namespace mbgl {
@@ -232,6 +233,9 @@ public:
*/
virtual void setOfflineMapboxTileCountLimit(uint64_t) const;
void setResourceOptions(ResourceOptions) override;
ResourceOptions getResourceOptions() override;
private:
class Impl;
const std::unique_ptr<Impl> impl;

View File

@@ -2,6 +2,7 @@
#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mapbox/compatibility/value.hpp>
@@ -33,7 +34,6 @@ enum FileSourceType : uint8_t {
// GeoJSONSource, RasterSource, VectorSource, CustomGeometrySource and other *Sources.
class FileSource {
public:
FileSource(const FileSource&) = delete;
FileSource& operator=(const FileSource&) = delete;
virtual ~FileSource() = default;
@@ -87,6 +87,11 @@ public:
// When supported, sets the modifier of the requested resources.
virtual void setResourceTransform(ResourceTransform) {} // NOLINT(performance-unnecessary-value-param)
// sets the resource options
virtual void setResourceOptions(ResourceOptions) = 0;
// gets the resource options
virtual ResourceOptions getResourceOptions() = 0;
protected:
FileSource() = default;
};
@@ -95,7 +100,7 @@ protected:
// Property name to set / get an access token.
// type: std::string
constexpr const char* ACCESS_TOKEN_KEY = "access-token";
constexpr const char* API_KEY_KEY = "api-tkey";
// Property name to set / get base url.
// type: std::string

View File

@@ -1,14 +1,17 @@
#pragma once
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
class OnlineFileSource : public FileSource {
public:
OnlineFileSource();
OnlineFileSource(const ResourceOptions& options);
~OnlineFileSource() override;
void setResourceOptions(ResourceOptions) override;
ResourceOptions getResourceOptions() override;
private:
// FileSource overrides

View File

@@ -2,6 +2,7 @@
#include <memory>
#include <string>
#include <mbgl/util/tile_server_options.hpp>
namespace mbgl {
@@ -17,6 +18,7 @@ public:
~ResourceOptions();
ResourceOptions(ResourceOptions&&) noexcept;
ResourceOptions& operator=(ResourceOptions& options);
ResourceOptions clone() const;
@@ -26,29 +28,29 @@ public:
* @param token Mapbox access token.
* @return ResourceOptions for chaining options together.
*/
ResourceOptions& withAccessToken(std::string token);
ResourceOptions& withApiKey(std::string token);
/**
* @brief Gets the previously set (or default) Mapbox access token.
*
* @return const std::string& Mapbox access token.
*/
const std::string& accessToken() const;
const std::string& apiKey() const;
/**
* @brief Sets the API base URL. Default is https://api.mapbox.com for Mapbox.
* @brief Sets the tile server options..
*
* @param baseURL API base URL.
* @param tileServerOptions Tile server options.
* @return ResourceOptions for chaining options together.
*/
ResourceOptions& withBaseURL(std::string baseURL);
ResourceOptions& withTileServerOptions(TileServerOptions tileServerOptions);
/**
* @brief Gets the previously set (or default) API base URL.
* @brief Gets the previously set (or default) TileServerOptions.
*
* @return const std::string& API base URL.
* @return const TileServerOptions tile server options.
*/
const std::string& baseURL() const;
const TileServerOptions tileServerOptions() const;
/**
* @brief Sets the cache path.
@@ -112,6 +114,13 @@ public:
*/
void* platformContext() const;
/**
* @brief Returns default resource options.
*
* @return Resource options.
*/
static ResourceOptions Default();
private:
ResourceOptions(const ResourceOptions&);

View File

@@ -59,7 +59,6 @@ constexpr UnitBezier DEFAULT_TRANSITION_EASE = { 0, 0, 0.25, 1 };
constexpr int DEFAULT_RATE_LIMIT_TIMEOUT = 5;
constexpr const char* API_BASE_URL = "https://api.mapbox.com";
constexpr const char* ASSET_PROTOCOL = "asset://";
constexpr const char* FILE_PROTOCOL = "file://";
constexpr const char* MBTILES_PROTOCOL = "mbtiles://";

View File

@@ -0,0 +1,25 @@
#pragma once
#include <array>
#include <string>
#include <vector>
namespace mbgl {
namespace util {
class DefaultStyle {
public:
DefaultStyle(std::string, std::string, int);
const std::string& getUrl() const;
const std::string& getName() const;
int getCurrentVersion() const;
private:
std::string url;
std::string name;
int currentVersion;
};
} // end namespace util
} // end namespace mbgl

View File

@@ -1,33 +0,0 @@
#pragma once
#include <array>
#include <string>
#include <vector>
namespace mbgl {
namespace util {
namespace default_styles {
struct DefaultStyle {
const char* url;
const char* name;
const unsigned currentVersion;
};
// clang-format off
constexpr const DefaultStyle streets = { "mapbox://styles/mapbox/streets-v11", "Streets", 11 };
constexpr const DefaultStyle outdoors = { "mapbox://styles/mapbox/outdoors-v11", "Outdoors", 11 };
constexpr const DefaultStyle light = { "mapbox://styles/mapbox/light-v10", "Light", 10 };
constexpr const DefaultStyle dark = { "mapbox://styles/mapbox/dark-v10", "Dark", 10 };
constexpr const DefaultStyle satellite = { "mapbox://styles/mapbox/satellite-v9", "Satellite", 9 };
constexpr const DefaultStyle satelliteStreets = { "mapbox://styles/mapbox/satellite-streets-v11", "Satellite Streets", 11 };
// clang-format on
constexpr std::array<const DefaultStyle, 6> orderedStyles = {
{streets, outdoors, light, dark, satellite, satelliteStreets}};
constexpr size_t numOrderedStyles = orderedStyles.size();
} // end namespace default_styles
} // end namespace util
} // end namespace mbgl

View File

@@ -0,0 +1,288 @@
#pragma once
#include <string>
#include <memory>
#include <mbgl/util/default_style.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
/**
* @brief Holds values for tile server options.
*/
class TileServerOptions final {
public:
/**
* @brief Constructs a TileServerOptions object with default values.
*/
explicit TileServerOptions();
~TileServerOptions();
// movable
TileServerOptions(TileServerOptions&& options) noexcept;
TileServerOptions& operator=(TileServerOptions&& options) noexcept;
// copyable
TileServerOptions(const TileServerOptions&);
TileServerOptions clone() const;
/**
* @brief Sets the API base URL.
*
* @param baseURL API base URL.
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withBaseURL(std::string baseURL);
/**
* @brief Gets the previously set (or default) API base URL.
*
* @return const std::string& API base URL.
*/
const std::string& baseURL() const;
/**
* @brief Sets the scheme alias for the tile server. For example maptiler:// for MapTiler.
*
* @param alias The URI alias.
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withUriSchemeAlias(std::string alias);
/**
* @brief Gets the previously set (or default) tile server URI alias.
*
* @return const std::string& scheme alias.
*/
const std::string& uriSchemeAlias() const;
/**
* @brief Sets the template for sources.
*
* @param sourceTemplate The source template.
* @param domainName The domain name.
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withSourceTemplate(std::string sourceTemplate, std::string domainName, optional<std::string> versionPrefix);
/**
* @brief Gets the previously set (or default) source template.
*
* @return const std::string& source template.
*/
const std::string& sourceTemplate() const;
/**
* @brief Gets the previously set (or default) source domain name
*
* @return const std::string& source domain name.
*/
const std::string& sourceDomainName() const;
/**
* @brief Gets the previously set (or default) version prefix
*
* @return const optional<std::string>& version prefix.
*/
const optional<std::string>& sourceVersionPrefix() const;
/**
* @brief Sets the template for styles.
*
* @param styleTemplate The style template.
* @param domainName If set, the URL domain must contain the specified string to be matched as canonical style URL .
*
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withStyleTemplate(std::string styleTemplate, std::string domainName, optional<std::string> versionPrefix);
/**
* @brief Gets the previously set (or default) style template.
*
* @return const std::string& style template.
*/
const std::string& styleTemplate() const;
/**
* @brief Gets the previously set (or default) style domain name.
*
* @return const std::string& domain name.
*/
const std::string& styleDomainName() const;
/**
* @brief Gets the previously set (or default) version prefix
*
* @return const optional<std::string>& version prefix.
*/
const optional<std::string>& styleVersionPrefix() const;
/**
* @brief Sets the template for sprites.
* @param domainName If set, the URL domain must contain the specified string to be matched as canonical sprite URL .
*
* @param spritesTemplate The sprites template.
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withSpritesTemplate(std::string spritesTemplate, std::string domainName, optional<std::string> versionPrefix);
/**
* @brief Gets the previously set (or default) sprites template.
*
* @return const std::string& sprites template.
*/
const std::string& spritesTemplate() const;
/**
* @brief Gets the previously set (or default) sprites domain name.
*
* @return const std::string& domain name.
*/
const std::string& spritesDomainName() const;
/**
* @brief Gets the previously set (or default) version prefix
*
* @return const optional<std::string>& version prefix.
*/
const optional<std::string>& spritesVersionPrefix() const;
/**
* @brief Sets the template for glyphs.
*
* @param glyphsTemplate The glyphs template.
* @param domainName If set, the URL domain must contain the specified string to be matched as canonical glyphs URL .
*
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withGlyphsTemplate(std::string glyphsTemplate, std::string domainName, optional<std::string> versionPrefix);
/**
* @brief Gets the previously set (or default) glyphs template.
*
* @return const std::string& glyphs template.
*/
const std::string& glyphsTemplate() const;
/**
* @brief Gets the previously set (or default) glyphs domain name.
*
* @return const std::string& domain name.
*/
const std::string& glyphsDomainName() const;
/**
* @brief Gets the previously set (or default) version prefix
*
* @return const optional<std::string>& version prefix.
*/
const optional<std::string>& glyphsVersionPrefix() const;
/**
* @brief Sets the template for tiles.
*
* @param tileTemplate The tile template.
* @param domainName If set, the URL domain must contain the specified string to be matched as canonical tile URL .
*
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withTileTemplate(std::string tileTemplate, std::string domainName, optional<std::string> versionPrefix);
/**
* @brief Gets the previously set (or default) tile template.
*
* @return const std::string& tile template.
*/
const std::string& tileTemplate() const;
/**
* @brief Gets the previously set (or default) tile domain name.
*
* @return const std::string& domain name.
*/
const std::string& tileDomainName() const;
/**
* @brief Gets the previously set (or default) version prefix
*
* @return const optional<std::string>& version prefix.
*/
const optional<std::string>& tileVersionPrefix() const;
/**
* @brief Sets the access token parameter name.
*
* @param apiKeyParameterName The parameter name.
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withApiKeyParameterName(std::string apiKeyParameterName);
/**
* @brief Gets the previously set (or default) apiKeyParameterName.
*
* @return const std::string& apiKeyParameterName.
*/
const std::string& apiKeyParameterName() const;
TileServerOptions& setRequiresApiKey(bool apiKeyRequired);
/**
* @brief Whether the tile server requires API key
*
* @return const bool true if API key is required
*/
bool requiresApiKey() const;
/**
* @brief Gets the default styles.
*/
const std::vector<const mbgl::util::DefaultStyle> defaultStyles() const;
/**
* @brief Sets the collection default styles.
*
* @param styles The style set.
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withDefaultStyles(std::vector<const mbgl::util::DefaultStyle> styles);
/**
* @brief Sets the default style by name. The style name must exists in defaultStyles collection
*
* @param defaultStyle The style name
* @return TileServerOptions for chaining options together.
*/
TileServerOptions& withDefaultStyle(std::string defaultStyle);
/**
* @brief Get the default style name
*/
const std::string& defaultStyle() const;
/**
* @brief Get the default configuration
*/
static TileServerOptions DefaultConfiguration();
/**
* @brief Get the tile server options configured for MapLibre.
*/
static TileServerOptions MapLibreConfiguration();
/**
* @brief Get the tile server options configured for Mapbox.
*/
static TileServerOptions MapboxConfiguration();
/**
* @brief Get the tile server options configured for MapTiler.
*/
static TileServerOptions MapTilerConfiguration();
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace mbgl

View File

@@ -2,11 +2,15 @@
MapLibre welcomes participation and contributions from everyone. Please read [`Contributing Guide`](https://github.com/maplibre/maplibre-gl-native/blob/master/CONTRIBUTING.md) to get started.
## master
## 9.5.0 - June 29, 2021
### Features
### Bug Fixes
* Replacing hardcoded configuration with configurable API and removing Mapbox assets and dependencies [#90](https://github.com/maplibre/maplibre-gl-native/pull/90)
### Other
* Migration from bintray [#77](https://github.com/maplibre/maplibre-gl-native/pull/77)
## 9.4.2 - May 6, 2021

View File

@@ -224,14 +224,14 @@ 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
#.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
## 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

View File

@@ -8,7 +8,6 @@ dependencies {
lintChecks project(":MapboxGLAndroidSDKLint")
api dependenciesList.mapboxJavaGeoJSON
api dependenciesList.mapboxAndroidGestures
api dependenciesList.mapboxAndroidAccounts
implementation dependenciesList.mapboxJavaTurf
implementation dependenciesList.supportAnnotations
@@ -106,5 +105,5 @@ 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-publish.gradle"
// Disabled to prevent timeouts
// apply from: "${rootDir}/gradle/jacoco-report.gradle"
// intentionally disabled
// apply from: "${rootDir}/gradle/jacoco-report.gradle"

View File

@@ -183,7 +183,11 @@ add_library(mapbox-gl SHARED
${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)
${PROJECT_SOURCE_DIR}/style/value.hpp
${PROJECT_SOURCE_DIR}/util/default_style.cpp
${PROJECT_SOURCE_DIR}/util/tile_server_options.cpp
${PROJECT_SOURCE_DIR}/util/default_style.hpp
${PROJECT_SOURCE_DIR}/util/tile_server_options.hpp)
target_include_directories(
mapbox-gl

View File

@@ -3,6 +3,7 @@
#include <mbgl/platform/settings.hpp>
#include <mbgl/storage/file_source_request.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/url.hpp>
@@ -15,8 +16,9 @@ namespace mbgl {
class AssetManagerFileSource::Impl {
public:
Impl(ActorRef<Impl>, AAssetManager* assetManager_) : assetManager(assetManager_) {
}
Impl(ActorRef<Impl>, AAssetManager* assetManager_, const ResourceOptions options) :
resourceOptions(options.clone()),
assetManager(assetManager_) {}
void request(const std::string& url, ActorRef<FileSourceRequest> req) {
// Note: AssetManager already prepends "assets" to the filename.
@@ -36,17 +38,28 @@ public:
req.invoke(&FileSourceRequest::setResponse, response);
}
void setResourceOptions(ResourceOptions options) {
resourceOptions = options;
}
ResourceOptions getResourceOptions() {
return resourceOptions.clone();
}
private:
AAssetManager* assetManager;
ResourceOptions resourceOptions;
};
AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env,
const jni::Object<android::AssetManager>& assetManager_)
const jni::Object<android::AssetManager>& assetManager_,
const ResourceOptions options)
: 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())))) {}
AAssetManager_fromJava(&env, jni::Unwrap(assetManager.get())),
options.clone())) {}
AssetManagerFileSource::~AssetManagerFileSource() = default;
@@ -62,4 +75,11 @@ bool AssetManagerFileSource::canRequest(const Resource& resource) const {
return 0 == resource.url.rfind(mbgl::util::ASSET_PROTOCOL, 0);
}
void AssetManagerFileSource::setResourceOptions(ResourceOptions options) {
impl->actor().invoke(&Impl::setResourceOptions, options.clone());
}
ResourceOptions AssetManagerFileSource::getResourceOptions() {
return impl->actor().ask(&Impl::getResourceOptions).get();
}
} // namespace mbgl

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/resource_options.hpp>
#include "asset_manager.hpp"
@@ -14,12 +15,15 @@ template <typename T> class Thread;
class AssetManagerFileSource : public FileSource {
public:
AssetManagerFileSource(jni::JNIEnv&, const jni::Object<android::AssetManager>&);
AssetManagerFileSource(jni::JNIEnv&, const jni::Object<android::AssetManager>&, const ResourceOptions);
~AssetManagerFileSource() override;
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
bool canRequest(const Resource&) const override;
void setResourceOptions(ResourceOptions options) override;
ResourceOptions getResourceOptions() override;
private:
class Impl;

View File

@@ -19,24 +19,27 @@ namespace android {
// FileSource //
FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const jni::String& _cachePath)
FileSource::FileSource(jni::JNIEnv& _env, const jni::String& apiKey, const jni::String& _cachePath, const jni::Object<TileServerOptions>& _options)
: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&) {
mbgl::FileSourceType::Asset, [](const mbgl::ResourceOptions& opts) {
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);
assetFileSource = std::make_unique<AssetManagerFileSource>(*env, assetManager, opts.clone());
}
return assetFileSource;
});
resourceOptions.withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "")
.withCachePath(path + DATABASE_FILE);
auto tileServerOptions = TileServerOptions::getTileServerOptions(_env, _options);
resourceOptions
.withTileServerOptions(tileServerOptions)
.withApiKey(apiKey ? jni::Make<std::string>(_env, apiKey) : "")
.withCachePath(path + DATABASE_FILE);
// Create a core file sources
// TODO: Split Android FileSource API to smaller interfaces
@@ -50,8 +53,16 @@ FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const
FileSource::~FileSource() {
}
jni::Local<jni::String> FileSource::getAccessToken(jni::JNIEnv& env) {
if (auto* token = onlineSource->getProperty(mbgl::ACCESS_TOKEN_KEY).getString()) {
void FileSource::setTileServerOptions(jni::JNIEnv& _env, const jni::Object<TileServerOptions>& _options) {
auto tileServerOptions = TileServerOptions::getTileServerOptions(_env, _options);
resourceOptions.withTileServerOptions(tileServerOptions);
resourceLoader->setResourceOptions(resourceOptions.clone());
databaseSource->setResourceOptions(resourceOptions.clone());
onlineSource->setResourceOptions(resourceOptions.clone());
}
jni::Local<jni::String> FileSource::getApiKey(jni::JNIEnv& env) {
if (auto* token = onlineSource->getProperty(mbgl::API_KEY_KEY).getString()) {
return jni::Make<jni::String>(env, *token);
}
@@ -59,9 +70,9 @@ jni::Local<jni::String> FileSource::getAccessToken(jni::JNIEnv& env) {
return jni::Make<jni::String>(env, "");
}
void FileSource::setAccessToken(jni::JNIEnv& env, const jni::String& token) {
void FileSource::setApiKey(jni::JNIEnv& env, const jni::String& token) {
if (onlineSource) {
onlineSource->setProperty(mbgl::ACCESS_TOKEN_KEY, token ? jni::Make<std::string>(env, token) : "");
onlineSource->setProperty(mbgl::API_KEY_KEY, token ? jni::Make<std::string>(env, token) : "");
} else {
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
}
@@ -75,6 +86,15 @@ void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) {
}
}
jni::Local<jni::String> FileSource::getAPIBaseUrl(jni::JNIEnv& env) {
if (auto* url = onlineSource->getProperty(mbgl::API_BASE_URL_KEY).getString()) {
return jni::Make<jni::String>(env, *url);
}
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
return jni::Make<jni::String>(env, "");
}
void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& transformCallback) {
// Core could be built without support for network resource provider.
if (!onlineSource) {
@@ -214,12 +234,14 @@ void FileSource::registerNative(jni::JNIEnv& env) {
jni::RegisterNativePeer<FileSource>(env,
javaClass,
"nativePtr",
jni::MakePeer<FileSource, const jni::String&, const jni::String&>,
jni::MakePeer<FileSource, const jni::String&, const jni::String&, const jni::Object<TileServerOptions>&>,
"initialize",
"finalize",
METHOD(&FileSource::getAccessToken, "getAccessToken"),
METHOD(&FileSource::setAccessToken, "setAccessToken"),
METHOD(&FileSource::setTileServerOptions, "setTileServerOptions"),
METHOD(&FileSource::getApiKey, "getApiKey"),
METHOD(&FileSource::setApiKey, "setApiKey"),
METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"),
METHOD(&FileSource::getAPIBaseUrl, "getApiBaseUrl"),
METHOD(&FileSource::setResourceTransform, "setResourceTransform"),
METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"),
METHOD(&FileSource::resume, "activate"),

View File

@@ -9,6 +9,8 @@
#include <jni/jni.hpp>
#include "util/tile_server_options.hpp"
namespace mbgl {
template <typename T> class Actor;
@@ -42,13 +44,17 @@ public:
const jni::String&);
};
FileSource(jni::JNIEnv&, const jni::String&, const jni::String&);
FileSource(jni::JNIEnv&, const jni::String&, const jni::String&, const jni::Object<TileServerOptions>&);
~FileSource();
jni::Local<jni::String> getAccessToken(jni::JNIEnv&);
void setTileServerOptions(jni::JNIEnv& _env, const jni::Object<TileServerOptions>& _options);
void setAccessToken(jni::JNIEnv&, const jni::String&);
jni::Local<jni::String> getApiKey(jni::JNIEnv&);
void setApiKey(jni::JNIEnv&, const jni::String&);
jni::Local<jni::String> getAPIBaseUrl(jni::JNIEnv&);
void setAPIBaseUrl(jni::JNIEnv&, const jni::String&);

View File

@@ -1,5 +1,6 @@
#include <mbgl/storage/http_file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/logging.hpp>
@@ -16,7 +17,15 @@ namespace mbgl {
class HTTPFileSource::Impl {
public:
Impl(const ResourceOptions options): resourceOptions(options.clone()){};
android::UniqueEnv env { android::AttachEnv() };
void setResourceOptions(ResourceOptions options) {resourceOptions = options;};
ResourceOptions getResourceOptions() {return resourceOptions.clone(); };
private:
ResourceOptions resourceOptions;
};
class HTTPRequest : public AsyncRequest {
@@ -182,8 +191,8 @@ void HTTPRequest::onFailure(jni::JNIEnv& env, int type, const jni::String& messa
async.send();
}
HTTPFileSource::HTTPFileSource()
: impl(std::make_unique<Impl>()) {
HTTPFileSource::HTTPFileSource(const ResourceOptions& options)
: impl(std::make_unique<Impl>(options.clone())) {
}
HTTPFileSource::~HTTPFileSource() = default;
@@ -192,4 +201,12 @@ std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource,
return std::make_unique<HTTPRequest>(*impl->env, resource, callback);
}
void HTTPFileSource::setResourceOptions(ResourceOptions options) {
impl->setResourceOptions(options.clone());
}
ResourceOptions HTTPFileSource::getResourceOptions() {
return impl->getResourceOptions();
}
} // namespace mbgl

View File

@@ -34,6 +34,7 @@
#include "map_renderer_runnable.hpp"
#include "mapbox.hpp"
#include "native_map_view.hpp"
#include "util/tile_server_options.hpp"
#ifndef MBGL_MODULE_OFFLINE_DISABLE
#include "offline/offline_manager.hpp"
#include "offline/offline_region.hpp"
@@ -162,6 +163,10 @@ void registerNatives(JavaVM *vm) {
// AssetManager
Mapbox::registerNative(env);
// Util
DefaultStyle::registerNative(env);
TileServerOptions::registerNative(env);
}
} // namespace android

View File

@@ -0,0 +1,31 @@
#include "default_style.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<DefaultStyle>> DefaultStyle::New(jni::JNIEnv& env, const mbgl::util::DefaultStyle& jDefaultStyle) {
static auto& javaClass = jni::Class<DefaultStyle>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jni::String, jni::String, int>(env);
return javaClass.New(
env,
constructor,
jni::Make<jni::String>(env, jDefaultStyle.getUrl()),
jni::Make<jni::String>(env, jDefaultStyle.getName()),
jDefaultStyle.getCurrentVersion());
}
mbgl::util::DefaultStyle DefaultStyle::getDefaultStyle(jni::JNIEnv& env, const jni::Object<DefaultStyle>& options) {
static auto& javaClass = jni::Class<DefaultStyle>::Singleton(env);
return mbgl::util::DefaultStyle (
jni::Make<std::string>(env, options.Get(env, javaClass.GetField<jni::String>(env, "url"))),
jni::Make<std::string>(env, options.Get(env, javaClass.GetField<jni::String>(env, "name"))),
options.Get(env, javaClass.GetField<int>(env, "version"))
);
}
void DefaultStyle::registerNative(jni::JNIEnv& env) {
jni::Class<DefaultStyle>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,25 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/default_style.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class DefaultStyle : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/util/DefaultStyle"; };
static jni::Local<jni::Object<DefaultStyle>> New(jni::JNIEnv&, const mbgl::util::DefaultStyle&);
static mbgl::util::DefaultStyle getDefaultStyle(jni::JNIEnv&, const jni::Object<DefaultStyle>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,178 @@
#include "tile_server_options.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<TileServerOptions>> TileServerOptions::New(jni::JNIEnv& env, const mbgl::TileServerOptions& tileServerOptions) {
static auto& javaClass = jni::Class<TileServerOptions>::Singleton(env);
static auto constructor = javaClass.GetConstructor<
jni::String, jni::String, jni::String, jni::String, jni::String, jni::String,
jni::String, jni::String, jni::String, jni::String, jni::String,
jni::String, jni::String, jni::String, jni::String, jni::String,
jni::String, jni::String, jni::jboolean, jni::String, jni::Array<jni::Object<DefaultStyle>>>(env);
optional<std::string> sourceVersionPrefixValue = tileServerOptions.sourceVersionPrefix();
optional<std::string> styleVersionPrefixValue = tileServerOptions.styleVersionPrefix();
optional<std::string> spritesVersionPrefixValue = tileServerOptions.spritesVersionPrefix();
optional<std::string> glyphsVersionPrefixValue = tileServerOptions.glyphsVersionPrefix();
optional<std::string> tileVersionPrefixValue = tileServerOptions.tileVersionPrefix();
return javaClass.New(env, constructor,
jni::Make<jni::String>(env, tileServerOptions.baseURL()),
jni::Make<jni::String>(env, tileServerOptions.uriSchemeAlias()),
jni::Make<jni::String>(env, tileServerOptions.sourceTemplate()),
jni::Make<jni::String>(env, tileServerOptions.sourceDomainName()),
sourceVersionPrefixValue ? jni::Make<jni::String>(env, *sourceVersionPrefixValue) : jni::Local<jni::String>(),
jni::Make<jni::String>(env, tileServerOptions.styleTemplate()),
jni::Make<jni::String>(env, tileServerOptions.styleDomainName()),
styleVersionPrefixValue ? jni::Make<jni::String>(env, *styleVersionPrefixValue) : jni::Local<jni::String>(),
jni::Make<jni::String>(env, tileServerOptions.spritesTemplate()),
jni::Make<jni::String>(env, tileServerOptions.spritesDomainName()),
spritesVersionPrefixValue ? jni::Make<jni::String>(env, *spritesVersionPrefixValue) : jni::Local<jni::String>(),
jni::Make<jni::String>(env, tileServerOptions.glyphsTemplate()),
jni::Make<jni::String>(env, tileServerOptions.glyphsDomainName()),
glyphsVersionPrefixValue ? jni::Make<jni::String>(env, *glyphsVersionPrefixValue) : jni::Local<jni::String>(),
jni::Make<jni::String>(env, tileServerOptions.tileTemplate()),
jni::Make<jni::String>(env, tileServerOptions.tileDomainName()),
tileVersionPrefixValue ? jni::Make<jni::String>(env, *tileVersionPrefixValue) : jni::Local<jni::String>(),
jni::Make<jni::String>(env, tileServerOptions.apiKeyParameterName()),
jni::jboolean(tileServerOptions.requiresApiKey()),
jni::Make<jni::String>(env, tileServerOptions.defaultStyle()),
TileServerOptions::NewStyles(env, tileServerOptions.defaultStyles())
);
}
jni::Local<jni::Array<jni::Object<DefaultStyle>>> TileServerOptions::NewStyles(jni::JNIEnv& env, const std::vector<const mbgl::util::DefaultStyle> nativeStyles) {
auto retVal = jni::Array<jni::Object<DefaultStyle>>::New(env, nativeStyles.size());
for (auto it = begin(nativeStyles); it != end(nativeStyles); ++it) {
auto converted = DefaultStyle::New(env, *it);
retVal.Set(env, it - nativeStyles.begin(), converted);
}
return retVal;
}
jni::Local<jni::Object<TileServerOptions>> TileServerOptions::DefaultConfiguration(jni::JNIEnv& env, const jni::Class<TileServerOptions>& jOptions) {
auto options = mbgl::TileServerOptions::DefaultConfiguration();
return TileServerOptions::New(env, options);
}
jni::Local<jni::Object<TileServerOptions>> TileServerOptions::MapboxConfiguration(jni::JNIEnv& env, const jni::Class<TileServerOptions>& jOptions) {
auto options = mbgl::TileServerOptions::MapboxConfiguration();
return TileServerOptions::New(env, options);
}
jni::Local<jni::Object<TileServerOptions>> TileServerOptions::MapTilerConfiguration(jni::JNIEnv& env, const jni::Class<TileServerOptions>& jOptions) {
auto options = mbgl::TileServerOptions::MapTilerConfiguration();
return TileServerOptions::New(env, options);
}
jni::Local<jni::Object<TileServerOptions>> TileServerOptions::MapLibreConfiguration(jni::JNIEnv& env, const jni::Class<TileServerOptions>& jOptions) {
auto options = mbgl::TileServerOptions::MapLibreConfiguration();
return TileServerOptions::New(env, options);
}
mbgl::TileServerOptions TileServerOptions::getTileServerOptions(jni::JNIEnv& env, const jni::Object<TileServerOptions>& options) {
auto opts = mbgl::TileServerOptions();
static auto& javaClass = jni::Class<TileServerOptions>::Singleton(env);
static auto baseURLField = javaClass.GetField<jni::String>(env, "baseURL");
static auto uriSchemeAliasField = javaClass.GetField<jni::String>(env, "uriSchemeAlias");
static auto sourceTemplateField = javaClass.GetField<jni::String>(env, "sourceTemplate");
static auto sourceDomainNameField = javaClass.GetField<jni::String>(env, "sourceDomainName");
static auto sourceVersionPrefixField = javaClass.GetField<jni::String>(env, "sourceVersionPrefix");
static auto styleTemplateField = javaClass.GetField<jni::String>(env, "styleTemplate");
static auto styleDomainNameField = javaClass.GetField<jni::String>(env, "styleDomainName");
static auto styleVersionPrefixField = javaClass.GetField<jni::String>(env, "styleVersionPrefix");
static auto spritesTemplateField = javaClass.GetField<jni::String>(env, "spritesTemplate");
static auto spritesDomainNameField = javaClass.GetField<jni::String>(env, "spritesDomainName");
static auto spritesVersionPrefixField = javaClass.GetField<jni::String>(env, "spritesVersionPrefix");
static auto glyphsTemplateField = javaClass.GetField<jni::String>(env, "glyphsTemplate");
static auto glyphsDomainNameField = javaClass.GetField<jni::String>(env, "glyphsDomainName");
static auto glyphsVersionPrefixField = javaClass.GetField<jni::String>(env, "glyphsVersionPrefix");
static auto tileTemplateField = javaClass.GetField<jni::String>(env, "tileTemplate");
static auto tileDomainNameField = javaClass.GetField<jni::String>(env, "tileDomainName");
static auto tileVersionPrefixField = javaClass.GetField<jni::String>(env, "tileVersionPrefix");
static auto apiKeyParameterNameField = javaClass.GetField<jni::String>(env, "apiKeyParameterName");
static auto apiKeyRequiredField = javaClass.GetField<jni::jboolean>(env, "apiKeyRequired");
static auto defaultStyleField = javaClass.GetField<jni::String>(env, "defaultStyle");
static auto defaultStylesField = javaClass.GetField<jni::Array<jni::Object<DefaultStyle>>>(env, "defaultStyles");
std::vector<const mbgl::util::DefaultStyle> defaultStyles = TileServerOptions::getDefaultStyles(env, options.Get(env, defaultStylesField));
auto retVal = mbgl::TileServerOptions()
.withBaseURL(jni::Make<std::string>(env, options.Get(env, baseURLField)))
.withUriSchemeAlias(jni::Make<std::string>(env, options.Get(env, uriSchemeAliasField)))
.withApiKeyParameterName(jni::Make<std::string>(env, options.Get(env, apiKeyParameterNameField)))
.setRequiresApiKey(options.Get(env, apiKeyRequiredField));
auto sourcePrefixValue = options.Get(env, sourceVersionPrefixField);
retVal.withSourceTemplate(
jni::Make<std::string>(env, options.Get(env, sourceTemplateField)),
jni::Make<std::string>(env, options.Get(env, sourceDomainNameField)),
sourcePrefixValue ? jni::Make<std::string>(env, sourcePrefixValue): optional<std::string>{});
auto styleVersionPrefixValue = options.Get(env, styleVersionPrefixField);
retVal.withStyleTemplate(
jni::Make<std::string>(env, options.Get(env, styleTemplateField)),
jni::Make<std::string>(env, options.Get(env, styleDomainNameField)),
styleVersionPrefixValue ? jni::Make<std::string>(env, styleVersionPrefixValue): optional<std::string>{});
auto spritesVersionPrefixValue = options.Get(env, spritesVersionPrefixField);
retVal.withSpritesTemplate(
jni::Make<std::string>(env, options.Get(env, spritesTemplateField)),
jni::Make<std::string>(env, options.Get(env, spritesDomainNameField)),
spritesVersionPrefixValue ? jni::Make<std::string>(env, spritesVersionPrefixValue): optional<std::string>{});
auto glyphsVersionPrefixValue = options.Get(env, glyphsVersionPrefixField);
retVal.withGlyphsTemplate(
jni::Make<std::string>(env, options.Get(env, glyphsTemplateField)),
jni::Make<std::string>(env, options.Get(env, glyphsDomainNameField)),
glyphsVersionPrefixValue ? jni::Make<std::string>(env, glyphsVersionPrefixValue) : optional<std::string>{});
auto tileVersionPrefixValue = options.Get(env, tileVersionPrefixField);
retVal.withTileTemplate(
jni::Make<std::string>(env, options.Get(env, tileTemplateField)),
jni::Make<std::string>(env, options.Get(env, tileDomainNameField)),
tileVersionPrefixValue ? jni::Make<std::string>(env, tileVersionPrefixValue): optional<std::string>{});
retVal.withDefaultStyle(jni::Make<std::string>(env, options.Get(env, defaultStyleField)));
retVal.withDefaultStyles(defaultStyles);
return retVal;
}
std::vector<const mbgl::util::DefaultStyle> TileServerOptions::getDefaultStyles(jni::JNIEnv& env, const jni::Array<jni::Object<DefaultStyle>>& styles_) {
std::size_t length = styles_.Length(env);
std::vector<const mbgl::util::DefaultStyle> convertedStyles;
//convertedStyles.reserve(length);
for (std::size_t i = 0; i < length; i++) {
const mbgl::util::DefaultStyle converted = DefaultStyle::getDefaultStyle(env, styles_.Get(env, i));
convertedStyles.push_back(converted);
}
return convertedStyles;
}
void TileServerOptions::registerNative(jni::JNIEnv& env) {
static auto& javaClass = jni::Class<TileServerOptions>::Singleton(env);
jni::RegisterNatives(env,
*javaClass,
jni::MakeNativeMethod<decltype(&TileServerOptions::DefaultConfiguration), &TileServerOptions::DefaultConfiguration>("defaultConfiguration"),
jni::MakeNativeMethod<decltype(&TileServerOptions::MapboxConfiguration), &TileServerOptions::MapboxConfiguration>("mapboxConfiguration"),
jni::MakeNativeMethod<decltype(&TileServerOptions::MapTilerConfiguration), &TileServerOptions::MapTilerConfiguration>("mapTilerConfiguration"),
jni::MakeNativeMethod<decltype(&TileServerOptions::MapLibreConfiguration), &TileServerOptions::MapLibreConfiguration>("mapLibreConfiguration"));
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,38 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/tile_server_options.hpp>
#include <mbgl/util/default_style.hpp>
#include <jni/jni.hpp>
#include "default_style.hpp"
namespace mbgl {
namespace android {
class TileServerOptions : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/util/TileServerOptions"; };
static jni::Local<jni::Object<TileServerOptions>> New(jni::JNIEnv&, const mbgl::TileServerOptions&);
static jni::Local<jni::Object<TileServerOptions>> DefaultConfiguration(jni::JNIEnv&, const jni::Class<TileServerOptions>&);
static jni::Local<jni::Object<TileServerOptions>> MapboxConfiguration(jni::JNIEnv&, const jni::Class<TileServerOptions>&);
static jni::Local<jni::Object<TileServerOptions>> MapTilerConfiguration(jni::JNIEnv&, const jni::Class<TileServerOptions>&);
static jni::Local<jni::Object<TileServerOptions>> MapLibreConfiguration(jni::JNIEnv&, const jni::Class<TileServerOptions>&);
static mbgl::TileServerOptions getTileServerOptions(jni::JNIEnv&, const jni::Object<TileServerOptions>&);
static void registerNative(jni::JNIEnv&);
static jni::Local<jni::Array<jni::Object<DefaultStyle>>> NewStyles(jni::JNIEnv& env, const std::vector<const mbgl::util::DefaultStyle>);
static std::vector<const mbgl::util::DefaultStyle> getDefaultStyles(jni::JNIEnv& env, const jni::Array<jni::Object<DefaultStyle>>& styles_);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,107 +0,0 @@
package com.mapbox.mapboxsdk;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.mapbox.android.accounts.v1.MapboxAccounts;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.log.Logger;
/**
* REMOVAL OR MODIFICATION OF THE FOLLOWING CODE VIOLATES THE MAPBOX TERMS
* OF SERVICE
* <p>
* The following code is used to access Mapbox's Mapping APIs.
* <p>
* Removal or modification of this code when used with Mapbox's Mapping APIs
* can result in termination of your agreement and/or your account with
* Mapbox.
* <p>
* Using this code to access Mapbox Mapping APIs from outside the Mapbox Maps
* SDK also violates the Mapbox Terms of Service. On Android, Mapping APIs
* should be accessed using the methods documented at
* https://www.mapbox.com/android.
* <p>
* You can access the Mapbox Terms of Service at https://www.mapbox.com/tos/
*/
class AccountsManager {
private static final String TAG = "Mbgl-AccountsManager";
private static final String PREFERENCE_USER_ID = "com.mapbox.mapboxsdk.accounts.userid";
private static final String PREFERENCE_TIMESTAMP = "com.mapbox.mapboxsdk.accounts.timestamp";
private SharedPreferences sharedPreferences;
private String userId;
private long timestamp;
AccountsManager() {
initialize();
}
@VisibleForTesting
AccountsManager(SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
initialize();
}
private void initialize() {
}
private ApplicationInfo retrieveApplicationInfo() throws PackageManager.NameNotFoundException {
return Mapbox.getApplicationContext().getPackageManager().getApplicationInfo(
Mapbox.getApplicationContext().getPackageName(),
PackageManager.GET_META_DATA);
}
private boolean isExpired() {
return isExpired(getNow(), timestamp);
}
static boolean isExpired(long now, long then) {
return ((now - then) > DateUtils.HOUR_IN_MILLIS);
}
@NonNull
private SharedPreferences getSharedPreferences() {
if (sharedPreferences == null) {
sharedPreferences = Mapbox.getApplicationContext()
.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES, Context.MODE_PRIVATE);
}
return sharedPreferences;
}
static long getNow() {
return System.currentTimeMillis();
}
private synchronized String getUserId() {
if (!TextUtils.isEmpty(userId)) {
return userId;
}
SharedPreferences sharedPreferences = getSharedPreferences();
userId = sharedPreferences.getString(PREFERENCE_USER_ID, "");
if (TextUtils.isEmpty(userId)) {
userId = generateUserId();
SharedPreferences.Editor editor = getSharedPreferences().edit();
editor.putString(PREFERENCE_USER_ID, userId);
if (!editor.commit()) {
Logger.e(TAG, "Failed to save user id.");
}
}
return userId;
}
@NonNull
private String generateUserId() {
return MapboxAccounts.obtainEndUserId();
}
}

View File

@@ -13,14 +13,16 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.mapboxsdk.util.DefaultStyle;
import com.mapbox.mapboxsdk.util.TileServerOptions;
import com.mapbox.mapboxsdk.utils.ThreadUtils;
/**
* The entry point to initialize the Mapbox Android SDK.
* The entry point to initialize the MapLibre Android SDK.
* <p>
* Obtain a reference by calling {@link #getInstance(Context, String)}. Usually this class is configured in
* Application#onCreate() and is responsible for the active access token, application context, and
* connectivity state.
* Obtain a reference by calling {@link #getInstance(Context, String, WellKnownTileServer)}.
* Usually this class is configured in Application#onCreate() and is responsible for the
* active API key, application context, and connectivity state.
* </p>
*/
@UiThread
@@ -34,62 +36,149 @@ public final class Mapbox {
private Context context;
@Nullable
private String accessToken;
private String apiKey;
@Nullable
private AccountsManager accounts;
private TileServerOptions tileServerOptions;
/**
* Get an instance of Mapbox.
* <p>
* This class manages the Mapbox access token, application context, and connectivity state.
* This class manages the API key, application context, and connectivity state.
* </p>
*
* @param context Android context which holds or is an application context
* @param accessToken Mapbox access token
* @param context Android context which holds or is an application context
* @return the single instance of Mapbox
*/
@UiThread
@NonNull
public static synchronized Mapbox getInstance(@NonNull Context context, @Nullable String accessToken) {
public static synchronized Mapbox getInstance(@NonNull Context context) {
ThreadUtils.init(context);
ThreadUtils.checkThread(TAG);
if (INSTANCE == null) {
Context appContext = context.getApplicationContext();
FileSource.initializeFileDirsPaths(appContext);
INSTANCE = new Mapbox(appContext, accessToken);
if (isAccessTokenValid(accessToken)) {
INSTANCE.accounts = new AccountsManager();
}
INSTANCE = new Mapbox(appContext, null);
ConnectivityReceiver.instance(appContext);
} else {
TileServerOptions tileServerOptions = TileServerOptions.get(WellKnownTileServer.MapLibre);
INSTANCE.tileServerOptions = tileServerOptions;
INSTANCE.apiKey = null;
FileSource fileSource = FileSource.getInstance(context);
fileSource.setTileServerOptions(tileServerOptions);
fileSource.setApiKey(null);
}
return INSTANCE;
}
Mapbox(@NonNull Context context, @Nullable String accessToken) {
/**
* Get an instance of Mapbox.
* <p>
* This class manages the API key, application context, and connectivity state.
* </p>
*
* @param context Android context which holds or is an application context
* @param apiKey api key
* @param tileServer the tile server whose predefined configuration will be used to
* bootstrap the SDK. The predefined configuration includes
* rules for converting resource URLs between normal and canonical forms
* and set of predefined styles available on the server.
* @return the single instance of Mapbox
*/
@UiThread
@NonNull
public static synchronized Mapbox getInstance(@NonNull Context context, @Nullable String apiKey,
WellKnownTileServer tileServer) {
ThreadUtils.init(context);
ThreadUtils.checkThread(TAG);
if (INSTANCE == null) {
Context appContext = context.getApplicationContext();
FileSource.initializeFileDirsPaths(appContext);
INSTANCE = new Mapbox(appContext, apiKey);
ConnectivityReceiver.instance(appContext);
} else {
INSTANCE.apiKey = apiKey;
}
TileServerOptions tileServerOptions = TileServerOptions.get(tileServer);
INSTANCE.tileServerOptions = tileServerOptions;
FileSource fileSource = FileSource.getInstance(context);
fileSource.setTileServerOptions(tileServerOptions);
fileSource.setApiKey(apiKey);
return INSTANCE;
}
Mapbox(@NonNull Context context, @Nullable String apiKey) {
this.context = context;
this.accessToken = accessToken;
this.apiKey = apiKey;
}
Mapbox(@NonNull Context context, @Nullable String apiKey, @NonNull TileServerOptions options) {
this.context = context;
this.apiKey = apiKey;
this.tileServerOptions = options;
}
/**
* Get the current active access token for this application.
* Get the current active API key for this application.
*
* @return Mapbox access token
* @return API key
*/
@Nullable
public static String getAccessToken() {
public static String getApiKey() {
validateMapbox();
return INSTANCE.accessToken;
return INSTANCE.apiKey;
}
/**
* Set the current active accessToken.
* Set the current active apiKey.
*/
public static void setAccessToken(String accessToken) {
public static void setApiKey(String apiKey) {
validateMapbox();
throwIfAccessTokenInvalid(accessToken);
INSTANCE.accessToken = accessToken;
INSTANCE.accounts = new AccountsManager();
FileSource.getInstance(getApplicationContext()).setAccessToken(accessToken);
throwIfApiKeyInvalid(apiKey);
INSTANCE.apiKey = apiKey;
FileSource.getInstance(getApplicationContext()).setApiKey(apiKey);
}
/**
* Get tile server configuration.
*/
@Nullable
public static TileServerOptions getTileServerOptions() {
validateMapbox();
return INSTANCE.tileServerOptions;
}
/**
* Get all pre-defined styles
*
* @return List of predefined styles
*/
@Nullable
public static DefaultStyle[] getPredefinedStyles() {
validateMapbox();
if (INSTANCE.tileServerOptions != null) {
return INSTANCE.tileServerOptions.getDefaultStyles();
}
return null;
}
/**
* Get predefined style by name
*
* @return Predefined style if found
*/
@Nullable
public static DefaultStyle getPredefinedStyle(String name) {
validateMapbox();
if (INSTANCE.tileServerOptions != null) {
DefaultStyle[] styles = INSTANCE.tileServerOptions.getDefaultStyles();
for (DefaultStyle style : styles) {
if (style.getName().equalsIgnoreCase(name)) {
return style;
}
}
}
return null;
}
/**
@@ -151,28 +240,25 @@ public final class Mapbox {
/**
* Runtime validation of Mapbox access token
*
* @param accessToken the access token to validate
* @param apiKey the access token to validate
* @return true is valid, false otherwise
*/
static boolean isAccessTokenValid(@Nullable String accessToken) {
if (accessToken == null) {
static boolean isApiKeyValid(@Nullable String apiKey) {
if (apiKey == null) {
return false;
}
accessToken = accessToken.trim().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
return accessToken.length() != 0 && (accessToken.startsWith("pk.") || accessToken.startsWith("sk."));
apiKey = apiKey.trim().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
return apiKey.length() != 0;
}
/**
* Throws exception when access token is invalid
*/
public static void throwIfAccessTokenInvalid(@Nullable String accessToken) {
if (!isAccessTokenValid(accessToken)) {
public static void throwIfApiKeyInvalid(@Nullable String apiKey) {
if (!isApiKeyValid(apiKey)) {
throw new MapboxConfigurationException(
"A valid access token parameter is required when using a Mapbox service."
+ "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."
+ "Currently provided token is: " + accessToken);
"A valid API key is required, currently provided key is: " + apiKey);
}
}

View File

@@ -0,0 +1,7 @@
package com.mapbox.mapboxsdk;
public enum WellKnownTileServer {
Mapbox,
MapTiler,
MapLibre;
}

View File

@@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
/**
* A MapboxConfigurationException is thrown by MapboxMap when the SDK hasn't been properly initialised.
* <p>
* This occurs either when {@link com.mapbox.mapboxsdk.Mapbox} is not correctly initialised or the provided access token
* This occurs either when {@link com.mapbox.mapboxsdk.Mapbox} is not correctly initialised or the provided apiKey
* through {@link com.mapbox.mapboxsdk.Mapbox#getInstance(Context, String)} isn't valid.
* </p>
*
@@ -19,10 +19,8 @@ public class MapboxConfigurationException extends RuntimeException {
* Creates a Mapbox configuration exception thrown by MapboxMap when the SDK hasn't been properly initialised.
*/
public MapboxConfigurationException() {
super("\nUsing MapView requires calling Mapbox.getInstance(Context context, String accessToken) before "
+ "inflating or creating the view. The access token parameter is required when using a Mapbox service."
+ "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens.");
super("\nUsing MapView requires calling Mapbox.getInstance(Context context, String apiKey) before "
+ "inflating or creating the view.");
}
/**

View File

@@ -108,13 +108,13 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt
Attribution[] attributions = attributionSet.toArray(new Attribution[attributionSet.size()]);
String url = attributions[which].getUrl();
if (url.contains(MAP_FEEDBACK_URL_OLD) || url.contains(MAP_FEEDBACK_URL)) {
url = buildMapFeedbackMapUrl(Mapbox.getAccessToken());
url = buildMapFeedbackMapUrl(Mapbox.getApiKey());
}
showWebPage(url);
}
@NonNull
String buildMapFeedbackMapUrl(@Nullable String accessToken) {
String buildMapFeedbackMapUrl(@Nullable String apiKey) {
// TODO Add Android Maps SDK version to the query parameter, currently the version API is not available.
// TODO Keep track of this issue at [#15632](https://github.com/mapbox/mapbox-gl-native/issues/15632)
@@ -132,8 +132,9 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt
builder.appendQueryParameter("referrer", packageName);
}
if (accessToken != null) {
builder.appendQueryParameter("access_token", accessToken);
if (apiKey != null) {
//TODO:PP
builder.appendQueryParameter("access_token", apiKey);
}
Style style = mapboxMap.getStyle();

View File

@@ -883,7 +883,7 @@ public final class MapboxMap {
* @param style The bundled style
* @see Style
*/
public void setStyle(@Style.StyleUrl String style) {
public void setStyle(String style) {
this.setStyle(style, null);
}
@@ -899,7 +899,7 @@ public final class MapboxMap {
* @param callback The callback to be invoked when the style has loaded
* @see Style
*/
public void setStyle(@Style.StyleUrl String style, final Style.OnStyleLoaded callback) {
public void setStyle(String style, final Style.OnStyleLoaded callback) {
this.setStyle(new Style.Builder().fromUri(style), callback);
}

View File

@@ -9,17 +9,16 @@ import android.util.Pair;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringDef;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.style.light.Light;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.util.DefaultStyle;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -802,11 +801,6 @@ public class Style {
* </p>
* {@code url} can take the following forms:
* <ul>
* <li>{@code Style#StyleUrl}: load one of the bundled styles in {@link Style}.</li>
* <li>{@code mapbox://styles/<user>/<style>}:
* loads the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a>
* {@code user} is your username. {@code style} is the ID of your custom
* style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li>
* <li>{@code http://...} or {@code https://...}:
* loads the style over the Internet from any web server.</li>
* <li>{@code asset://...}:
@@ -816,7 +810,6 @@ public class Style {
* loads the style from a file path. This is used to load a style from disk.
* </li>
* </li>
* <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
* </ul>
* <p>
* This method is asynchronous and will return before the style finishes loading.
@@ -845,11 +838,6 @@ public class Style {
* </p>
* {@code uri} can take the following forms:
* <ul>
* <li>{@code Style#StyleUrl}: load one of the bundled styles in {@link Style}.</li>
* <li>{@code mapbox://styles/<user>/<style>}:
* loads the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a>
* {@code user} is your username. {@code style} is the ID of your custom
* style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li>
* <li>{@code http://...} or {@code https://...}:
* loads the style over the Internet from any web server.</li>
* <li>{@code asset://...}:
@@ -859,7 +847,6 @@ public class Style {
* loads the style from a file path. This is used to load a style from disk.
* </li>
* </li>
* <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
* </ul>
* <p>
* This method is asynchronous and will return before the style finishes loading.
@@ -1421,70 +1408,25 @@ public class Style {
//
/**
* Indicates the parameter accepts one of the values from Style. Using one of these
* constants means your map style will always use the latest version and may change as we
* improve the style
* Get predefined styles
*
* @return The list of predefined styles
*/
@StringDef( {MAPBOX_STREETS, OUTDOORS, LIGHT, DARK, SATELLITE, SATELLITE_STREETS, TRAFFIC_DAY, TRAFFIC_NIGHT})
@Retention(RetentionPolicy.SOURCE)
public @interface StyleUrl {
public static DefaultStyle[] getPredefinedStyles() {
return Mapbox.getPredefinedStyles();
}
// IMPORTANT: If you change any of these you also need to edit them in strings.xml
/**
* Mapbox Streets: A complete basemap, perfect for incorporating your own data. Using this
* constant means your map style will always use the latest version and may change as we
* improve the style.
* Get predefined style by name
*
* @return The predefined style definition
*/
public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v11";
/**
* Outdoors: A general-purpose style tailored to outdoor activities. Using this constant means
* your map style will always use the latest version and may change as we improve the style.
*/
public static final String OUTDOORS = "mapbox://styles/mapbox/outdoors-v11";
/**
* Light: Subtle light backdrop for data visualizations. Using this constant means your map
* style will always use the latest version and may change as we improve the style.
*/
public static final String LIGHT = "mapbox://styles/mapbox/light-v10";
/**
* Dark: Subtle dark backdrop for data visualizations. Using this constant means your map style
* will always use the latest version and may change as we improve the style.
*/
public static final String DARK = "mapbox://styles/mapbox/dark-v10";
/**
* Satellite: A beautiful global satellite and aerial imagery layer. Using this constant means
* your map style will always use the latest version and may change as we improve the style.
*/
public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v9";
/**
* Satellite Streets: Global satellite and aerial imagery with unobtrusive labels. Using this
* constant means your map style will always use the latest version and may change as we
* improve the style.
*/
public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-streets-v11";
/**
* Traffic Day: Color-coded roads based on live traffic congestion data. Traffic data is currently
* available in
* <a href="https://www.mapbox.com/help/how-directions-work/#traffic-data">these select
* countries</a>. Using this constant means your map style will always use the latest version and
* may change as we improve the style.
*/
public static final String TRAFFIC_DAY = "mapbox://styles/mapbox/traffic-day-v2";
/**
* Traffic Night: Color-coded roads based on live traffic congestion data, designed to maximize
* legibility in low-light situations. Traffic data is currently available in
* <a href="https://www.mapbox.com/help/how-directions-work/#traffic-data">these select
* countries</a>. Using this constant means your map style will always use the latest version and
* may change as we improve the style.
*/
public static final String TRAFFIC_NIGHT = "mapbox://styles/mapbox/traffic-night-v2";
@NonNull
public static String getPredefinedStyle(String name) {
DefaultStyle style = Mapbox.getPredefinedStyle(name);
if (style != null) {
return style.getUrl();
}
throw new IllegalArgumentException("Could not find layer " + name);
}
}

View File

@@ -325,14 +325,14 @@ public class MapSnapshotter {
*/
@Deprecated
public String getStyleUrl() {
return builder == null ? Style.MAPBOX_STREETS : builder.getUri();
return builder == null ? null : builder.getUri();
}
/**
* @return the style uri
*/
public String getStyleUri() {
return builder == null ? Style.MAPBOX_STREETS : builder.getUri();
return builder == null ? null : builder.getUri();
}
/**

View File

@@ -16,6 +16,7 @@ import com.mapbox.mapboxsdk.MapStrictMode;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.util.TileServerOptions;
import com.mapbox.mapboxsdk.utils.FileUtils;
import com.mapbox.mapboxsdk.utils.ThreadUtils;
@@ -371,9 +372,13 @@ public class FileSource {
private long nativePtr;
private FileSource(String cachePath) {
initialize(Mapbox.getAccessToken(), cachePath);
TileServerOptions options = Mapbox.getTileServerOptions();
initialize(Mapbox.getApiKey(), cachePath, options);
}
@Keep
public native void setTileServerOptions(TileServerOptions tileServerOptions);
@Keep
public native boolean isActivated();
@@ -384,15 +389,19 @@ public class FileSource {
public native void deactivate();
@Keep
public native void setAccessToken(String accessToken);
public native void setApiKey(String apiKey);
@NonNull
@Keep
public native String getAccessToken();
public native String getApiKey();
@Keep
public native void setApiBaseUrl(String baseUrl);
@NonNull
@Keep
public native String getApiBaseUrl();
/**
* Sets a callback for transforming URLs requested from the internet
* <p>
@@ -408,7 +417,7 @@ public class FileSource {
private native void setResourceCachePath(String path, ResourcesCachePathChangeCallback callback);
@Keep
private native void initialize(String accessToken, String cachePath);
private native void initialize(String apiKey, String cachePath, TileServerOptions options);
@Override
@Keep

View File

@@ -9,7 +9,7 @@ import java.net.URI;
import java.net.URL;
/**
* A raster DEM source. Currently only supports Mapbox Terrain RGB (mapbox://mapbox.terrain-rgb)
* A raster DEM source.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-raster-dem">The style specification</a>
*/

View File

@@ -0,0 +1,110 @@
package com.mapbox.mapboxsdk.util;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
/**
* Default style definition
*/
public class DefaultStyle implements Parcelable {
/**
* Inner class responsible for recreating Parcels into objects.
*/
public static final Creator<DefaultStyle> CREATOR = new Creator<DefaultStyle>() {
public DefaultStyle createFromParcel(@NonNull Parcel in) {
return new DefaultStyle(in);
}
public DefaultStyle[] newArray(int size) {
return new DefaultStyle[size];
}
};
@Keep
private String url;
@Keep
private String name;
@Keep
private int version;
/**
* Construct a new Default style definition
*
* @param url canonical style url
* @param name style name
* @param version style version
*/
@Keep
public DefaultStyle(
String url,
String name,
int version
) {
setUrl(url);
setName(name);
setVersion(version);
}
public void setUrl(String url) {
this.url = url;
}
public String getUrl() {
return this.url;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setVersion(int version) {
this.version = version;
}
public int getVersion() {
return this.version;
}
/**
* Describe the kinds of special objects contained in this Parcelable instance's marshaled representation.
*
* @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance.
*/
@Override
public int describeContents() {
return 0;
}
/**
* Constructs a new default style tuple given a parcel.
*
* @param in the parcel containing the tile server options values
*/
protected DefaultStyle(Parcel in) {
setUrl(in.readString());
setName(in.readString());
setVersion(in.readInt());
}
/**
* Flatten this object in to a Parcel.
*
* @param out The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written
*/
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeString(url);
out.writeString(name);
out.writeInt(version);
}
}

View File

@@ -0,0 +1,417 @@
package com.mapbox.mapboxsdk.util;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.WellKnownTileServer;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
/**
* Tile server options - baseUrl and similar properties
*/
public class TileServerOptions implements Parcelable {
/**
* Inner class responsible for recreating Parcels into objects.
*/
public static final Creator<TileServerOptions> CREATOR = new Creator<TileServerOptions>() {
public TileServerOptions createFromParcel(@NonNull Parcel in) {
return new TileServerOptions(in);
}
public TileServerOptions[] newArray(int size) {
return new TileServerOptions[size];
}
};
@Keep
private String baseURL;
@Keep
private String uriSchemeAlias;
@Keep
private String sourceTemplate;
@Keep
private String sourceDomainName;
@Keep
@Nullable
private String sourceVersionPrefix;
@Keep
private String styleTemplate;
@Keep
private String styleDomainName;
@Keep
@Nullable
private String styleVersionPrefix;
@Keep
private String spritesTemplate;
@Keep
private String spritesDomainName;
@Keep
@Nullable
private String spritesVersionPrefix;
@Keep
private String glyphsTemplate;
@Keep
private String glyphsDomainName;
@Keep
@Nullable
private String glyphsVersionPrefix;
@Keep
private String tileTemplate;
@Keep
private String tileDomainName;
@Keep
@Nullable
private String tileVersionPrefix;
@Keep
private String apiKeyParameterName;
@Keep
private boolean apiKeyRequired;
@Keep
private String defaultStyle;
@Keep
private DefaultStyle[] defaultStyles;
/**
* Construct a new TileServerOptions given string arguments
*
* @param baseURL tile server base url
* @param uriSchemeAlias scheme alias such as maplibre://
* @param sourceTemplate tile source url template
* @param sourceDomainName tile source domain name
* @param sourceVersionPrefix tile source version prefix
* @param styleTemplate style url template
* @param styleDomainName the name of style domain in canonical url
* @param styleVersionPrefix version prefix
* @param spritesTemplate sprites url template
* @param spritesDomainName the name of the sprites domain in canonical url
* @param spritesVersionPrefix the sprite version prefix
* @param glyphsTemplate glyphs url template
* @param glyphsDomainName the name of the glyphs domain in canonical url
* @param glyphsVersionPrefix the glyphs version prefix
* @param tileTemplate tile url template
* @param tileDomainName the name of the tile domain in canonical url
* @param tileVersionPrefix the tile version prefix
* @param apiKeyParameterName the name of api key parameter
* @param apiKeyRequired indicates if API key is required
* @param defaultStyle the name of the default style
* @param defaultStyles the list of default styles
*/
@Keep
public TileServerOptions(
String baseURL,
String uriSchemeAlias,
String sourceTemplate,
String sourceDomainName,
@Nullable String sourceVersionPrefix,
String styleTemplate,
String styleDomainName,
@Nullable String styleVersionPrefix,
String spritesTemplate,
String spritesDomainName,
@Nullable String spritesVersionPrefix,
String glyphsTemplate,
String glyphsDomainName,
@Nullable String glyphsVersionPrefix,
String tileTemplate,
String tileDomainName,
@Nullable String tileVersionPrefix,
String apiKeyParameterName,
boolean apiKeyRequired,
String defaultStyle,
DefaultStyle[] defaultStyles
) {
setBaseURL(baseURL);
setUriSchemeAlias(uriSchemeAlias);
setSourceTemplate(sourceTemplate);
setSourceDomainName(sourceDomainName);
setSourceVersionPrefix(sourceVersionPrefix);
setStyleTemplate(styleTemplate);
setStyleDomainName(styleDomainName);
setStyleVersionPrefix(styleVersionPrefix);
setSpritesTemplate(spritesTemplate);
setSpritesDomainName(spritesDomainName);
setSpritesVersionPrefix(spritesVersionPrefix);
setGlyphsTemplate(glyphsTemplate);
setGlyphsDomainName(glyphsDomainName);
setGlyphsVersionPrefix(glyphsVersionPrefix);
setTileTemplate(tileTemplate);
setTileDomainName(tileDomainName);
setTileVersionPrefix(tileVersionPrefix);
setApiKeyParameterName(apiKeyParameterName);
setDefaultStyles(defaultStyles);
setDefaultStyle(defaultStyle);
setApiKeyRequired(apiKeyRequired);
}
public void setBaseURL(String baseURL) {
this.baseURL = baseURL;
}
public String getBaseURL() {
return this.baseURL;
}
public void setUriSchemeAlias(String uriSchemeAlias) {
this.uriSchemeAlias = uriSchemeAlias;
}
public String getUriSchemeAlias() {
return this.uriSchemeAlias;
}
public void setSourceTemplate(String sourceTemplate) {
this.sourceTemplate = sourceTemplate;
}
public String getSourceTemplate() {
return this.sourceTemplate;
}
public void setSourceDomainName(String domainName) {
this.sourceDomainName = domainName;
}
public String getSourceDomainName() {
return this.sourceDomainName;
}
public void setSourceVersionPrefix(String sourceVersionPrefix) {
this.sourceVersionPrefix = sourceVersionPrefix;
}
public String getSourceVersionPrefix() {
return this.sourceVersionPrefix;
}
public void setStyleTemplate(String styleTemplate) {
this.styleTemplate = styleTemplate;
}
public String getStyleTemplate() {
return this.styleTemplate;
}
public void setStyleDomainName(String styleDomainName) {
this.styleDomainName = styleDomainName;
}
public String getStyleDomainName() {
return this.styleDomainName;
}
public void setStyleVersionPrefix(String styleVersionPrefix) {
this.styleVersionPrefix = styleVersionPrefix;
}
public String getStyleVersionPrefix() {
return this.styleVersionPrefix;
}
public void setSpritesTemplate(String spritesTemplate) {
this.spritesTemplate = spritesTemplate;
}
public String getSpritesTemplate() {
return this.spritesTemplate;
}
public void setSpritesDomainName(String spritesDomainName) {
this.spritesDomainName = spritesDomainName;
}
public String getSpritesDomainName() {
return this.spritesDomainName;
}
public void setSpritesVersionPrefix(String spritesVersionPrefix) {
this.spritesVersionPrefix = spritesVersionPrefix;
}
public String getSpritesVersionPrefix() {
return this.spritesVersionPrefix;
}
public void setGlyphsTemplate(String glyphsTemplate) {
this.glyphsTemplate = glyphsTemplate;
}
public String getGlyphsTemplate() {
return this.glyphsTemplate;
}
public void setGlyphsDomainName(String glyphsDomainName) {
this.glyphsDomainName = glyphsDomainName;
}
public String getGlyphsDomainName() {
return this.glyphsDomainName;
}
public void setGlyphsVersionPrefix(String glyphsVersionPrefix) {
this.glyphsVersionPrefix = glyphsVersionPrefix;
}
public String getGlyphsVersionPrefix() {
return this.glyphsVersionPrefix;
}
public void setTileTemplate(String tileTemplate) {
this.tileTemplate = tileTemplate;
}
public String getTileTemplate() {
return this.tileTemplate;
}
public void setTileDomainName(String tileDomainName) {
this.tileDomainName = tileDomainName;
}
public String getTileDomainName() {
return this.tileDomainName;
}
public void setTileVersionPrefix(String tileVersionPrefix) {
this.tileVersionPrefix = tileVersionPrefix;
}
public String getTileVersionPrefix() {
return this.tileVersionPrefix;
}
public void setApiKeyParameterName(String apiKeyParameterName) {
this.apiKeyParameterName = apiKeyParameterName;
}
public String getApiKeyParameterName() {
return this.apiKeyParameterName;
}
public void setApiKeyRequired(boolean isRequired) {
this.apiKeyRequired = isRequired;
}
public boolean getApiKeyRequired() {
return this.apiKeyRequired;
}
public void setDefaultStyles(DefaultStyle[] defaultStyles) {
this.defaultStyles = defaultStyles;
}
public DefaultStyle[] getDefaultStyles() {
return this.defaultStyles;
}
public void setDefaultStyle(String defaultStyleName) {
this.defaultStyle = defaultStyleName;
}
public String getDefaultStyle() {
return this.defaultStyle;
}
/**
* Describe the kinds of special objects contained in this Parcelable instance's marshaled representation.
*
* @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance.
*/
@Override
public int describeContents() {
return 0;
}
/**
* Constructs a new tile server options tuple given a parcel.
*
* @param in the parcel containing the tile server options values
*/
protected TileServerOptions(Parcel in) {
setBaseURL(in.readString());
setUriSchemeAlias(in.readString());
setSourceTemplate(in.readString());
setSourceDomainName(in.readString());
setSourceVersionPrefix(in.readString());
setStyleTemplate(in.readString());
setStyleDomainName(in.readString());
setStyleVersionPrefix(in.readString());
setSpritesTemplate(in.readString());
setSpritesDomainName(in.readString());
setSpritesVersionPrefix(in.readString());
setGlyphsTemplate(in.readString());
setGlyphsDomainName(in.readString());
setGlyphsVersionPrefix(in.readString());
setTileTemplate(in.readString());
setTileDomainName(in.readString());
setTileVersionPrefix(in.readString());
setApiKeyParameterName(in.readString());
setApiKeyRequired(in.readByte() != 0);
setDefaultStyle(in.readString());
in.createTypedArray(DefaultStyle.CREATOR);
}
/**
* Flatten this object in to a Parcel.
*
* @param out The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written
*/
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeString(baseURL);
out.writeString(uriSchemeAlias);
out.writeString(sourceTemplate);
out.writeString(sourceDomainName);
out.writeString(sourceVersionPrefix);
out.writeString(styleTemplate);
out.writeString(styleDomainName);
out.writeString(styleVersionPrefix);
out.writeString(spritesTemplate);
out.writeString(spritesDomainName);
out.writeString(spritesVersionPrefix);
out.writeString(glyphsTemplate);
out.writeString(glyphsDomainName);
out.writeString(glyphsVersionPrefix);
out.writeString(tileTemplate);
out.writeString(tileDomainName);
out.writeString(tileVersionPrefix);
out.writeString(apiKeyParameterName);
out.writeByte((byte) (apiKeyRequired ? 1 : 0));
out.writeString(defaultStyle);
out.writeTypedArray(defaultStyles, 0);
}
public static TileServerOptions get(WellKnownTileServer tileServer) {
switch (tileServer) {
case Mapbox:
return mapboxConfiguration();
case MapTiler:
return mapTilerConfiguration();
case MapLibre:
return mapLibreConfiguration();
default:
throw new MapboxConfigurationException("Unknown tile server");
}
}
@Keep
@NonNull
private static native TileServerOptions defaultConfiguration();
@Keep
@NonNull
private static native TileServerOptions mapboxConfiguration();
@Keep
@NonNull
private static native TileServerOptions mapTilerConfiguration();
@Keep
@NonNull
private static native TileServerOptions mapLibreConfiguration();
}

View File

@@ -7,16 +7,4 @@
<string name="mapbox_attributionsDialogTitle">Mapbox Maps SDK for Android</string>
<string name="mapbox_attributionErrorNoBrowser">No web browser installed on device, can\'t open web page.</string>
<string name="mapbox_offline_error_region_definition_invalid">Provided OfflineRegionDefinition doesn\'t fit the world bounds: %s</string>
<!-- these are public -->
<!-- Using one of these constants means your map style will always use the latest version and
may change as we improve the style. -->
<string name="mapbox_style_mapbox_streets" translatable="false">mapbox://styles/mapbox/streets-v11</string>
<string name="mapbox_style_outdoors" translatable="false">mapbox://styles/mapbox/outdoors-v11</string>
<string name="mapbox_style_light" translatable="false">mapbox://styles/mapbox/light-v10</string>
<string name="mapbox_style_dark" translatable="false">mapbox://styles/mapbox/dark-v10</string>
<string name="mapbox_style_satellite" translatable="false">mapbox://styles/mapbox/satellite-v9</string>
<string name="mapbox_style_satellite_streets" translatable="false">mapbox://styles/mapbox/satellite-streets-v11</string>
<string name="mapbox_style_traffic_day" translatable="false">mapbox://styles/mapbox/traffic-day-v2</string>
<string name="mapbox_style_traffic_night" translatable="false">mapbox://styles/mapbox/traffic-night-v2</string>
</resources>

View File

@@ -1,29 +0,0 @@
package com.mapbox.mapboxsdk;
import android.text.format.DateUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(RobolectricTestRunner.class)
public class AccountsManagerTest {
@Test
public void testIsExpired() {
long now = AccountsManager.getNow();
long defaultValue = 0L;
long tooOld = now - DateUtils.HOUR_IN_MILLIS - 1;
long futureValue = now + 1;
long immediatePast = now - 1;
assertTrue(AccountsManager.isExpired(now, defaultValue));
assertTrue(AccountsManager.isExpired(now, tooOld));
assertFalse(AccountsManager.isExpired(now, futureValue));
assertFalse(AccountsManager.isExpired(now, immediatePast));
}
}

View File

@@ -4,27 +4,21 @@ import android.content.Context;
import androidx.annotation.NonNull;
import java.lang.reflect.Field;
import com.mapbox.mapboxsdk.util.TileServerOptions;
import static org.mockito.Mockito.mock;
import java.lang.reflect.Field;
public class MapboxInjector {
private static final String FIELD_INSTANCE = "INSTANCE";
private static final String FIELD_ACCOUNTS = "accounts";
public static void inject(@NonNull Context context, @NonNull String accessToken) {
Mapbox mapbox = new Mapbox(context, accessToken);
public static void inject(@NonNull Context context, @NonNull String apiKey,
@NonNull TileServerOptions options) {
Mapbox mapbox = new Mapbox(context, apiKey, options);
try {
Field instance = Mapbox.class.getDeclaredField(FIELD_INSTANCE);
instance.setAccessible(true);
instance.set(mapbox, mapbox);
Field accounts = Mapbox.class.getDeclaredField(FIELD_ACCOUNTS);
accounts.setAccessible(true);
AccountsManager manager = mock(AccountsManager.class);
accounts.set(mapbox, manager);
} catch (Exception exception) {
throw new AssertionError();
}

View File

@@ -8,6 +8,7 @@ import android.util.DisplayMetrics;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.utils.ConfigUtils;
import org.junit.After;
import org.junit.Before;
@@ -43,43 +44,33 @@ public class MapboxTest {
}
@Test
public void testGetAccessToken() {
final String accessToken = "pk.0000000001";
MapboxInjector.inject(context, accessToken);
assertSame(accessToken, Mapbox.getAccessToken());
public void testGetApiKey() {
final String apiKey = "pk.0000000001";
MapboxInjector.inject(context, apiKey, ConfigUtils.getMockedOptions());
assertSame(apiKey, Mapbox.getApiKey());
}
@Test
public void testApplicationContext() {
MapboxInjector.inject(context, "pk.0000000001");
MapboxInjector.inject(context, "pk.0000000001", ConfigUtils.getMockedOptions());
assertNotNull(Mapbox.getApplicationContext());
assertNotEquals(context, appContext);
assertEquals(appContext, appContext);
}
@Test
public void testPkTokenValid() {
assertTrue(Mapbox.isAccessTokenValid("pk.0000000001"));
}
@Test
public void testSkTokenValid() {
assertTrue(Mapbox.isAccessTokenValid("sk.0000000001"));
public void testPlainTokenValid() {
assertTrue(Mapbox.isApiKeyValid("apiKey"));
}
@Test
public void testEmptyToken() {
assertFalse(Mapbox.isAccessTokenValid(""));
assertFalse(Mapbox.isApiKeyValid(""));
}
@Test
public void testNullToken() {
assertFalse(Mapbox.isAccessTokenValid(null));
}
@Test
public void testBlaBlaToken() {
assertFalse(Mapbox.isAccessTokenValid("blabla"));
assertFalse(Mapbox.isApiKeyValid(null));
}
@Test
@@ -94,10 +85,8 @@ public class MapboxTest {
expectedException.expect(MapboxConfigurationException.class);
expectedException.expectMessage(
"\nUsing MapView requires calling Mapbox.getInstance(Context context, String accessToken) before "
+ "inflating or creating the view. The access token parameter is required when using a Mapbox service."
+ "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."
"\nUsing MapView requires calling Mapbox.getInstance(Context context, String apiKey) before "
+ "inflating or creating the view."
);
new MapView(context);
}

View File

@@ -2,10 +2,6 @@ package com.mapbox.mapboxsdk.maps;
import android.content.Context;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -14,7 +10,6 @@ import org.robolectric.RobolectricTestRunner;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(RobolectricTestRunner.class)
public class AttributionDialogManagerTest {
@@ -28,72 +23,14 @@ public class AttributionDialogManagerTest {
Style style = mock(Style.class);
private AttributionDialogManager attributionDialogManager;
private CameraPosition cameraPosition;
private static final String ASSERT_MAPBOX_TOKEN = "TestAccessToken";
private static final String ASSERT_MAPBOX_STYLE_URI = "mapbox://styles/mapbox/streets-v11";
private static final String ASSERT_MAPBOX_LOCAL_STYLE_URI = "asset://style.json";
private static final String ASSERT_MAPBOX_PACKAGE_NAME = "com.mapbox.attributionmanagertest";
private static final String ASSERT_MAPBOX_FEEDBACK_FINAL_URL =
"https://apps.mapbox.com/feedback?referrer=com.mapbox.attributionmanagertest&"
+ "access_token=TestAccessToken&owner=mapbox&id=streets-v11"
+ "#/22.200001/11.100000/12.000000/24.000000/5";
private static final String ASSERT_MAPBOX_FEEDHACK_FINAL_URL_LOCAL_STYLE =
"https://apps.mapbox.com/feedback?referrer=com.mapbox.attributionmanagertest&"
+ "access_token=TestAccessToken#/22.200001/11.100000/12.000000/24.000000/5";
private static final String ASSERT_MAPBOX_FEEDBACL_FINAL_URL_NULL_CAMERA_POSITION =
"https://apps.mapbox.com/feedback?referrer=com.mapbox.attributionmanagertest&access_token=TestAccessToken";
@Before
public void beforeTest() {
attributionDialogManager = new AttributionDialogManager(context, mapboxMap);
cameraPosition = new CameraPosition.Builder(CameraPosition.DEFAULT)
.tilt(5.0f).zoom(12).bearing(24.0f).target(new LatLng(11.1f, 22.2f)).build();
}
@Test
public void testSanity() {
assertNotNull("AttributionDialogManager should not be null", attributionDialogManager);
}
@Test
public void testBuildMapFeedbackMapUrl() {
when(context.getApplicationContext()).thenReturn(context);
when(context.getPackageName()).thenReturn(ASSERT_MAPBOX_PACKAGE_NAME);
when(style.getUri()).thenReturn(ASSERT_MAPBOX_STYLE_URI);
when(mapboxMap.getCameraPosition()).thenReturn(cameraPosition);
when(mapboxMap.getStyle()).thenReturn(style);
Assert.assertEquals(ASSERT_MAPBOX_FEEDBACK_FINAL_URL,
attributionDialogManager.buildMapFeedbackMapUrl(ASSERT_MAPBOX_TOKEN));
}
@Test
public void testBuildMapFeedbackMapUrlWithLocalStyleJson() {
when(context.getApplicationContext()).thenReturn(context);
when(context.getPackageName()).thenReturn(ASSERT_MAPBOX_PACKAGE_NAME);
when(style.getUri()).thenReturn(ASSERT_MAPBOX_LOCAL_STYLE_URI);
when(mapboxMap.getCameraPosition()).thenReturn(cameraPosition);
when(mapboxMap.getStyle()).thenReturn(style);
Assert.assertEquals(ASSERT_MAPBOX_FEEDHACK_FINAL_URL_LOCAL_STYLE,
attributionDialogManager.buildMapFeedbackMapUrl(ASSERT_MAPBOX_TOKEN));
}
@Test
public void testBuildMapFeedbackMapUrlWithNullCameraPosition() {
when(context.getApplicationContext()).thenReturn(context);
when(context.getPackageName()).thenReturn(ASSERT_MAPBOX_PACKAGE_NAME);
when(style.getUri()).thenReturn(ASSERT_MAPBOX_LOCAL_STYLE_URI);
when(mapboxMap.getCameraPosition()).thenReturn(null);
when(mapboxMap.getStyle()).thenReturn(style);
Assert.assertEquals(ASSERT_MAPBOX_FEEDBACL_FINAL_URL_NULL_CAMERA_POSITION,
attributionDialogManager.buildMapFeedbackMapUrl(ASSERT_MAPBOX_TOKEN));
}
}

View File

@@ -1,16 +1,21 @@
package com.mapbox.mapboxsdk.maps
import android.content.Context
import com.mapbox.mapboxsdk.MapboxInjector
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.constants.MapboxConstants
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.style.layers.TransitionOptions
import com.mapbox.mapboxsdk.utils.ConfigUtils
import io.mockk.*
import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
@@ -26,8 +31,15 @@ class MapboxMapTest {
private lateinit var developerAnimationListener: MapboxMap.OnDeveloperAnimationListener
@Mock
private lateinit var context: Context
@Mock
private lateinit var appContext: Context
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
MapboxInjector.inject(context, "abcdef", ConfigUtils.getMockedOptions())
cameraChangeDispatcher = spyk()
developerAnimationListener = mockk(relaxed = true)
nativeMapView = mockk(relaxed = true)
@@ -36,7 +48,7 @@ class MapboxMapTest {
every { nativeMapView.isDestroyed } returns false
every { nativeMapView.nativePtr } returns 5
mapboxMap.injectLocationComponent(spyk())
mapboxMap.setStyle(Style.MAPBOX_STREETS)
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"))
mapboxMap.onFinishLoadingStyle()
}

View File

@@ -20,7 +20,7 @@ class StyleBuilderTest {
@Test
fun testFromUrl() {
val expected = Style.MAPBOX_STREETS
val expected = Style.getPredefinedStyle("Streets")
val builder = Style.Builder()
builder.fromUrl(expected)
assertEquals(expected, builder.uri)

View File

@@ -1,13 +1,16 @@
package com.mapbox.mapboxsdk.maps
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.ShapeDrawable
import com.mapbox.mapboxsdk.MapboxInjector
import com.mapbox.mapboxsdk.constants.MapboxConstants
import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException
import com.mapbox.mapboxsdk.style.layers.SymbolLayer
import com.mapbox.mapboxsdk.style.layers.TransitionOptions
import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
import com.mapbox.mapboxsdk.utils.ConfigUtils
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
@@ -16,6 +19,8 @@ import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
@@ -25,8 +30,16 @@ class StyleTest {
private lateinit var nativeMapView: NativeMap
@Mock
private lateinit var context: Context
@Mock
private lateinit var appContext: Context
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
MapboxInjector.inject(context, "abcdef", ConfigUtils.getMockedOptions())
nativeMapView = mockk(relaxed = true)
mapboxMap = MapboxMap(nativeMapView, null, null, null, null, null, null)
every { nativeMapView.isDestroyed } returns false
@@ -35,9 +48,9 @@ class StyleTest {
@Test
fun testFromUrl() {
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS)
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets"))
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
}
@Test
@@ -61,7 +74,12 @@ class StyleTest {
val builder = Style.Builder().withLayer(layer)
mapboxMap.setStyle(builder)
mapboxMap.onFinishLoadingStyle()
verify(exactly = 1) { nativeMapView.addLayerBelow(layer, MapboxConstants.LAYER_ID_ANNOTATIONS) }
verify(exactly = 1) {
nativeMapView.addLayerBelow(
layer,
MapboxConstants.LAYER_ID_ANNOTATIONS
)
}
}
@Test
@@ -117,9 +135,10 @@ class StyleTest {
fun testWithFromLoadingSource() {
val source = mockk<GeoJsonSource>()
every { source.id } returns "1"
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withSource(source)
val builder =
Style.Builder().fromUrl(Style.getPredefinedStyle("Streets")).withSource(source)
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addSource(source) }
}
@@ -128,20 +147,26 @@ class StyleTest {
fun testWithFromLoadingLayer() {
val layer = mockk<SymbolLayer>()
every { layer.id } returns "1"
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withLayer(layer)
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets")).withLayer(layer)
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addLayerBelow(layer, MapboxConstants.LAYER_ID_ANNOTATIONS) }
verify(exactly = 1) {
nativeMapView.addLayerBelow(
layer,
MapboxConstants.LAYER_ID_ANNOTATIONS
)
}
}
@Test
fun testWithFromLoadingLayerAt() {
val layer = mockk<SymbolLayer>()
every { layer.id } returns "1"
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withLayerAt(layer, 1)
val builder =
Style.Builder().fromUrl(Style.getPredefinedStyle("Streets")).withLayerAt(layer, 1)
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addLayerAt(layer, 1) }
}
@@ -150,9 +175,10 @@ class StyleTest {
fun testWithFromLoadingLayerBelow() {
val layer = mockk<SymbolLayer>()
every { layer.id } returns "1"
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withLayerBelow(layer, "below")
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets"))
.withLayerBelow(layer, "below")
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addLayerBelow(layer, "below") }
}
@@ -161,9 +187,10 @@ class StyleTest {
fun testWithFromLoadingLayerAbove() {
val layer = mockk<SymbolLayer>()
every { layer.id } returns "1"
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withLayerBelow(layer, "below")
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets"))
.withLayerBelow(layer, "below")
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addLayerBelow(layer, "below") }
}
@@ -171,9 +198,10 @@ class StyleTest {
@Test
fun testWithFromLoadingTransitionOptions() {
val transitionOptions = TransitionOptions(100, 200)
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withTransition(transitionOptions)
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets"))
.withTransition(transitionOptions)
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.transitionOptions = transitionOptions }
}
@@ -182,9 +210,9 @@ class StyleTest {
fun testFromCallback() {
val callback = mockk<Style.OnStyleLoaded>()
every { callback.onStyleLoaded(any()) } answers {}
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS)
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets"))
mapboxMap.setStyle(builder, callback)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { callback.onStyleLoaded(any()) }
}
@@ -237,9 +265,10 @@ class StyleTest {
mapboxMap.getStyle(callback)
val source = mockk<GeoJsonSource>()
every { source.id } returns "1"
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withSource(source)
val builder =
Style.Builder().fromUrl(Style.getPredefinedStyle("Streets")).withSource(source)
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.MAPBOX_STREETS }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Streets") }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addSource(source) }
verify(exactly = 1) { callback.onStyleLoaded(any()) }
@@ -253,7 +282,8 @@ class StyleTest {
@Test
fun testGetNullWhileLoading() {
val transitionOptions = TransitionOptions(100, 200)
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS).withTransition(transitionOptions)
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets"))
.withTransition(transitionOptions)
mapboxMap.setStyle(builder)
Assert.assertNull(mapboxMap.style)
mapboxMap.notifyStyleLoaded()
@@ -271,26 +301,27 @@ class StyleTest {
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleJson = "{}" }
mapboxMap.notifyStyleLoaded()
mapboxMap.setStyle(Style.MAPBOX_STREETS)
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"))
verify(exactly = 1) { callback.onStyleLoaded(any()) }
}
@Test(expected = IllegalStateException::class)
fun testIllegalStateExceptionWithStyleReload() {
val builder = Style.Builder().fromUrl(Style.MAPBOX_STREETS)
val builder = Style.Builder().fromUrl(Style.getPredefinedStyle("Streets"))
mapboxMap.setStyle(builder)
mapboxMap.notifyStyleLoaded()
val style = mapboxMap.style
mapboxMap.setStyle(Style.Builder().fromUrl(Style.DARK))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Bright")))
style!!.addLayer(mockk<SymbolLayer>())
}
@Test
fun testAddImage() {
val bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
val builder = Style.Builder().fromUrl(Style.SATELLITE).withImage("id", bitmap)
val builder =
Style.Builder().fromUrl(Style.getPredefinedStyle("Satellite Hybrid")).withImage("id", bitmap)
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.SATELLITE }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Satellite Hybrid") }
verify(exactly = 0) { nativeMapView.addImages(any()) }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addImages(any()) }
@@ -301,9 +332,10 @@ class StyleTest {
val drawable = ShapeDrawable()
drawable.intrinsicHeight = 10
drawable.intrinsicWidth = 10
val builder = Style.Builder().fromUrl(Style.SATELLITE).withImage("id", drawable)
val builder =
Style.Builder().fromUrl(Style.getPredefinedStyle("Satellite Hybrid")).withImage("id", drawable)
mapboxMap.setStyle(builder)
verify(exactly = 1) { nativeMapView.styleUri = Style.SATELLITE }
verify(exactly = 1) { nativeMapView.styleUri = Style.getPredefinedStyle("Satellite Hybrid") }
verify(exactly = 0) { nativeMapView.addImages(any()) }
mapboxMap.notifyStyleLoaded()
verify(exactly = 1) { nativeMapView.addImages(any()) }
@@ -325,7 +357,11 @@ class StyleTest {
try {
mapboxMap.style!!.addSource(source2)
} catch (ex: Exception) {
Assert.assertEquals("Source that failed to be added shouldn't be cached", source1, mapboxMap.style!!.getSource("source1"))
Assert.assertEquals(
"Source that failed to be added shouldn't be cached",
source1,
mapboxMap.style!!.getSource("source1")
)
}
}
@@ -345,7 +381,11 @@ class StyleTest {
try {
mapboxMap.style!!.addLayer(layer2)
} catch (ex: Exception) {
Assert.assertEquals("Layer that failed to be added shouldn't be cached", layer1, mapboxMap.style!!.getLayer("layer1"))
Assert.assertEquals(
"Layer that failed to be added shouldn't be cached",
layer1,
mapboxMap.style!!.getLayer("layer1")
)
}
}
@@ -360,12 +400,21 @@ class StyleTest {
mapboxMap.setStyle(builder)
mapboxMap.notifyStyleLoaded()
every { nativeMapView.addLayerBelow(any(), "") } throws CannotAddLayerException("Duplicate ID")
every {
nativeMapView.addLayerBelow(
any(),
""
)
} throws CannotAddLayerException("Duplicate ID")
try {
mapboxMap.style!!.addLayerBelow(layer2, "")
} catch (ex: Exception) {
Assert.assertEquals("Layer that failed to be added shouldn't be cached", layer1, mapboxMap.style!!.getLayer("layer1"))
Assert.assertEquals(
"Layer that failed to be added shouldn't be cached",
layer1,
mapboxMap.style!!.getLayer("layer1")
)
}
}
@@ -380,12 +429,21 @@ class StyleTest {
mapboxMap.setStyle(builder)
mapboxMap.notifyStyleLoaded()
every { nativeMapView.addLayerAbove(any(), "") } throws CannotAddLayerException("Duplicate ID")
every {
nativeMapView.addLayerAbove(
any(),
""
)
} throws CannotAddLayerException("Duplicate ID")
try {
mapboxMap.style!!.addLayerAbove(layer2, "")
} catch (ex: Exception) {
Assert.assertEquals("Layer that failed to be added shouldn't be cached", layer1, mapboxMap.style!!.getLayer("layer1"))
Assert.assertEquals(
"Layer that failed to be added shouldn't be cached",
layer1,
mapboxMap.style!!.getLayer("layer1")
)
}
}
@@ -405,7 +463,11 @@ class StyleTest {
try {
mapboxMap.style!!.addLayerAt(layer2, 5)
} catch (ex: Exception) {
Assert.assertEquals("Layer that failed to be added shouldn't be cached", layer1, mapboxMap.style!!.getLayer("layer1"))
Assert.assertEquals(
"Layer that failed to be added shouldn't be cached",
layer1,
mapboxMap.style!!.getLayer("layer1")
)
}
}
}

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.module.http
import com.mapbox.mapboxsdk.MapboxInjector
import com.mapbox.mapboxsdk.http.HttpRequestUrl
import com.mapbox.mapboxsdk.utils.ConfigUtils
import io.mockk.mockk
import junit.framework.Assert.assertEquals
import org.junit.After
@@ -15,7 +16,7 @@ class HttpRequestUrlTest {
@Before
fun setUp() {
MapboxInjector.inject(mockk(relaxed = true), "pk.foobar")
MapboxInjector.inject(mockk(relaxed = true), "pk.foobar", ConfigUtils.getMockedOptions())
}
@Test

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.module.http
import com.mapbox.mapboxsdk.MapboxInjector
import com.mapbox.mapboxsdk.utils.ConfigUtils
import io.mockk.mockk
import junit.framework.Assert.assertEquals
import okhttp3.OkHttpClient
@@ -13,7 +14,7 @@ class HttpRequestUtilTest {
@Test
fun replaceHttpClient() {
MapboxInjector.inject(mockk(relaxed = true), "")
MapboxInjector.inject(mockk(relaxed = true), "", ConfigUtils.getMockedOptions())
assertEquals(HttpRequestImpl.DEFAULT_CLIENT, HttpRequestImpl.client)

View File

@@ -0,0 +1,46 @@
package com.mapbox.mapboxsdk.utils
import com.mapbox.mapboxsdk.util.DefaultStyle
import com.mapbox.mapboxsdk.util.TileServerOptions
class ConfigUtils {
companion object {
@JvmStatic
fun getMockedOptions(): TileServerOptions {
val defaultStyles = arrayOf(
DefaultStyle("maptiler://maps/streets", "Streets", 1),
DefaultStyle("maptiler://maps/outdoor", "Outdoor", 1),
DefaultStyle("maptiler://maps/basic", "Basic", 1),
DefaultStyle("maptiler://maps/bright", "Bright", 1),
DefaultStyle("maptiler://maps/pastel", "Pastel", 1),
DefaultStyle("maptiler://maps/hybrid", "Satellite Hybrid", 1),
DefaultStyle("maptiler://maps/topo", "Satellite Topo", 1)
)
val defaultStyle = defaultStyles[0].name
return TileServerOptions(
"https://api.maptiler.com",
"maptiler",
"{path}",
"sources",
null,
"/maps{path}/style.json",
"maps",
null,
"/maps{path}",
"sprites",
null,
"/fonts{path}",
"fonts",
null,
"{path}",
"tiles",
null,
"key",
true,
defaultStyle,
defaultStyles
)
}
}
}

View File

@@ -3,8 +3,8 @@
<issue
id="UnusedResources"
message="The resource `R.string.mapbox_access_token` appears to be unused"
errorLine1=" &lt;string name=&quot;mapbox_access_token&quot;>YOUR_MAPBOX_ACCESS_TOKEN_GOES_HERE&lt;/string>"
message="The resource `R.string.api_key` appears to be unused"
errorLine1=" &lt;string name=&quot;api_key&quot;>YOUR_API_KEY_GOES_HERE&lt;/string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/developer-config.xml"

View File

@@ -190,7 +190,7 @@ class LocationComponentTest : EspressoTest() {
uiController: UiController,
context: Context
) {
mapboxMap.setStyle(Style.Builder().fromUrl(Style.LIGHT))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Bright")))
component.activateLocationComponent(
LocationComponentActivationOptions
@@ -675,7 +675,7 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
component.isLocationComponentEnabled = false
mapboxMap.setStyle(Style.Builder().fromUrl(Style.LIGHT))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Bright")))
component.isLocationComponentEnabled = true
TestingAsyncUtils.waitForLayer(uiController, mapView)
@@ -796,7 +796,7 @@ class LocationComponentTest : EspressoTest() {
component.onStop()
component.onStart()
mapboxMap.setStyle(Style.Builder().fromUrl(Style.DARK))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Bright")))
TestingAsyncUtils.waitForLayer(uiController, mapView)
}
}
@@ -821,7 +821,7 @@ class LocationComponentTest : EspressoTest() {
.build()
)
component.isLocationComponentEnabled = true
mapboxMap.setStyle(Style.Builder().fromUrl(Style.DARK))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Bright")))
component.onStop()
component.onStart()
TestingAsyncUtils.waitForLayer(uiController, mapView)
@@ -908,7 +908,7 @@ class LocationComponentTest : EspressoTest() {
)
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
mapboxMap.setStyle(Style.Builder().fromUrl(Style.LIGHT))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Bright")))
component.onStop()
TestingAsyncUtils.waitForLayer(uiController, mapView)
component.onStart()

View File

@@ -154,7 +154,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.renderMode = RenderMode.NORMAL
component.forceLocationUpdate(location)
styleChangeIdlingResource.waitForStyle(mapboxMap, Style.LIGHT)
styleChangeIdlingResource.waitForStyle(mapboxMap, Style.getPredefinedStyle("Bright"))
TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(component.renderMode, `is`(equalTo(RenderMode.NORMAL)))
@@ -456,7 +456,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.renderMode = RenderMode.NORMAL
component.forceLocationUpdate(location)
styleChangeIdlingResource.waitForStyle(mapboxMap, Style.LIGHT)
styleChangeIdlingResource.waitForStyle(mapboxMap, Style.getPredefinedStyle("Bright"))
TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(component.renderMode, `is`(equalTo(RenderMode.NORMAL)))
@@ -503,7 +503,7 @@ class LocationLayerControllerTest : EspressoTest() {
`is`(true)
)
mapboxMap.setStyle(Style.Builder().fromUrl(Style.LIGHT))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Bright")))
TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(

View File

@@ -0,0 +1,96 @@
package com.mapbox.mapboxsdk.maps
import androidx.test.annotation.UiThreadTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.mapbox.mapboxsdk.AppCenter
import com.mapbox.mapboxsdk.Mapbox
import com.mapbox.mapboxsdk.WellKnownTileServer
import com.mapbox.mapboxsdk.storage.FileSource
import com.mapbox.mapboxsdk.testapp.MapboxApplication
import com.mapbox.mapboxsdk.util.TileServerOptions
import org.junit.*
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class BootstrapTest : AppCenter() {
var apiKeyBackup: String? = null
@Before
@UiThreadTest
fun before() {
apiKeyBackup = Mapbox.getApiKey()
}
@After
@UiThreadTest
fun after() {
val context = InstrumentationRegistry.getInstrumentation().context
Mapbox.getInstance(context, apiKeyBackup, MapboxApplication.TILE_SERVER)
}
@Test
@UiThreadTest
fun defaultBootstrap() {
val context = InstrumentationRegistry.getInstrumentation().context
Mapbox.getInstance(context)
val tileServerOptions = TileServerOptions.get(WellKnownTileServer.MapLibre)
Assert.assertTrue(
Style.getPredefinedStyles().count() == tileServerOptions.defaultStyles.count()
)
Assert.assertTrue(
Style.getPredefinedStyles().first().url == tileServerOptions.defaultStyles.first().url
)
val fileSource = FileSource.getInstance(context)
Assert.assertEquals(fileSource.apiBaseUrl, tileServerOptions.baseURL)
}
@Test
@UiThreadTest
fun maptilerBootstrap() {
val context = InstrumentationRegistry.getInstrumentation().context
val key = "abcdef"
Mapbox.getInstance(context, key, WellKnownTileServer.MapTiler)
val tileServerOptions = TileServerOptions.get(WellKnownTileServer.MapTiler)
Assert.assertTrue(
Style.getPredefinedStyles().count() == tileServerOptions.defaultStyles.count()
)
Assert.assertTrue(
Style.getPredefinedStyles().first().url == tileServerOptions.defaultStyles.first().url
)
val fileSource = FileSource.getInstance(context)
Assert.assertEquals(fileSource.apiBaseUrl, tileServerOptions.baseURL)
Assert.assertEquals(fileSource.apiKey, key)
}
@Test
@UiThreadTest
fun duplicateBootstrap() {
val context = InstrumentationRegistry.getInstrumentation().context
val key = "pk.abcdef"
Mapbox.getInstance(context, key, WellKnownTileServer.MapTiler)
Mapbox.getInstance(context)
Mapbox.getInstance(context, key, WellKnownTileServer.Mapbox)
val tileServerOptions = TileServerOptions.get(WellKnownTileServer.Mapbox)
Assert.assertTrue(
Style.getPredefinedStyles().count() == tileServerOptions.defaultStyles.count()
)
Assert.assertTrue(
Style.getPredefinedStyles().first().url == tileServerOptions.defaultStyles.first().url
)
val fileSource = FileSource.getInstance(context)
Assert.assertEquals(fileSource.apiBaseUrl, tileServerOptions.baseURL)
Assert.assertEquals(fileSource.apiKey, key)
}
}

View File

@@ -21,8 +21,8 @@ import static junit.framework.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
public class MapboxTest extends AppCenter {
private static final String ACCESS_TOKEN = "pk.0000000001";
private static final String ACCESS_TOKEN_2 = "pk.0000000002";
private static final String API_KEY = "pk.0000000001";
private static final String API_KEY_2 = "pk.0000000002";
@Rule
public ExpectedException expectedException = ExpectedException.none();
@@ -31,7 +31,7 @@ public class MapboxTest extends AppCenter {
@Before
public void setup() {
realToken = Mapbox.getAccessToken();
realToken = Mapbox.getApiKey();
}
@Test
@@ -52,44 +52,26 @@ public class MapboxTest extends AppCenter {
@Test
@UiThreadTest
public void setAccessToken() {
Mapbox.setAccessToken(ACCESS_TOKEN);
assertSame(ACCESS_TOKEN, Mapbox.getAccessToken());
Mapbox.setAccessToken(ACCESS_TOKEN_2);
assertSame(ACCESS_TOKEN_2, Mapbox.getAccessToken());
public void setApiKey() {
Mapbox.setApiKey(API_KEY);
assertSame(API_KEY, Mapbox.getApiKey());
Mapbox.setApiKey(API_KEY_2);
assertSame(API_KEY_2, Mapbox.getApiKey());
}
@Test
@UiThreadTest
public void setInvalidAccessToken() {
final String invalidAccessToken = "xyz";
public void setNullApiKey() {
expectedException.expect(MapboxConfigurationException.class);
expectedException.expectMessage(
"A valid access token parameter is required when using a Mapbox service."
+ "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."
+ "Currently provided token is: " + invalidAccessToken
"A valid API key is required, currently provided key is: " + null
);
Mapbox.setAccessToken(invalidAccessToken);
}
@Test
@UiThreadTest
public void setNullAccessToken() {
expectedException.expect(MapboxConfigurationException.class);
expectedException.expectMessage(
"A valid access token parameter is required when using a Mapbox service."
+ "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."
+ "Currently provided token is: " + null
);
Mapbox.setAccessToken(null);
Mapbox.setApiKey(null);
}
@After
public void tearDown() {
Mapbox.setAccessToken(realToken);
Mapbox.setApiKey(realToken);
}
}

View File

@@ -6,12 +6,15 @@ import androidx.test.annotation.UiThreadTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.mapbox.mapboxsdk.AppCenter
import com.mapbox.mapboxsdk.Mapbox
import com.mapbox.mapboxsdk.WellKnownTileServer
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.geometry.ProjectedMeters
import com.mapbox.mapboxsdk.maps.renderer.MapRenderer
import com.mapbox.mapboxsdk.style.layers.TransitionOptions
import com.mapbox.mapboxsdk.testapp.MapboxApplication
import com.mapbox.mapboxsdk.testapp.utils.TestConstants
import junit.framework.Assert.*
import org.junit.After
@@ -41,6 +44,8 @@ class NativeMapViewTest : AppCenter() {
@UiThreadTest
fun before() {
val context = InstrumentationRegistry.getInstrumentation().context
val apiKey = Mapbox.getApiKey()
Mapbox.getInstance(context, apiKey, WellKnownTileServer.MapTiler)
nativeMapView = NativeMapView(context, 2.0f, false, null, null, DummyRenderer(context))
nativeMapView.resizeView(WIDTH, HEIGHT)
}
@@ -48,13 +53,16 @@ class NativeMapViewTest : AppCenter() {
@After
@UiThreadTest
fun after() {
val context = InstrumentationRegistry.getInstrumentation().context
val apiKey = Mapbox.getApiKey()
Mapbox.getInstance(context, apiKey, MapboxApplication.TILE_SERVER)
nativeMapView.destroy()
}
@Test
@UiThreadTest
fun testSetStyleUrl() {
val expected = Style.DARK
val expected = Style.getPredefinedStyle("Pastel")
nativeMapView.styleUri = expected
val actual = nativeMapView.styleUri
assertEquals("Style URL should match", expected, actual)

View File

@@ -69,7 +69,7 @@ class OfflineDownloadTest : OfflineRegion.OfflineRegionObserver {
private fun createTestRegionDefinition(): OfflineRegionDefinition {
return OfflineGeometryRegionDefinition(
Style.MAPBOX_STREETS,
Style.getPredefinedStyle("Streets"),
Point.fromLngLat(50.847857, 4.360137),
17.0,
17.0,

View File

@@ -38,7 +38,7 @@ class MapSnapshotterTest {
val options = MapSnapshotter.Options(512, 512)
.withPixelRatio(1.0f)
.withStyleBuilder(
Style.Builder().fromUri(Style.SATELLITE_STREETS)
Style.Builder().fromUri(Style.getPredefinedStyle("Satellite Hybrid"))
.withLayerAbove(bg, "country-label")
)
.withCameraPosition(

View File

@@ -70,9 +70,9 @@ class ImageMissingTest : AppCenter() {
"""
{
"version": 8,
"name": "Mapbox Streets",
"sprite": "mapbox://sprites/mapbox/streets-v8",
"glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
"name": "Streets",
"sprite": "maptiler://sprites/streets/sprite",
"glyphs": "maptiler://fonts/{fontstack}/{range}.pbf",
"sources": {
"point": {
"type": "geojson",
@@ -114,9 +114,9 @@ class ImageMissingTest : AppCenter() {
"""
{
"version": 8,
"name": "Mapbox Streets",
"sprite": "asset://sprites/mapbox/invalid",
"glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
"name": "Streets",
"sprite": "maptiler://sprites/streets/sprite",
"glyphs": "maptiler://fonts/{fontstack}/{range}.pbf",
"sources": {
"point": {
"type": "geojson",

View File

@@ -23,7 +23,7 @@ class StyleLoadTest : EspressoTest() {
val layer = SymbolLayer("id", "id")
mapboxMap.setStyle(Style.Builder().withSource(source).withLayer(layer))
TestingAsyncUtils.waitForLayer(uiController, mapView)
mapboxMap.setStyle(Style.Builder().fromUrl(Style.MAPBOX_STREETS))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.getPredefinedStyle("Streets")))
TestingAsyncUtils.waitForLayer(uiController, mapView)
source.setGeoJson("{}")
}

View File

@@ -184,11 +184,11 @@ public class RuntimeStyleTests extends EspressoTest {
public void testAddRemoveSource() {
validateTestSetup();
invoke(mapboxMap, (uiController, mapboxMap) -> {
mapboxMap.getStyle().addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
mapboxMap.getStyle().addSource(new VectorSource("my-source", "maptiler://sources/hillshades"));
mapboxMap.getStyle().removeSource("my-source");
// Add initial source
mapboxMap.getStyle().addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
mapboxMap.getStyle().addSource(new VectorSource("my-source", "maptiler://sources/hillshades"));
// Remove
boolean removeOk = mapboxMap.getStyle().removeSource("my-source");
@@ -196,7 +196,7 @@ public class RuntimeStyleTests extends EspressoTest {
assertNull(mapboxMap.getStyle().getLayer("my-source"));
// Add
Source source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
Source source = new VectorSource("my-source", "maptiler://sources/hillshades");
mapboxMap.getStyle().addSource(source);
// Remove, preserving the reference
@@ -210,7 +210,7 @@ public class RuntimeStyleTests extends EspressoTest {
// Test adding a duplicate source
try {
Source source2 = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
Source source2 = new VectorSource("my-source", "maptiler://sources/hillshades");
mapboxMap.getStyle().addSource(source2);
fail("Should not have been allowed to add a source with a duplicate id");
} catch (CannotAddSourceException cannotAddSourceException) {
@@ -224,9 +224,9 @@ public class RuntimeStyleTests extends EspressoTest {
public void testVectorSourceUrlGetter() {
validateTestSetup();
invoke(mapboxMap, (uiController, mapboxMap) -> {
VectorSource source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
VectorSource source = new VectorSource("my-source", "maptiler://sources/hillshades");
mapboxMap.getStyle().addSource(source);
assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUri());
assertEquals("maptiler://sources/hillshades", source.getUri());
});
}
@@ -234,9 +234,9 @@ public class RuntimeStyleTests extends EspressoTest {
public void testRasterSourceUrlGetter() {
validateTestSetup();
invoke(mapboxMap, (uiController, mapboxMap) -> {
RasterSource source = new RasterSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
RasterSource source = new RasterSource("my-source", "maptiler://sources/hillshades");
mapboxMap.getStyle().addSource(source);
assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUri());
assertEquals("maptiler://sources/hillshades", source.getUri());
});
}
@@ -260,7 +260,7 @@ public class RuntimeStyleTests extends EspressoTest {
@Override
public void perform(UiController uiController, View view) {
mapboxMap.getStyle().addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
mapboxMap.getStyle().addSource(new VectorSource("my-source", "maptiler://sources/hillshades"));
mapboxMap.getStyle().addLayer(new LineLayer("my-layer", "my-source"));
mapboxMap.getStyle().removeSource("my-source");
assertNotNull(mapboxMap.getStyle().getSource("my-source"));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,766 @@
{
"id": "hybrid",
"name": "Satellite Hybrid",
"zoom": 1,
"pitch": 0,
"center": [
0,
0
],
"glyphs": "https://api.maptiler.com/fonts/{fontstack}/{range}.pbf?key=uwvyvzaF2P7UWbyOEvjU",
"layers": [
{
"id": "satellite",
"type": "raster",
"paint": {
"raster-opacity": 1
},
"filter": [
"all"
],
"layout": {
"visibility": "visible"
},
"source": "satellite",
"minzoom": 0
},
{
"id": "tunnel",
"type": "line",
"paint": {
"line-color": "rgba(255, 255, 255, 0.2)",
"line-width": [
"interpolate",
[
"exponential",
1.5
],
[
"zoom"
],
6,
0.5,
20,
30
],
"line-dasharray": [
0.28,
0.14
]
},
"filter": [
"all",
[
"==",
"$type",
"LineString"
],
[
"==",
"brunnel",
"tunnel"
],
[
"in",
"class",
"motorway",
"primary",
"secondary",
"tertiary",
"trunk"
]
],
"layout": {
"line-cap": "butt",
"line-join": "miter"
},
"source": "openmaptiles",
"source-layer": "transportation"
},
{
"id": "path",
"type": "line",
"paint": {
"line-color": "rgba(247, 247, 247, 0.33)",
"line-width": [
"interpolate",
[
"exponential",
1.5
],
[
"zoom"
],
14,
0.5,
20,
4
],
"line-dasharray": [
1,
1
]
},
"filter": [
"all",
[
"==",
"$type",
"LineString"
],
[
"in",
"class",
"path",
"track"
]
],
"layout": {
"line-cap": "square",
"line-join": "bevel"
},
"source": "openmaptiles",
"source-layer": "transportation"
},
{
"id": "road",
"type": "line",
"paint": {
"line-color": [
"interpolate",
[
"linear"
],
[
"zoom"
],
8,
"rgba(255, 255, 255, 0.2)",
14,
"rgba(255, 255, 255, 0.3)"
],
"line-width": [
"interpolate",
[
"linear"
],
[
"zoom"
],
5,
[
"match",
[
"get",
"class"
],
[
"motorway",
"motorway_link"
],
1,
0
],
7,
[
"match",
[
"get",
"class"
],
[
"motorway",
"motorway_link"
],
1.4,
0
],
8,
[
"match",
[
"get",
"class"
],
[
"motorway",
"motorway_link",
"primary",
"trunk"
],
0.75,
0
],
9,
[
"match",
[
"get",
"class"
],
[
"secondary",
"tertiary"
],
0.7,
1
],
10,
[
"match",
[
"get",
"class"
],
[
"motorway",
"motorway_link"
],
1.3,
1.3
],
14,
[
"match",
[
"get",
"class"
],
[
"minor",
"service"
],
0.5,
2.4
]
]
},
"filter": [
"all",
[
"==",
"$type",
"LineString"
],
[
"!in",
"class",
"rail",
"ferry",
"path",
"track"
],
[
"!=",
"brunnel",
"tunnel"
]
],
"layout": {
"line-cap": "butt",
"line-join": "round"
},
"source": "openmaptiles",
"minzoom": 6,
"source-layer": "transportation"
},
{
"id": "railway",
"type": "line",
"paint": {
"line-color": "rgba(179, 170, 158, 0.2)",
"line-opacity": [
"interpolate",
[
"linear"
],
[
"zoom"
],
11,
0.5,
16,
1.3
]
},
"filter": [
"==",
"class",
"rail"
],
"layout": {
"visibility": "visible"
},
"source": "openmaptiles",
"minzoom": 11,
"source-layer": "transportation"
},
{
"id": "admin_sub",
"type": "line",
"paint": {
"line-color": "rgba(194, 194, 194, 0.5)",
"line-dasharray": [
2,
1
]
},
"filter": [
"in",
"admin_level",
4,
6,
8
],
"layout": {
"visibility": "visible"
},
"source": "openmaptiles",
"minzoom": 3,
"source-layer": "boundary"
},
{
"id": "admin_country-dark",
"type": "line",
"paint": {
"line-color": "rgba(0, 0, 0, 0.51)",
"line-width": [
"interpolate",
[
"exponential",
1.5
],
[
"zoom"
],
3,
0.5,
21,
32
],
"line-offset": 1
},
"filter": [
"all",
[
"<=",
"admin_level",
2
],
[
"==",
"$type",
"LineString"
]
],
"layout": {
"line-cap": "butt",
"line-join": "round",
"visibility": "visible"
},
"source": "openmaptiles",
"source-layer": "boundary"
},
{
"id": "admin_country",
"type": "line",
"paint": {
"line-color": "rgba(226, 226, 226, 1)",
"line-width": [
"interpolate",
[
"exponential",
1.5
],
[
"zoom"
],
3,
0.5,
21,
32
]
},
"filter": [
"all",
[
"<=",
"admin_level",
2
],
[
"==",
"$type",
"LineString"
]
],
"layout": {
"line-cap": "round",
"line-join": "round",
"visibility": "visible"
},
"source": "openmaptiles",
"source-layer": "boundary"
},
{
"id": "road_label",
"type": "symbol",
"paint": {
"text-color": "rgba(255, 255, 255, 1)",
"text-halo-color": "rgba(43, 43, 43, 1)",
"text-halo-width": 1
},
"filter": [
"==",
"$type",
"LineString"
],
"layout": {
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"cubic-bezier",
0.75,
1,
0.75,
1
],
[
"zoom"
],
10,
8,
15,
9
],
"text-field": "{name:latin} {name:nonlatin}",
"text-transform": "none",
"symbol-placement": "line",
"text-letter-spacing": 0.1,
"text-rotation-alignment": "map"
},
"source": "openmaptiles",
"source-layer": "transportation_name"
},
{
"id": "place_label",
"type": "symbol",
"paint": {
"text-color": "rgba(255, 255, 255, 1)",
"text-halo-blur": 0.5,
"text-halo-color": [
"match",
[
"get",
"class"
],
[
"city"
],
"rgba(0, 0, 0, 0.75)",
"rgba(43, 43, 43, 1)"
],
"text-halo-width": 1
},
"filter": [
"all",
[
"==",
"$type",
"Point"
],
[
"!in",
"class",
"country",
"state"
]
],
"layout": {
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"cubic-bezier",
0.5,
1,
0.5,
1
],
[
"zoom"
],
3,
[
"match",
[
"get",
"class"
],
"city",
11,
10
],
6,
[
"match",
[
"get",
"class"
],
"city",
14.5,
11
],
8,
[
"match",
[
"get",
"class"
],
"city",
16,
12
],
10,
[
"match",
[
"get",
"class"
],
"city",
20,
13
]
],
"text-field": "{name:latin}\n{name:nonlatin}",
"text-max-width": 10
},
"source": "openmaptiles",
"maxzoom": 16,
"minzoom": 3,
"source-layer": "place"
},
{
"id": "state_label",
"type": "symbol",
"paint": {
"text-color": "rgba(255, 255, 255, 1)",
"text-halo-blur": 1,
"text-halo-color": "rgba(0, 0, 0, 1)",
"text-halo-width": 1
},
"filter": [
"all",
[
"==",
"$type",
"Point"
],
[
"in",
"class",
"state"
]
],
"layout": {
"text-font": [
"Noto Sans Italic"
],
"text-size": [
"interpolate",
[
"cubic-bezier",
0.75,
1,
0.75,
1
],
[
"zoom"
],
1,
[
"step",
[
"get",
"rank"
],
13,
1,
12,
2,
12
],
4,
[
"step",
[
"get",
"rank"
],
15,
1,
14,
2,
14
],
6,
[
"step",
[
"get",
"rank"
],
23,
1,
18,
2,
18
],
9,
[
"step",
[
"get",
"rank"
],
27,
1,
22,
2,
22
]
],
"text-field": "{name:latin}",
"text-max-width": 10
},
"source": "openmaptiles",
"maxzoom": 12,
"minzoom": 3,
"source-layer": "place"
},
{
"id": "country_label",
"type": "symbol",
"paint": {
"text-color": "rgba(255, 255, 255, 1)",
"text-halo-blur": 1,
"text-halo-color": "rgba(0, 0, 0, 1)",
"text-halo-width": 1
},
"filter": [
"all",
[
"==",
"$type",
"Point"
],
[
"in",
"class",
"country"
]
],
"layout": {
"text-font": [
"Noto Sans Bold"
],
"text-size": [
"interpolate",
[
"cubic-bezier",
0.75,
1,
0.75,
1
],
[
"zoom"
],
1,
[
"step",
[
"get",
"rank"
],
13,
1,
12,
2,
12
],
4,
[
"step",
[
"get",
"rank"
],
15,
1,
14,
2,
14
],
6,
[
"step",
[
"get",
"rank"
],
23,
1,
18,
2,
18
],
9,
[
"step",
[
"get",
"rank"
],
27,
1,
22,
2,
22
]
],
"text-field": "{name:latin}",
"text-max-width": 10
},
"source": "openmaptiles",
"maxzoom": 12,
"source-layer": "place"
}
],
"bearing": 0,
"sources": {
"satellite": {
"url": "https://api.maptiler.com/tiles/satellite/tiles.json?key=uwvyvzaF2P7UWbyOEvjU",
"type": "raster",
"tileSize": 256
},
"openmaptiles": {
"url": "https://api.maptiler.com/tiles/v3/tiles.json?key=uwvyvzaF2P7UWbyOEvjU",
"type": "vector"
}
},
"version": 8,
"metadata": {
"maputnik:renderer": "mbgljs",
"openmaptiles:version": "3.x"
}
}

View File

@@ -6,10 +6,11 @@ import android.text.TextUtils;
import com.mapbox.mapboxsdk.MapStrictMode;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.WellKnownTileServer;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.testapp.utils.TileLoadingMeasurementUtils;
import com.mapbox.mapboxsdk.testapp.utils.TimberLogger;
import com.mapbox.mapboxsdk.testapp.utils.TokenUtils;
import com.mapbox.mapboxsdk.testapp.utils.ApiKeyUtils;
import com.squareup.leakcanary.LeakCanary;
import timber.log.Timber;
@@ -24,9 +25,11 @@ import static timber.log.Timber.DebugTree;
*/
public class MapboxApplication extends Application {
private static final String DEFAULT_MAPBOX_ACCESS_TOKEN = "YOUR_MAPBOX_ACCESS_TOKEN_GOES_HERE";
private static final String ACCESS_TOKEN_NOT_SET_MESSAGE = "In order to run the Test App you need to set a valid "
+ "access token. During development, you can set the MAPBOX_ACCESS_TOKEN environment variable for the SDK to "
public static final WellKnownTileServer TILE_SERVER = WellKnownTileServer.MapTiler;
private static final String DEFAULT_API_KEY = "YOUR_API_KEY_GOES_HERE";
private static final String API_KEY_NOT_SET_MESSAGE = "In order to run the Test App you need to set a valid "
+ "API key. During development, you can set the MGL_API_KEY environment variable for the SDK to "
+ "automatically include it in the Test App. Otherwise, you can manually include it in the "
+ "res/values/developer-config.xml file in the MapboxGLAndroidSDKTestApp folder.";
@@ -73,17 +76,19 @@ public class MapboxApplication extends Application {
}
private void initializeMapbox() {
String accessToken = TokenUtils.getMapboxAccessToken(getApplicationContext());
validateAccessToken(accessToken);
Mapbox.getInstance(getApplicationContext(), accessToken);
String apiKey = ApiKeyUtils.getApiKey(getApplicationContext());
validateApiKey(apiKey);
Mapbox.getInstance(getApplicationContext(), apiKey, TILE_SERVER);
TileLoadingMeasurementUtils.setUpTileLoadingMeasurement();
MapStrictMode.setStrictModeEnabled(true);
}
private static void validateAccessToken(String accessToken) {
if (TextUtils.isEmpty(accessToken) || accessToken.equals(DEFAULT_MAPBOX_ACCESS_TOKEN)) {
Timber.e(ACCESS_TOKEN_NOT_SET_MESSAGE);
private static void validateApiKey(String apiKey) {
if (TextUtils.isEmpty(apiKey) || apiKey.equals(DEFAULT_API_KEY)) {
Timber.e(API_KEY_NOT_SET_MESSAGE);
}
}
}

View File

@@ -50,7 +50,7 @@ public class AnimatedSymbolLayerActivity extends AppCompatActivity {
private static final String RANDOM_CAR_SOURCE = "random-car-source";
private static final String RANDOM_CAR_IMAGE_ID = "random-car";
private static final String PROPERTY_BEARING = "bearing";
private static final String WATERWAY_LAYER_ID = "waterway-label";
private static final String WATERWAY_LAYER_ID = "water_intermittent";
private static final int DURATION_RANDOM_MAX = 1500;
private static final int DURATION_BASE = 3000;
@@ -77,7 +77,7 @@ public class AnimatedSymbolLayerActivity extends AppCompatActivity {
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(map -> {
this.mapboxMap = map;
map.setStyle(Style.MAPBOX_STREETS, style -> {
map.setStyle(Style.getPredefinedStyle("Streets"), style -> {
this.style = style;
setupCars();
animateRandomRoutes();

View File

@@ -52,7 +52,7 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
private void initMap(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.MAPBOX_STREETS);
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
}
@Override

View File

@@ -37,7 +37,7 @@ public class DynamicMarkerChangeActivity extends AppCompatActivity {
mapView.setTag(false);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> {
mapboxMap.setStyle(Style.MAPBOX_STREETS);
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
DynamicMarkerChangeActivity.this.mapboxMap = mapboxMap;
// Create marker

View File

@@ -77,7 +77,7 @@ public class PolygonActivity extends AppCompatActivity implements OnMapReadyCall
@Override
public void onMapReady(@NonNull MapboxMap map) {
mapboxMap = map;
map.setStyle(Style.MAPBOX_STREETS);
map.setStyle(Style.getPredefinedStyle("Streets"));
map.setOnPolygonClickListener(polygon -> Toast.makeText(
PolygonActivity.this,

View File

@@ -67,7 +67,7 @@ public class PolylineActivity extends AppCompatActivity {
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> {
PolylineActivity.this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.SATELLITE_STREETS);
mapboxMap.setStyle(Style.getPredefinedStyle("Satellite Hybrid"));
mapboxMap.setOnPolylineClickListener(polyline -> Toast.makeText(
PolylineActivity.this,
"You clicked on polyline with id = " + polyline.getId(),

View File

@@ -55,7 +55,7 @@ public class PressForMarkerActivity extends AppCompatActivity {
return false;
});
mapboxMap.setStyle(Style.MAPBOX_STREETS);
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
if (savedInstanceState != null) {
markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);

View File

@@ -74,7 +74,7 @@ public class CameraAnimationTypeActivity extends AppCompatActivity implements On
@Override
public void onMapReady(@NonNull MapboxMap map) {
mapboxMap = map;
mapboxMap.setStyle(new Style.Builder().fromUri(Style.MAPBOX_STREETS));
mapboxMap.setStyle(new Style.Builder().fromUri(Style.getPredefinedStyle("Streets")));
mapboxMap.getUiSettings().setAttributionEnabled(false);
mapboxMap.getUiSettings().setLogoEnabled(false);
mapboxMap.addOnCameraIdleListener(cameraIdleListener);

View File

@@ -79,7 +79,7 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
@Override
public void onMapReady(@NonNull final MapboxMap map) {
mapboxMap = map;
map.setStyle(Style.MAPBOX_STREETS);
map.setStyle(Style.getPredefinedStyle("Streets"));
initFab();
}

View File

@@ -60,7 +60,7 @@ public class CameraPositionActivity extends FragmentActivity implements OnMapRea
@Override
public void onMapReady(@NonNull final MapboxMap map) {
mapboxMap = map;
map.setStyle(Style.SATELLITE_STREETS, style -> {
map.setStyle(Style.getPredefinedStyle("Satellite Hybrid"), style -> {
// add a listener to FAB
fab = findViewById(R.id.fab);
fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.primary));

View File

@@ -71,7 +71,7 @@ public class GestureDetectorActivity extends AppCompatActivity {
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> {
GestureDetectorActivity.this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.MAPBOX_STREETS);
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
initializeMap();
});

View File

@@ -68,7 +68,7 @@ class LatLngBoundsActivity : AppCompatActivity() {
private fun loadStyle(featureCollection: FeatureCollection) {
mapboxMap.setStyle(
Style.Builder()
.fromUri(Style.MAPBOX_STREETS)
.fromUri(Style.getPredefinedStyle("Streets"))
.withLayer(
SymbolLayer("symbol", "symbol")
.withProperties(

View File

@@ -35,7 +35,7 @@ public class ManualZoomActivity extends AppCompatActivity {
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> {
ManualZoomActivity.this.mapboxMap = mapboxMap;
mapboxMap.setStyle(new Style.Builder().fromUri(Style.SATELLITE));
mapboxMap.setStyle(new Style.Builder().fromUri(Style.getPredefinedStyle("Satellite Hybrid")));
UiSettings uiSettings = ManualZoomActivity.this.mapboxMap.getUiSettings();
uiSettings.setAllGesturesEnabled(false);
});

View File

@@ -26,7 +26,7 @@ public class MaxMinZoomActivity extends AppCompatActivity implements OnMapReadyC
@Override
public boolean onMapClick(@NonNull LatLng point) {
if (mapboxMap != null) {
mapboxMap.setStyle(new Style.Builder().fromUri(Style.OUTDOORS));
mapboxMap.setStyle(new Style.Builder().fromUri(Style.getPredefinedStyle("Outdoor")));
}
return true;
}
@@ -47,7 +47,7 @@ public class MaxMinZoomActivity extends AppCompatActivity implements OnMapReadyC
@Override
public void onMapReady(@NonNull final MapboxMap map) {
mapboxMap = map;
mapboxMap.setStyle(Style.MAPBOX_STREETS);
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
mapboxMap.setMinZoomPreference(3);
mapboxMap.setMaxZoomPreference(5);
mapboxMap.addOnMapClickListener(clickListener);

View File

@@ -63,7 +63,7 @@ public class ScrollByActivity extends AppCompatActivity implements OnMapReadyCal
@Override
public void onMapReady(@NonNull MapboxMap map) {
mapboxMap = map;
mapboxMap.setStyle(Style.DARK);
mapboxMap.setStyle(Style.getPredefinedStyle("Pastel"));
UiSettings uiSettings = mapboxMap.getUiSettings();
uiSettings.setLogoEnabled(false);

View File

@@ -41,7 +41,7 @@ public class CustomLayerActivity extends AppCompatActivity {
mapView.getMapAsync(map -> {
mapboxMap = map;
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.91448, -243.60947), 10));
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> initFab());
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"), style -> initFab());
});
}

View File

@@ -30,7 +30,7 @@ public class DeviceIndependentTestActivity extends AppCompatActivity implements
@Override
public void onMapReady(@NonNull MapboxMap map) {
mapboxMap = map;
mapboxMap.setStyle(Style.MAPBOX_STREETS);
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
}
public MapboxMap getMapboxMap() {

View File

@@ -26,7 +26,7 @@ class PixelTestActivity : AppCompatActivity(), OnMapReadyCallback {
override fun onMapReady(map: MapboxMap) {
mapboxMap = map
mapboxMap.setStyle(Style.MAPBOX_STREETS)
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"))
}
public override fun onResume() {

View File

@@ -43,7 +43,7 @@ public class QueryRenderedFeaturesBoxCountActivity extends AppCompatActivity {
mapView.getMapAsync(mapboxMap -> {
QueryRenderedFeaturesBoxCountActivity.this.mapboxMap = mapboxMap;
mapboxMap.setStyle(new Style.Builder().fromUri(Style.MAPBOX_STREETS));
mapboxMap.setStyle(new Style.Builder().fromUri(Style.getPredefinedStyle("Streets")));
selectionBox.setOnClickListener(view -> {
// Query

View File

@@ -76,7 +76,7 @@ public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity
});
mapboxMap.setStyle(new Style.Builder()
.fromUri(Style.MAPBOX_STREETS)
.fromUri(Style.getPredefinedStyle("Streets"))
.withSource(source)
.withLayer(layer)
);

View File

@@ -71,7 +71,7 @@ public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> {
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> {
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"), style -> {
QueryRenderedFeaturesPropertiesActivity.this.mapboxMap = mapboxMap;
// Add custom window adapter

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