From dfdbaf5493130a19da9978f40d2ff535fff2c0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Wed, 13 Nov 2019 14:14:21 +0100 Subject: [PATCH] bump gl-native submodule and bring platform changes --- CHANGELOG.md | 11 ++++ .../mapboxsdk/offline/OfflineManager.java | 45 ++++++++++++++++ .../mapboxsdk/offline/OfflineRegion.java | 52 ++++++++++++++++++- .../style/expressions/Expression.java | 50 ++++++++++++++++-- .../mapboxsdk/testapp/offline/CacheTest.kt | 16 ++++++ .../mapboxsdk/testapp/style/layer.junit.ejs | 4 ++ scripts/generate-style-code.js | 8 +++ vendor/mapbox-gl-native | 2 +- 8 files changed, 182 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfa1add83..43e35db36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. +## master +### Features +- Added support for [image expression](https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-image) in core library. Runtime APIs for image expression will be implemented separately. [#15877](https://github.com/mapbox/mapbox-gl-native/pull/15877) +- Introduce `OfflineManager#packDatabase` and `OfflineRegion#deleteAndSkipPackDatabase` API in order to decouple offline storage vacuum and delete region operations and thus to gain performance benefits e.g. when several regions should be deleted in a row [#15899](https://github.com/mapbox/mapbox-gl-native/pull/15899) + +### Bugs +- Fixed Geo JSON source flickering on style transition [#15907](https://github.com/mapbox/mapbox-gl-native/pull/15907) + +### Performance improvements +- Convert GeoJSON features to tiles for the loaded source description in a background thread and thus unblock the UI thread [#15885](https://github.com/mapbox/mapbox-gl-native/pull/15885) + ## 8.5.0-alpha.4 - October 24, 2019 [Changes](https://github.com/mapbox/mapbox-gl-native-android/compare/android-v8.5.0-alpha.3...android-v8.5.0-alpha.4) since [Mapbox Maps SDK for Android v8.5.0-alpha.3](https://github.com/mapbox/mapbox-gl-native-android/releases/tag/android-v8.5.0-alpha.3): ### Bug fixes diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java index faed46662..3975e0134 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java @@ -8,6 +8,7 @@ import android.support.annotation.Keep; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.UiThread; + import com.mapbox.mapboxsdk.LibraryLoader; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.R; @@ -306,6 +307,47 @@ public class OfflineManager { }); } + /** + * Packs the existing database file into a minimal amount of disk space. + *

+ * When the operation is complete or encounters an error, the given callback will be + * executed on the database thread; it is the responsibility of the SDK bindings + * to re-execute a user-provided callback on the main thread. + *

+ * + * @param callback the callback to be invoked when the database was reset or when the operation erred. + */ + public void packDatabase(@Nullable final FileSourceCallback callback) { + fileSource.activate(); + nativePackDatabase(new FileSourceCallback() { + @Override + public void onSuccess() { + handler.post(new Runnable() { + @Override + public void run() { + fileSource.deactivate(); + if (callback != null) { + callback.onSuccess(); + } + } + }); + } + + @Override + public void onError(@NonNull final String message) { + handler.post(new Runnable() { + @Override + public void run() { + fileSource.deactivate(); + if (callback != null) { + callback.onError(message); + } + } + }); + } + }); + } + /** * Forces re-validation of the ambient cache. *

@@ -648,6 +690,9 @@ public class OfflineManager { @Keep private native void nativeResetDatabase(@Nullable FileSourceCallback callback); + @Keep + private native void nativePackDatabase(@Nullable FileSourceCallback callback); + @Keep private native void nativeInvalidateAmbientCache(@Nullable FileSourceCallback callback); diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java index f13128da6..b188d60a9 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java @@ -401,7 +401,55 @@ public class OfflineRegion { if (!isDeleted) { isDeleted = true; fileSource.activate(); - deleteOfflineRegion(new OfflineRegionDeleteCallback() { + deleteOfflineRegion(true /*pack*/, new OfflineRegionDeleteCallback() { + @Override + public void onDelete() { + handler.post(new Runnable() { + @Override + public void run() { + fileSource.deactivate(); + callback.onDelete(); + OfflineRegion.this.finalize(); + } + }); + } + + @Override + public void onError(final String error) { + handler.post(new Runnable() { + @Override + public void run() { + isDeleted = false; + fileSource.deactivate(); + callback.onError(error); + } + }); + } + }); + } + } + + /** + * Same as {@link OfflineRegion#delete} but skipping database file packing for performance reasons. + *

+ * Database file packing can be done later with {@link OfflineManager#packDatabase}. + * This method is a useful optimization e.g. when several regions should be deleted in a row. + *

+ *

+ * When the operation is complete or encounters an error, the given callback will be + * executed on the main thread. + *

+ *

+ * After you call this method, you may not call any additional methods on this object. + *

+ * + * @param callback the callback to be invoked + */ + public void deleteAndSkipPackDatabase(@NonNull final OfflineRegionDeleteCallback callback) { + if (!isDeleted) { + isDeleted = true; + fileSource.activate(); + deleteOfflineRegion(false /*pack*/, new OfflineRegionDeleteCallback() { @Override public void onDelete() { handler.post(new Runnable() { @@ -521,7 +569,7 @@ public class OfflineRegion { private native void getOfflineRegionStatus(OfflineRegionStatusCallback callback); @Keep - private native void deleteOfflineRegion(OfflineRegionDeleteCallback callback); + private native void deleteOfflineRegion(boolean pack, OfflineRegionDeleteCallback callback); @Keep private native void updateOfflineRegionMetadata(byte[] metadata, OfflineRegionUpdateMetadataCallback callback); diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java index 34b330880..0003006b7 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java @@ -5,6 +5,7 @@ import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.Size; + import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -3150,7 +3151,7 @@ public class Expression { * If set, the min-fraction-digits and max-fraction-digits arguments specify the minimum and maximum number * of fractional digits to include. * - * @param number number expression + * @param number number expression * @param options number formatting options * @return expression */ @@ -3169,7 +3170,7 @@ public class Expression { * If set, the min-fraction-digits and max-fraction-digits arguments specify the minimum and maximum number * of fractional digits to include. * - * @param number number expression + * @param number number expression * @param options number formatting options * @return expression */ @@ -3409,6 +3410,49 @@ public class Expression { return new FormatEntry(literal(text), null); } + /** + * Returns image expression for use in '*-pattern' and 'icon-image' layer properties. Compared to + * string literals that can be used to represent an image, image expression allows to determine an + * image's availability at runtime, thus, can be used in conditional coalesce operator. + * + *

+ * Example usage: + *

+ *
+   * {@code
+   * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+   * symbolLayer.setProperties(
+   *     iconImage(image(get("key-to-feature")))
+   * );
+   * }
+   * 
+ * + *

+ * Example usage with coalesce operator: + *

+ *
+   * {@code
+   * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+   * symbolLayer.setProperties(
+   *     iconImage(
+   *         coalesce(
+   *             image(literal("maki-11")),
+   *             image(literal("bicycle-15")),
+   *             image(literal("default-icon"))
+   *         )
+   *     )
+   * );
+   * }
+   * 
+ * + * @param input expression input + * @return expression + * @see Image expression + */ + public static Expression image(@NonNull Expression input) { + return new Expression("image", input); + } + /** * Asserts that the input value is an object. If it is not, the expression is an error * The asserted input value is returned as result. @@ -4430,7 +4474,7 @@ public class Expression { /** * Create an option option entry that is encapsulated as a json object member for an expression. * - * @param type json object member name + * @param type json object member name * @param value json object member value */ Option(@NonNull String type, @NonNull Expression value) { diff --git a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt index a3214c9f1..da4cfbaf0 100644 --- a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt +++ b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt @@ -85,4 +85,20 @@ class CacheTest { } countDownLatch.await() } + + @Test + fun testSetPackDatabase() { + rule.activity.runOnUiThread { + OfflineManager.getInstance(context).packDatabase(object : OfflineManager.FileSourceCallback { + override fun onSuccess() { + countDownLatch.countDown() + } + + override fun onError(message: String) { + Assert.assertNull("onError should not be called", message) + } + }) + } + countDownLatch.await() + } } \ No newline at end of file diff --git a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs index 1104cbed9..141114c1a 100644 --- a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs +++ b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs @@ -151,6 +151,8 @@ public class <%- camelize(type) %>LayerTest extends BaseLayerTest { layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>("{token}")); <% if (property.type === 'formatted') { -%> assertEquals(layer.get<%- camelize(property.name) %>().getExpression(), <%- defaultExpressionJava(property) %>(Expression.formatEntry(Expression.toString(Expression.get("token"))))); +<% } else if (property.type === 'resolvedImage') {-%> + assertEquals(layer.get<%- camelize(property.name) %>().getExpression(), <%- defaultExpressionJava(property) %>(Expression.toString(Expression.get("token")))); <% } else {-%> assertEquals(layer.get<%- camelize(property.name) %>().getExpression(), Expression.toString(Expression.get("token"))); <% } -%> @@ -169,6 +171,8 @@ public class <%- camelize(type) %>LayerTest extends BaseLayerTest { // Set and Get <% if (property.type === 'formatted') { -%> Expression expression = <%- defaultExpressionJava(property) %>(Expression.formatEntry(Expression.get("undefined"), FormatOption.formatFontScale(2.0), FormatOption.formatTextFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}))); +<% } else if (property.type === 'resolvedImage') { -%> + Expression expression = <%- defaultExpressionJava(property) %>(string(Expression.get("undefined"))); <% } else { -%> Expression expression = <%- defaultExpressionJava(property) %>(Expression.get("undefined")); <% } -%> diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js index 652b8a98a..ea68a059d 100755 --- a/scripts/generate-style-code.js +++ b/scripts/generate-style-code.js @@ -72,6 +72,7 @@ global.propertyType = function propertyType(property) { case 'formatted': return 'Formatted'; case 'string': + case 'resolvedImage': return 'String'; case 'enum': return 'String'; @@ -93,6 +94,7 @@ global.propertyJavaType = function propertyType(property) { case 'formatted': return 'Formatted'; case 'string': + case 'resolvedImage': return 'String'; case 'enum': return 'String'; @@ -141,6 +143,7 @@ global.propertyNativeType = function (property) { return 'float'; case 'formatted': case 'string': + case 'resolvedImage': // TODO: replace once we implement image expressions return 'std::string'; case 'enum': if(property['light-property']){ @@ -176,7 +179,10 @@ global.defaultExpressionJava = function(property) { return 'number'; case 'formatted': return 'format'; + case 'resolvedImage': + return "image"; case 'string': + case 'image': return "string"; case 'enum': return "string"; @@ -203,6 +209,7 @@ global.defaultValueJava = function(property) { case 'formatted': return 'new Formatted(new FormattedSection("default"))' case 'string': + case 'resolvedImage': return '"' + property['default'] + '"'; case 'enum': return snakeCaseUpper(property.name) + "_" + snakeCaseUpper(Object.keys(property.values)[0]); @@ -335,6 +342,7 @@ global.evaluatedType = function (property) { return 'float'; case 'formatted': case 'string': + case 'image': return 'std::string'; case 'enum': return (isLightProperty(property) ? 'Light' : '') + `${camelize(property.name)}Type`; diff --git a/vendor/mapbox-gl-native b/vendor/mapbox-gl-native index ab7cd57de..4c1d03c25 160000 --- a/vendor/mapbox-gl-native +++ b/vendor/mapbox-gl-native @@ -1 +1 @@ -Subproject commit ab7cd57de037bc6e71e327cffeb421e08e3b2480 +Subproject commit 4c1d03c257754ecc1555f3e31b3c6ccf45c4bf7b