From f5610310104846adfc49180784e60f6d0adcab45 Mon Sep 17 00:00:00 2001 From: Artak Kalantarian Date: Sat, 14 Jan 2023 06:35:51 -0800 Subject: [PATCH] More namespaces updated to Kotlin (#692) --- .../java/com/mapbox/mapboxsdk/Mapbox.java | 4 +- .../sources/CannotAddSourceException.java | 15 - .../style/sources/CannotAddSourceException.kt | 9 + .../style/sources/CustomGeometrySource.java | 379 ------------- .../style/sources/CustomGeometrySource.kt | 344 ++++++++++++ .../sources/CustomGeometrySourceOptions.java | 85 --- .../sources/CustomGeometrySourceOptions.kt | 74 +++ .../style/sources/GeoJsonOptions.java | 140 ----- .../mapboxsdk/style/sources/GeoJsonOptions.kt | 123 +++++ .../style/sources/GeoJsonSource.java | 519 ------------------ .../mapboxsdk/style/sources/GeoJsonSource.kt | 498 +++++++++++++++++ .../style/sources/GeometryTileProvider.java | 22 - .../style/sources/GeometryTileProvider.kt | 20 + .../mapboxsdk/style/sources/ImageSource.java | 273 --------- .../mapboxsdk/style/sources/ImageSource.kt | 257 +++++++++ .../{package-info.java => PackageInfo.kt} | 2 +- .../style/sources/RasterDemSource.java | 185 ------- .../style/sources/RasterDemSource.kt | 176 ++++++ .../mapboxsdk/style/sources/RasterSource.java | 182 ------ .../mapboxsdk/style/sources/RasterSource.kt | 173 ++++++ .../mapboxsdk/style/sources/Source.java | 12 +- .../mapboxsdk/style/sources/TileSet.java | 341 ------------ .../mapbox/mapboxsdk/style/sources/TileSet.kt | 259 +++++++++ .../style/sources/UnknownSource.java | 27 - .../mapboxsdk/style/sources/UnknownSource.kt | 21 + .../mapboxsdk/style/sources/VectorSource.java | 172 ------ .../mapboxsdk/style/sources/VectorSource.kt | 151 +++++ .../mapboxsdk/style/types/Formatted.java | 69 --- .../mapbox/mapboxsdk/style/types/Formatted.kt | 55 ++ .../{package-info.java => PackageInfo.kt} | 2 +- .../activity/style/DataDrivenStyleActivity.kt | 2 +- .../activity/style/GridSourceActivity.kt | 21 +- .../activity/style/RealTimeGeoJsonActivity.kt | 7 +- 33 files changed, 2181 insertions(+), 2438 deletions(-) delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.kt rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/{package-info.java => PackageInfo.kt} (61%) delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.kt rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/{package-info.java => PackageInfo.kt} (67%) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java index 200a1dc69..ef1526c5b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java @@ -93,7 +93,7 @@ public final class Mapbox { ThreadUtils.init(context); ThreadUtils.checkThread(TAG); if (INSTANCE == null) { - Timber.plant(new Timber.DebugTree()); + Timber.plant(); Context appContext = context.getApplicationContext(); FileSource.initializeFileDirsPaths(appContext); INSTANCE = new Mapbox(appContext, apiKey); @@ -281,4 +281,4 @@ public final class Mapbox { private static AssetManager getAssetManager() { return getApplicationContext().getResources().getAssets(); } -} \ No newline at end of file +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java deleted file mode 100644 index d6be7a7c8..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.Keep; - -/** - * Thrown when adding a source to a map twice - */ -@Keep -public class CannotAddSourceException extends RuntimeException { - - public CannotAddSourceException(String message) { - super(message); - } - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.kt new file mode 100644 index 000000000..7d677ca96 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.kt @@ -0,0 +1,9 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.Keep + +/** + * Thrown when adding a source to a map twice + */ +@Keep +class CannotAddSourceException(message: String?) : RuntimeException(message) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java deleted file mode 100644 index 1bd53fd04..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java +++ /dev/null @@ -1,379 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; -import androidx.annotation.WorkerThread; - -import com.mapbox.geojson.Feature; -import com.mapbox.geojson.FeatureCollection; -import com.mapbox.mapboxsdk.geometry.LatLngBounds; -import com.mapbox.mapboxsdk.style.expressions.Expression; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Custom Vector Source, allows using FeatureCollections. - *

- * CustomGeometrySource uses a coalescing model for frequent data updates targeting the same tile id, - * which means, that the in-progress request as well as the last scheduled request are guaranteed to finish. - * Any requests scheduled meanwhile can be canceled. - */ -public class CustomGeometrySource extends Source { - public static final String THREAD_PREFIX = "CustomGeom"; - public static final int THREAD_POOL_LIMIT = 4; - private static final AtomicInteger poolCount = new AtomicInteger(); - private final Lock executorLock = new ReentrantLock(); - private ThreadPoolExecutor executor; - private GeometryTileProvider provider; - private final Map awaitingTasksMap = new HashMap<>(); - - /** - * A map containing in-progress requests targeting distinct tiles. - * A request is considered in-progress when it's started by the ThreadPoolExecutor. - * A request is marked as done when the data is passed from the JNI layer to the core, after the features conversion. - */ - private final Map inProgressTasksMap = new HashMap<>(); - - /** - * Create a CustomGeometrySource - * - * @param id The source id. - * @param provider The tile provider that returns geometry data for this source. - */ - @UiThread - public CustomGeometrySource(String id, GeometryTileProvider provider) { - this(id, new CustomGeometrySourceOptions(), provider); - } - - /** - * Create a CustomGeometrySource with non-default {@link CustomGeometrySourceOptions}. - * - * @param id The source id. - * @param options CustomGeometrySourceOptions. - * @param provider The tile provider that returns geometry data for this source. - */ - @UiThread - public CustomGeometrySource(String id, CustomGeometrySourceOptions options, - GeometryTileProvider provider) { - super(); - this.provider = provider; - initialize(id, options); - } - - /** - * Invalidate previously provided features within a given bounds at all zoom levels. - * Invoking this method will result in new requests to `GeometryTileProvider` for regions - * that contain, include, or intersect with the provided bounds. - * - * @param bounds The region in which features should be invalidated at all zoom levels - */ - public void invalidateRegion(LatLngBounds bounds) { - nativeInvalidateBounds(bounds); - } - - /** - * Invalidate the geometry contents of a specific tile. Invoking this method will result - * in new requests to `GeometryTileProvider` for visible tiles. - * - * @param zoomLevel Tile zoom level. - * @param x Tile X coordinate. - * @param y Tile Y coordinate. - */ - public void invalidateTile(int zoomLevel, int x, int y) { - nativeInvalidateTile(zoomLevel, x, y); - } - - /** - * Set or update geometry contents of a specific tile. Use this method to update tiles - * for which `GeometryTileProvider` was previously invoked. This method can be called from - * background threads. - * - * @param zoomLevel Tile zoom level. - * @param x Tile X coordinate. - * @param y Tile Y coordinate. - * @param data Feature collection for the tile. - */ - public void setTileData(int zoomLevel, int x, int y, FeatureCollection data) { - nativeSetTileData(zoomLevel, x, y, data); - } - - /** - * Queries the source for features. - * - * @param filter an optional filter expression to filter the returned Features - * @return the features - */ - @NonNull - public List querySourceFeatures(@Nullable Expression filter) { - checkThread(); - Feature[] features = querySourceFeatures(filter != null ? filter.toArray() : null); - return features != null ? Arrays.asList(features) : new ArrayList(); - } - - @Keep - protected native void initialize(String sourceId, Object options); - - @NonNull - @Keep - private native Feature[] querySourceFeatures(Object[] filter); - - @Keep - private native void nativeSetTileData(int z, int x, int y, FeatureCollection data); - - @Keep - private native void nativeInvalidateTile(int z, int x, int y); - - @Keep - private native void nativeInvalidateBounds(LatLngBounds bounds); - - @Override - @Keep - protected native void finalize() throws Throwable; - - private void setTileData(TileID tileId, FeatureCollection data) { - nativeSetTileData(tileId.z, tileId.x, tileId.y, data); - } - - /** - * Tile data request can come from a number of different threads. - * To remove race condition for requests targeting the same tile id we are first checking if there is a request - * already enqueued, if yes, we are replacing it. - * Otherwise, we are checking if there is an in-progress request, if yes, - * we are creating or replacing an awaiting request. - * If none of the above, we are enqueueing the request. - */ - @WorkerThread - @Keep - private void fetchTile(int z, int x, int y) { - AtomicBoolean cancelFlag = new AtomicBoolean(false); - TileID tileID = new TileID(z, x, y); - GeometryTileRequest request = - new GeometryTileRequest(tileID, provider, awaitingTasksMap, inProgressTasksMap, this, cancelFlag); - - synchronized (awaitingTasksMap) { - synchronized (inProgressTasksMap) { - if (executor.getQueue().contains(request)) { - executor.remove(request); - executeRequest(request); - } else if (inProgressTasksMap.containsKey(tileID)) { - awaitingTasksMap.put(tileID, request); - } else { - executeRequest(request); - } - } - } - } - - private void executeRequest(@NonNull GeometryTileRequest request) { - executorLock.lock(); - try { - if (executor != null && !executor.isShutdown()) { - executor.execute(request); - } - } finally { - executorLock.unlock(); - } - } - - /** - * We want to cancel only the oldest request, therefore, we are first checking if it's in progress, - * if not or if the currently in progress request has already been canceled, - * we are searching for any request in the executor's queue. - * Otherwise, we are removing an awaiting request targeting this tile id. - *

- * {@link GeometryTileRequest#equals(Object)} is overridden to cover only the tile id, - * therefore, we can use an empty request to search the executor's queue. - */ - @WorkerThread - @Keep - private void cancelTile(int z, int x, int y) { - TileID tileID = new TileID(z, x, y); - - synchronized (awaitingTasksMap) { - synchronized (inProgressTasksMap) { - AtomicBoolean cancelFlag = inProgressTasksMap.get(tileID); - // check if there is an in progress task - if (!(cancelFlag != null && cancelFlag.compareAndSet(false, true))) { - // if there is no tasks in progress or the in progress task was already cancelled, check the executor's queue - GeometryTileRequest emptyRequest = - new GeometryTileRequest(tileID, null, null, null, null, null); - if (!executor.getQueue().remove(emptyRequest)) { - // if there was no tasks in queue, remove from the awaiting map - awaitingTasksMap.remove(tileID); - } - } - } - } - } - - @Keep - private void startThreads() { - executorLock.lock(); - try { - if (executor != null && !executor.isShutdown()) { - executor.shutdownNow(); - } - - executor = new ThreadPoolExecutor(THREAD_POOL_LIMIT, THREAD_POOL_LIMIT, - 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), - new ThreadFactory() { - final AtomicInteger threadCount = new AtomicInteger(); - final int poolId = poolCount.getAndIncrement(); - - @NonNull - @Override - public Thread newThread(@NonNull Runnable runnable) { - return new Thread( - runnable, - String.format(Locale.US, "%s-%d-%d", THREAD_PREFIX, poolId, threadCount.getAndIncrement())); - } - }); - } finally { - executorLock.unlock(); - } - } - - @Keep - private void releaseThreads() { - executorLock.lock(); - try { - executor.shutdownNow(); - } finally { - executorLock.unlock(); - } - } - - @Keep - private boolean isCancelled(int z, int x, int y) { - return inProgressTasksMap.get(new TileID(z, x, y)).get(); - } - - static class TileID { - public int z; - public int x; - public int y; - - TileID(int _z, int _x, int _y) { - z = _z; - x = _x; - y = _y; - } - - public int hashCode() { - return Arrays.hashCode(new int[] {z, x, y}); - } - - public boolean equals(@Nullable Object object) { - if (object == this) { - return true; - } - - if (object == null || getClass() != object.getClass()) { - return false; - } - - if (object instanceof TileID) { - TileID other = (TileID) object; - return this.z == other.z && this.x == other.x && this.y == other.y; - } - return false; - } - } - - static class GeometryTileRequest implements Runnable { - private final TileID id; - private final GeometryTileProvider provider; - private final Map awaiting; - private final Map inProgress; - @NonNull - private final WeakReference sourceRef; - private final AtomicBoolean cancelled; - - GeometryTileRequest(TileID _id, GeometryTileProvider p, - Map awaiting, - Map m, - CustomGeometrySource _source, AtomicBoolean _cancelled) { - id = _id; - provider = p; - this.awaiting = awaiting; - inProgress = m; - sourceRef = new WeakReference<>(_source); - cancelled = _cancelled; - } - - public void run() { - synchronized (awaiting) { - synchronized (inProgress) { - if (inProgress.containsKey(id)) { - // request targeting this tile id is already being processed, - // scenario that should occur only if the tile is being requested when - // another request is switching threads to execute - if (!awaiting.containsKey(id)) { - awaiting.put(id, this); - } - return; - } else { - inProgress.put(id, cancelled); - } - } - } - - if (!isCancelled()) { - FeatureCollection data = provider.getFeaturesForBounds(LatLngBounds.from(id.z, id.x, id.y), id.z); - CustomGeometrySource source = sourceRef.get(); - if (!isCancelled() && source != null && data != null) { - source.setTileData(id, data); - } - } - - synchronized (awaiting) { - synchronized (inProgress) { - inProgress.remove(id); - - // executing the next request targeting the same tile - if (awaiting.containsKey(id)) { - GeometryTileRequest queuedRequest = awaiting.get(id); - CustomGeometrySource source = sourceRef.get(); - if (source != null && queuedRequest != null) { - source.executor.execute(queuedRequest); - } - - awaiting.remove(id); - } - } - } - } - - private Boolean isCancelled() { - return cancelled.get(); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - GeometryTileRequest request = (GeometryTileRequest) o; - return id.equals(request.id); - } - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.kt new file mode 100644 index 000000000..e5f2cbecb --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.kt @@ -0,0 +1,344 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.Keep +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread +import com.mapbox.geojson.Feature +import com.mapbox.geojson.FeatureCollection +import com.mapbox.mapboxsdk.geometry.LatLngBounds +import com.mapbox.mapboxsdk.geometry.LatLngBounds.Companion.from +import com.mapbox.mapboxsdk.style.expressions.Expression +import java.lang.ref.WeakReference +import java.util.Arrays +import java.util.Locale +import java.util.concurrent.LinkedBlockingQueue +import java.util.concurrent.ThreadFactory +import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.locks.Lock +import java.util.concurrent.locks.ReentrantLock +import kotlin.collections.ArrayList +import kotlin.collections.HashMap + +/** + * Custom Vector Source, allows using FeatureCollections. + * + * + * CustomGeometrySource uses a coalescing model for frequent data updates targeting the same tile id, + * which means, that the in-progress request as well as the last scheduled request are guaranteed to finish. + * Any requests scheduled meanwhile can be canceled. + */ +class CustomGeometrySource @UiThread constructor(id: String?, options: CustomGeometrySourceOptions?, private val provider: GeometryTileProvider?) : Source() { + private val executorLock: Lock = ReentrantLock() + private var executor: ThreadPoolExecutor? = null + private val awaitingTasksMap: MutableMap = HashMap() + + /** + * A map containing in-progress requests targeting distinct tiles. + * A request is considered in-progress when it's started by the ThreadPoolExecutor. + * A request is marked as done when the data is passed from the JNI layer to the core, after the features conversion. + */ + private val inProgressTasksMap: MutableMap = HashMap() + + /** + * Create a CustomGeometrySource + * + * @param id The source id. + * @param provider The tile provider that returns geometry data for this source. + */ + @UiThread + constructor(id: String?, provider: GeometryTileProvider?) : this(id, CustomGeometrySourceOptions(), provider) { + } + + /** + * Create a CustomGeometrySource with non-default [CustomGeometrySourceOptions]. + * + * @param id The source id. + * @param options CustomGeometrySourceOptions. + */ + init { + initialize(id, options) + } + + /** + * Invalidate previously provided features within a given bounds at all zoom levels. + * Invoking this method will result in new requests to `GeometryTileProvider` for regions + * that contain, include, or intersect with the provided bounds. + * + * @param bounds The region in which features should be invalidated at all zoom levels + */ + fun invalidateRegion(bounds: LatLngBounds) { + nativeInvalidateBounds(bounds) + } + + /** + * Invalidate the geometry contents of a specific tile. Invoking this method will result + * in new requests to `GeometryTileProvider` for visible tiles. + * + * @param zoomLevel Tile zoom level. + * @param x Tile X coordinate. + * @param y Tile Y coordinate. + */ + fun invalidateTile(zoomLevel: Int, x: Int, y: Int) { + nativeInvalidateTile(zoomLevel, x, y) + } + + /** + * Set or update geometry contents of a specific tile. Use this method to update tiles + * for which `GeometryTileProvider` was previously invoked. This method can be called from + * background threads. + * + * @param zoomLevel Tile zoom level. + * @param x Tile X coordinate. + * @param y Tile Y coordinate. + * @param data Feature collection for the tile. + */ + fun setTileData(zoomLevel: Int, x: Int, y: Int, data: FeatureCollection) { + nativeSetTileData(zoomLevel, x, y, data) + } + + /** + * Queries the source for features. + * + * @param filter an optional filter expression to filter the returned Features + * @return the features + */ + fun querySourceFeatures(filter: Expression?): List { + checkThread() + val features = querySourceFeatures(filter?.toArray()) + return if (features != null) Arrays.asList(*features) else ArrayList() + } + + @Keep + private external fun initialize(sourceId: String?, options: Any?) + + @Keep + private external fun querySourceFeatures(filter: Array?): Array + + @Keep + private external fun nativeSetTileData(z: Int, x: Int, y: Int, data: FeatureCollection) + + @Keep + private external fun nativeInvalidateTile(z: Int, x: Int, y: Int) + + @Keep + private external fun nativeInvalidateBounds(bounds: LatLngBounds) + + @Keep + @Throws(Throwable::class) + protected external fun finalize() + + private fun setTileData(tileId: TileID, data: FeatureCollection) { + nativeSetTileData(tileId.z, tileId.x, tileId.y, data) + } + + /** + * Tile data request can come from a number of different threads. + * To remove race condition for requests targeting the same tile id we are first checking if there is a request + * already enqueued, if yes, we are replacing it. + * Otherwise, we are checking if there is an in-progress request, if yes, + * we are creating or replacing an awaiting request. + * If none of the above, we are enqueueing the request. + */ + @WorkerThread + @Keep + private fun fetchTile(z: Int, x: Int, y: Int) { + val cancelFlag = AtomicBoolean(false) + val tileID = TileID(z, x, y) + val request = GeometryTileRequest(tileID, provider, awaitingTasksMap, inProgressTasksMap, this, cancelFlag) + synchronized(awaitingTasksMap) { + synchronized(inProgressTasksMap) { + if (executor!!.queue.contains(request)) { + executor!!.remove(request) + executeRequest(request) + } else if (inProgressTasksMap.containsKey(tileID)) { + awaitingTasksMap.put(tileID, request) + } else { + executeRequest(request) + } + } + } + } + + private fun executeRequest(request: GeometryTileRequest) { + executorLock.lock() + try { + if (executor != null && !executor!!.isShutdown) { + executor!!.execute(request) + } + } finally { + executorLock.unlock() + } + } + + /** + * We want to cancel only the oldest request, therefore, we are first checking if it's in progress, + * if not or if the currently in progress request has already been canceled, + * we are searching for any request in the executor's queue. + * Otherwise, we are removing an awaiting request targeting this tile id. + * + * + * [GeometryTileRequest.equals] is overridden to cover only the tile id, + * therefore, we can use an empty request to search the executor's queue. + */ + @WorkerThread + @Keep + private fun cancelTile(z: Int, x: Int, y: Int) { + val tileID = TileID(z, x, y) + synchronized(awaitingTasksMap) { + synchronized(inProgressTasksMap) { + val cancelFlag = inProgressTasksMap[tileID] + // check if there is an in progress task + if (!(cancelFlag != null && cancelFlag.compareAndSet(false, true))) { + // if there is no tasks in progress or the in progress task was already cancelled, check the executor's queue + val emptyRequest = GeometryTileRequest(tileID, null, null, null, null, null) + if (!executor!!.queue.remove(emptyRequest)) { + // if there was no tasks in queue, remove from the awaiting map + awaitingTasksMap.remove(tileID) + } + } + } + } + } + + @Keep + private fun startThreads() { + executorLock.lock() + executor = try { + if (executor != null && !executor!!.isShutdown) { + executor!!.shutdownNow() + } + ThreadPoolExecutor( + THREAD_POOL_LIMIT, + THREAD_POOL_LIMIT, + 0L, + TimeUnit.MILLISECONDS, + LinkedBlockingQueue(), + object : ThreadFactory { + val threadCount = AtomicInteger() + val poolId = poolCount.getAndIncrement() + override fun newThread(runnable: Runnable): Thread { + return Thread(runnable, String.format(Locale.US, "%s-%d-%d", THREAD_PREFIX, poolId, threadCount.getAndIncrement())) + } + } + ) + } finally { + executorLock.unlock() + } + } + + @Keep + private fun releaseThreads() { + executorLock.lock() + try { + executor!!.shutdownNow() + } finally { + executorLock.unlock() + } + } + + @Keep + private fun isCancelled(z: Int, x: Int, y: Int): Boolean { + return inProgressTasksMap[TileID(z, x, y)]!!.get() + } + + internal class TileID(var z: Int, var x: Int, var y: Int) { + override fun hashCode(): Int { + return Arrays.hashCode(intArrayOf(z, x, y)) + } + + override fun equals(`object`: Any?): Boolean { + if (`object` === this) { + return true + } + if (`object` == null || javaClass != `object`.javaClass) { + return false + } + if (`object` is TileID) { + val other = `object` + return z == other.z && x == other.x && y == other.y + } + return false + } + } + + internal class GeometryTileRequest( + private val id: TileID, + private val provider: GeometryTileProvider?, + private val awaiting: MutableMap?, + private val inProgress: MutableMap?, + _source: CustomGeometrySource?, + _cancelled: AtomicBoolean? + ) : Runnable { + private val sourceRef: WeakReference + private val cancelled: AtomicBoolean? + + init { + sourceRef = WeakReference(_source) + cancelled = _cancelled + } + + override fun run() { + synchronized(awaiting!!) { + synchronized(inProgress!!) { + if (inProgress.containsKey(id)) { + // request targeting this tile id is already being processed, + // scenario that should occur only if the tile is being requested when + // another request is switching threads to execute + if (!awaiting.containsKey(id)) { + awaiting[id] = this + } + return + } else { + inProgress.put(id, cancelled) + } + } + } + if (!isCancelled()) { + val data = provider!!.getFeaturesForBounds(from(id.z, id.x, id.y), id.z) + val source = sourceRef.get() + if (!isCancelled() && source != null && data != null) { + source.setTileData(id, data) + } + } + synchronized(awaiting) { + synchronized(inProgress!!) { + inProgress.remove(id) + + // executing the next request targeting the same tile + if (awaiting.containsKey(id)) { + val queuedRequest = awaiting[id] + val source = sourceRef.get() + if (source != null && queuedRequest != null) { + source.executor!!.execute(queuedRequest) + } + awaiting.remove(id) + } + } + } + } + + private fun isCancelled(): Boolean { + return cancelled!!.get() + } + + override fun equals(o: Any?): Boolean { + if (this === o) { + return true + } + if (o == null || javaClass != o.javaClass) { + return false + } + val request = o as GeometryTileRequest + return id == request.id + } + } + + companion object { + const val THREAD_PREFIX = "CustomGeom" + const val THREAD_POOL_LIMIT = 4 + private val poolCount = AtomicInteger() + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.java deleted file mode 100644 index dd5998b04..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.NonNull; - -import java.util.HashMap; - -/** - * Builder class for composing CustomGeometrySource objects. - */ -public class CustomGeometrySourceOptions extends HashMap { - - /** - * If the data includes wrapped coordinates, setting this to true unwraps the coordinates. - * - * @param wrap defaults to false - * @return the current instance for chaining - */ - @NonNull - public CustomGeometrySourceOptions withWrap(boolean wrap) { - this.put("wrap", wrap); - return this; - } - - /** - * If the data includes geometry outside the tile boundaries, setting this to true clips the geometry - * to the tile boundaries. - * - * @param clip defaults to false - * @return the current instance for chaining - */ - @NonNull - public CustomGeometrySourceOptions withClip(boolean clip) { - this.put("clip", clip); - return this; - } - - /** - * Minimum zoom level at which to create vector tiles (lower means more field of view detail at low zoom levels). - * - * @param minZoom the minimum zoom - Defaults to 0. - * @return the current instance for chaining - */ - @NonNull - public CustomGeometrySourceOptions withMinZoom(int minZoom) { - this.put("minzoom", minZoom); - return this; - } - - /** - * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels). - * - * @param maxZoom the maximum zoom - Defaults to 25.5 - * @return the current instance for chaining - */ - @NonNull - public CustomGeometrySourceOptions withMaxZoom(int maxZoom) { - this.put("maxzoom", maxZoom); - return this; - } - - /** - * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile - * edges but slower performance). - * - * @param buffer the buffer size - Defaults to 128. - * @return the current instance for chaining - */ - @NonNull - public CustomGeometrySourceOptions withBuffer(int buffer) { - this.put("buffer", buffer); - return this; - } - - /** - * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance). - * - * @param tolerance the tolerance - Defaults to 0.375 - * @return the current instance for chaining - */ - @NonNull - public CustomGeometrySourceOptions withTolerance(float tolerance) { - this.put("tolerance", tolerance); - return this; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.kt new file mode 100644 index 000000000..494c2ca16 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySourceOptions.kt @@ -0,0 +1,74 @@ +package com.mapbox.mapboxsdk.style.sources + +/** + * Builder class for composing CustomGeometrySource objects. + */ +class CustomGeometrySourceOptions : HashMap() { + /** + * If the data includes wrapped coordinates, setting this to true unwraps the coordinates. + * + * @param wrap defaults to false + * @return the current instance for chaining + */ + fun withWrap(wrap: Boolean): CustomGeometrySourceOptions { + this["wrap"] = wrap + return this + } + + /** + * If the data includes geometry outside the tile boundaries, setting this to true clips the geometry + * to the tile boundaries. + * + * @param clip defaults to false + * @return the current instance for chaining + */ + fun withClip(clip: Boolean): CustomGeometrySourceOptions { + this["clip"] = clip + return this + } + + /** + * Minimum zoom level at which to create vector tiles (lower means more field of view detail at low zoom levels). + * + * @param minZoom the minimum zoom - Defaults to 0. + * @return the current instance for chaining + */ + fun withMinZoom(minZoom: Int): CustomGeometrySourceOptions { + this["minzoom"] = minZoom + return this + } + + /** + * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels). + * + * @param maxZoom the maximum zoom - Defaults to 25.5 + * @return the current instance for chaining + */ + fun withMaxZoom(maxZoom: Int): CustomGeometrySourceOptions { + this["maxzoom"] = maxZoom + return this + } + + /** + * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile + * edges but slower performance). + * + * @param buffer the buffer size - Defaults to 128. + * @return the current instance for chaining + */ + fun withBuffer(buffer: Int): CustomGeometrySourceOptions { + this["buffer"] = buffer + return this + } + + /** + * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance). + * + * @param tolerance the tolerance - Defaults to 0.375 + * @return the current instance for chaining + */ + fun withTolerance(tolerance: Float): CustomGeometrySourceOptions { + this["tolerance"] = tolerance + return this + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java deleted file mode 100644 index ea34b0dc0..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.NonNull; - -import com.mapbox.mapboxsdk.style.expressions.Expression; - -import java.util.HashMap; - -import static com.mapbox.mapboxsdk.style.expressions.Expression.ExpressionLiteral; - -/** - * Builder class for composing GeoJsonSource objects. - * - * @see GeoJsonSource - * @see The online documentation - */ -public class GeoJsonOptions extends HashMap { - - /** - * Minimum zoom level at which to create vector tiles (lower means more field of view detail at low zoom levels). - * - * @param minZoom the minimum zoom - Defaults to 0. - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withMinZoom(int minZoom) { - this.put("minzoom", minZoom); - return this; - } - - /** - * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels). - * - * @param maxZoom the maximum zoom - Defaults to 25.5 - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withMaxZoom(int maxZoom) { - this.put("maxzoom", maxZoom); - return this; - } - - /** - * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile - * edges but slower performance). - * - * @param buffer the buffer size - Defaults to 128. - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withBuffer(int buffer) { - this.put("buffer", buffer); - return this; - } - - /** - * Initialises whether to calculate line distance metrics. - * - * @param lineMetrics true to calculate line distance metrics. - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withLineMetrics(boolean lineMetrics) { - this.put("lineMetrics", lineMetrics); - return this; - } - - /** - * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance). - * - * @param tolerance the tolerance - Defaults to 0.375 - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withTolerance(float tolerance) { - this.put("tolerance", tolerance); - return this; - } - - /** - * If the data is a collection of point features, setting this to true clusters the points by radius into groups. - * - * @param cluster cluster? - Defaults to false - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withCluster(boolean cluster) { - this.put("cluster", cluster); - return this; - } - - /** - * Max zoom to cluster points on. - * - * @param clusterMaxZoom clusterMaxZoom cluster maximum zoom - Defaults to one zoom less than maxzoom (so that last - * zoom features are not clustered) - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withClusterMaxZoom(int clusterMaxZoom) { - this.put("clusterMaxZoom", clusterMaxZoom); - return this; - } - - /** - * Radius of each cluster when clustering points, measured in 1/512ths of a tile. - * - * @param clusterRadius cluster radius - Defaults to 50 - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withClusterRadius(int clusterRadius) { - this.put("clusterRadius", clusterRadius); - return this; - } - - /** - * An object defining custom properties on the generated clusters if clustering is enabled, - * aggregating values from clustered points. Has the form {"property_name": [operator, [map_expression]]} or - * {"property_name": [[operator, accumulated, expression], [map_expression]]} - * - * @param propertyName name of the property - * @param operatorExpr operatorExpr is any expression function that accepts at least 2 operands (e.g. "+" or "max"). - * It accumulates the property value from clusters/points the cluster contains. It can either be - * a literal with single operator, or be a valid expression - * @param mapExpr map expression produces the value of a single point, it shall be a valid expression - * @return the current instance for chaining - */ - @NonNull - public GeoJsonOptions withClusterProperty(String propertyName, Expression operatorExpr, Expression mapExpr) { - HashMap properties = containsKey("clusterProperties") - ? (HashMap) get("clusterProperties") : new HashMap(); - Object operator = (operatorExpr instanceof ExpressionLiteral) - ? ((ExpressionLiteral)operatorExpr).toValue() : operatorExpr.toArray(); - Object map = mapExpr.toArray(); - properties.put(propertyName, new Object[]{operator, map}); - this.put("clusterProperties", properties); - return this; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.kt new file mode 100644 index 000000000..db61665bb --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.kt @@ -0,0 +1,123 @@ +package com.mapbox.mapboxsdk.style.sources + +import com.mapbox.mapboxsdk.style.expressions.Expression +import com.mapbox.mapboxsdk.style.expressions.Expression.ExpressionLiteral +/** + * Builder class for composing GeoJsonSource objects. + * + * @see GeoJsonSource + * + * @see [The online documentation](https://www.mapbox.com/mapbox-gl-style-spec/.sources-geojson) + */ +class GeoJsonOptions : HashMap() { + /** + * Minimum zoom level at which to create vector tiles (lower means more field of view detail at low zoom levels). + * + * @param minZoom the minimum zoom - Defaults to 0. + * @return the current instance for chaining + */ + fun withMinZoom(minZoom: Int): GeoJsonOptions { + this["minzoom"] = minZoom + return this + } + + /** + * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels). + * + * @param maxZoom the maximum zoom - Defaults to 25.5 + * @return the current instance for chaining + */ + fun withMaxZoom(maxZoom: Int): GeoJsonOptions { + this["maxzoom"] = maxZoom + return this + } + + /** + * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile + * edges but slower performance). + * + * @param buffer the buffer size - Defaults to 128. + * @return the current instance for chaining + */ + fun withBuffer(buffer: Int): GeoJsonOptions { + this["buffer"] = buffer + return this + } + + /** + * Initialises whether to calculate line distance metrics. + * + * @param lineMetrics true to calculate line distance metrics. + * @return the current instance for chaining + */ + fun withLineMetrics(lineMetrics: Boolean): GeoJsonOptions { + this["lineMetrics"] = lineMetrics + return this + } + + /** + * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance). + * + * @param tolerance the tolerance - Defaults to 0.375 + * @return the current instance for chaining + */ + fun withTolerance(tolerance: Float): GeoJsonOptions { + this["tolerance"] = tolerance + return this + } + + /** + * If the data is a collection of point features, setting this to true clusters the points by radius into groups. + * + * @param cluster cluster? - Defaults to false + * @return the current instance for chaining + */ + fun withCluster(cluster: Boolean): GeoJsonOptions { + this["cluster"] = cluster + return this + } + + /** + * Max zoom to cluster points on. + * + * @param clusterMaxZoom clusterMaxZoom cluster maximum zoom - Defaults to one zoom less than maxzoom (so that last + * zoom features are not clustered) + * @return the current instance for chaining + */ + fun withClusterMaxZoom(clusterMaxZoom: Int): GeoJsonOptions { + this["clusterMaxZoom"] = clusterMaxZoom + return this + } + + /** + * Radius of each cluster when clustering points, measured in 1/512ths of a tile. + * + * @param clusterRadius cluster radius - Defaults to 50 + * @return the current instance for chaining + */ + fun withClusterRadius(clusterRadius: Int): GeoJsonOptions { + this["clusterRadius"] = clusterRadius + return this + } + + /** + * An object defining custom properties on the generated clusters if clustering is enabled, + * aggregating values from clustered points. Has the form {"property_name": [operator, [map_expression]]} or + * {"property_name": [[operator, accumulated, expression], [map_expression]]} + * + * @param propertyName name of the property + * @param operatorExpr operatorExpr is any expression function that accepts at least 2 operands (e.g. "+" or "max"). + * It accumulates the property value from clusters/points the cluster contains. It can either be + * a literal with single operator, or be a valid expression + * @param mapExpr map expression produces the value of a single point, it shall be a valid expression + * @return the current instance for chaining + */ + fun withClusterProperty(propertyName: String, operatorExpr: Expression, mapExpr: Expression): GeoJsonOptions { + val properties = if (containsKey("clusterProperties")) get("clusterProperties") as HashMap>? else HashMap() + val operator = if (operatorExpr is ExpressionLiteral) operatorExpr.toValue() else operatorExpr.toArray() + val map: Any = mapExpr.toArray() + properties!![propertyName] = arrayOf(operator, map) + this["clusterProperties"] = properties + return this + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java deleted file mode 100644 index 85216e931..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java +++ /dev/null @@ -1,519 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; - -import com.mapbox.geojson.Feature; -import com.mapbox.geojson.FeatureCollection; -import com.mapbox.geojson.Geometry; -import com.mapbox.mapboxsdk.style.expressions.Expression; - -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * GeoJson source, allows using FeatureCollections from Json. - * - * @see the style specification - */ -@UiThread -public class GeoJsonSource extends Source { - - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - @Keep - GeoJsonSource(long nativePtr) { - super(nativePtr); - } - - /** - * Create an empty GeoJsonSource - * - * @param id the source id - */ - public GeoJsonSource(String id) { - super(); - initialize(id, null); - setGeoJson(FeatureCollection.fromFeatures(new ArrayList())); - } - - /** - * Create an empty GeoJsonSource with non-default GeoJsonOptions. - * - * @param id the source id - * @param options options - */ - public GeoJsonSource(String id, GeoJsonOptions options) { - super(); - initialize(id, options); - setGeoJson(FeatureCollection.fromFeatures(new ArrayList())); - } - - /** - * Create a GeoJsonSource from a raw json string - * - * @param id the source id - * @param geoJson raw Json FeatureCollection - */ - public GeoJsonSource(String id, @Nullable String geoJson) { - super(); - if (geoJson == null || geoJson.startsWith("http")) { - throw new IllegalArgumentException("Expected a raw json body"); - } - initialize(id, null); - setGeoJson(geoJson); - } - - /** - * Create a GeoJsonSource from a raw json string and non-default GeoJsonOptions - * - * @param id the source id - * @param geoJson raw Json body - * @param options options - */ - public GeoJsonSource(String id, @Nullable String geoJson, GeoJsonOptions options) { - super(); - if (geoJson == null || geoJson.startsWith("http") || geoJson.startsWith("asset") || geoJson.startsWith("file")) { - throw new IllegalArgumentException("Expected a raw json body"); - } - initialize(id, options); - setGeoJson(geoJson); - } - - /** - * Create a GeoJsonSource from a remote geo json file - * - * @param id the source id - * @param url remote json file - * @deprecated use {@link #GeoJsonSource(String, URI)} instead - */ - @Deprecated - public GeoJsonSource(String id, URL url) { - super(); - initialize(id, null); - nativeSetUrl(url.toExternalForm()); - } - - /** - * Create a GeoJsonSource from a remote geo json file and non-default GeoJsonOptions - * - * @param id the source id - * @param url remote json file - * @param options options - * @deprecated use {@link #GeoJsonSource(String, URI, GeoJsonOptions)} instead - */ - @Deprecated - public GeoJsonSource(String id, URL url, GeoJsonOptions options) { - super(); - initialize(id, options); - nativeSetUrl(url.toExternalForm()); - } - - /** - * Create a GeoJsonSource from a geo json URI - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- * - * - * @param id the source id - * @param uri unique resource identifier - */ - public GeoJsonSource(String id, URI uri) { - super(); - initialize(id, null); - nativeSetUrl(uri.toString()); - } - - /** - * Create a GeoJsonSource from a geo json URI and non-default GeoJsonOptions - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- * - * - * @param id the source id - * @param uri remote json file - * @param options options - */ - public GeoJsonSource(String id, URI uri, GeoJsonOptions options) { - super(); - initialize(id, options); - nativeSetUrl(uri.toString()); - } - - /** - * Create a GeoJsonSource from a FeatureCollection. - * - * @param id the source id - * @param features the features - */ - public GeoJsonSource(String id, FeatureCollection features) { - super(); - initialize(id, null); - setGeoJson(features); - } - - /** - * Create a GeoJsonSource from a FeatureCollection and non-default GeoJsonOptions. - * - * @param id the source id - * @param features the features - * @param options options - */ - public GeoJsonSource(String id, FeatureCollection features, GeoJsonOptions options) { - super(); - initialize(id, options); - setGeoJson(features); - } - - /** - * Create a GeoJsonSource from a {@link Feature} - * - * @param id the source id - * @param feature the feature - */ - public GeoJsonSource(String id, Feature feature) { - super(); - initialize(id, null); - setGeoJson(feature); - } - - /** - * Create a GeoJsonSource from a {@link Feature} and non-default {@link GeoJsonOptions} - * - * @param id the source id - * @param feature the feature - * @param options options - */ - public GeoJsonSource(String id, Feature feature, GeoJsonOptions options) { - super(); - initialize(id, options); - setGeoJson(feature); - } - - /** - * Create a GeoJsonSource from a {@link Geometry} - * - * @param id the source id - * @param geometry the geometry - */ - public GeoJsonSource(String id, Geometry geometry) { - super(); - initialize(id, null); - setGeoJson(geometry); - } - - /** - * Create a GeoJsonSource from a {@link Geometry} and non-default {@link GeoJsonOptions} - * - * @param id the source id - * @param geometry the geometry - * @param options options - */ - public GeoJsonSource(String id, Geometry geometry, GeoJsonOptions options) { - super(); - initialize(id, options); - setGeoJson(geometry); - } - - /** - * Updates the GeoJson with a single feature. The update is performed asynchronously, - * so the data won't be immediately visible or available to query when this method returns. - * - * @param feature the GeoJSON {@link Feature} to set - */ - public void setGeoJson(Feature feature) { - if (detached) { - return; - } - checkThread(); - nativeSetFeature(feature); - } - - /** - * Updates the GeoJson with a single geometry. The update is performed asynchronously, - * so the data won't be immediately visible or available to query when this method returns. - * - * @param geometry the GeoJSON {@link Geometry} to set - */ - public void setGeoJson(Geometry geometry) { - if (detached) { - return; - } - checkThread(); - nativeSetGeometry(geometry); - } - - /** - * Updates the GeoJson. The update is performed asynchronously, - * so the data won't be immediately visible or available to query when this method returns. - * - * @param featureCollection the GeoJSON FeatureCollection - */ - public void setGeoJson(@Nullable FeatureCollection featureCollection) { - if (detached) { - return; - } - checkThread(); - - if (featureCollection != null && featureCollection.features() != null) { - List features = featureCollection.features(); - List featuresCopy = new ArrayList<>(features); - nativeSetFeatureCollection(FeatureCollection.fromFeatures(featuresCopy)); - } else { - nativeSetFeatureCollection(featureCollection); - } - } - - /** - * Updates the GeoJson. The update is performed asynchronously, - * so the data won't be immediately visible or available to query when this method returns. - * - * @param json the raw GeoJson FeatureCollection string - */ - public void setGeoJson(String json) { - if (detached) { - return; - } - checkThread(); - nativeSetGeoJsonString(json); - } - - /** - * Updates the url - * - * @param url the GeoJSON FeatureCollection url - * @deprecated use {@link #setUri(URI)} instead - */ - @Deprecated - public void setUrl(@NonNull URL url) { - checkThread(); - setUrl(url.toExternalForm()); - } - - /** - * Updates the URI of the source. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param uri the GeoJSON FeatureCollection uri - */ - public void setUri(@NonNull URI uri) { - setUri(uri.toString()); - } - - /** - * Updates the url - * - * @param url the GeoJSON FeatureCollection url - * @deprecated use {@link #setUri(String)} instead - */ - @Deprecated - public void setUrl(String url) { - checkThread(); - nativeSetUrl(url); - } - - /** - * Updates the URI of the source. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param uri the GeoJSON FeatureCollection uri - */ - public void setUri(String uri) { - checkThread(); - nativeSetUrl(uri); - } - - /** - * @return The url or null - * @deprecated use {@link #getUri()} instead - */ - @Nullable - public String getUrl() { - checkThread(); - return nativeGetUrl(); - } - - /** - * Get the URI of the source. - * - * @return The uri or null - */ - @Nullable - public String getUri() { - checkThread(); - return nativeGetUrl(); - } - - /** - * Queries the source for features. - * - * @param filter an optional filter expression to filter the returned Features - * @return the features - */ - @NonNull - public List querySourceFeatures(@Nullable Expression filter) { - checkThread(); - Feature[] features = querySourceFeatures(filter != null ? filter.toArray() : null); - return features != null ? Arrays.asList(features) : new ArrayList(); - } - - /** - * Returns the children of a cluster (on the next zoom level) given its id (cluster_id value from feature properties). - *

- * Requires configuring this source as a cluster by calling {@link GeoJsonOptions#withCluster(boolean)}. - *

- * - * @param cluster cluster from which to retrieve children from - * @return a list of features for the underlying children - */ - @NonNull - public FeatureCollection getClusterChildren(@NonNull Feature cluster) { - checkThread(); - return FeatureCollection.fromFeatures(nativeGetClusterChildren(cluster)); - } - - /** - * Returns all the leaves of a cluster (given its cluster_id), with pagination support: limit is the number of leaves - * to return (set to Infinity for all points), and offset is the amount of points to skip (for pagination). - *

- * Requires configuring this source as a cluster by calling {@link GeoJsonOptions#withCluster(boolean)}. - *

- * - * @param cluster cluster from which to retrieve leaves from - * @param limit limit is the number of points to return - * @param offset offset is the amount of points to skip (for pagination) - * @return a list of features for the underlying leaves - */ - @NonNull - public FeatureCollection getClusterLeaves(@NonNull Feature cluster, long limit, long offset) { - checkThread(); - return FeatureCollection.fromFeatures(nativeGetClusterLeaves(cluster, limit, offset)); - } - - /** - * Returns the zoom on which the cluster expands into several children (useful for "click to zoom" feature) - * given the cluster's cluster_id (cluster_id value from feature properties). - *

- * Requires configuring this source as a cluster by calling {@link GeoJsonOptions#withCluster(boolean)}. - *

- * - * @param cluster cluster from which to retrieve the expansion zoom from - * @return the zoom on which the cluster expands into several children - */ - public int getClusterExpansionZoom(@NonNull Feature cluster) { - checkThread(); - return nativeGetClusterExpansionZoom(cluster); - } - - @Keep - protected native void initialize(String layerId, Object options); - - @Keep - protected native void nativeSetUrl(String url); - - @NonNull - @Keep - protected native String nativeGetUrl(); - - @Keep - private native void nativeSetGeoJsonString(String geoJson); - - @Keep - private native void nativeSetFeatureCollection(FeatureCollection geoJson); - - @Keep - private native void nativeSetFeature(Feature feature); - - @Keep - private native void nativeSetGeometry(Geometry geometry); - - @NonNull - @Keep - private native Feature[] querySourceFeatures(Object[] filter); - - @Keep - private native Feature[] nativeGetClusterChildren(Feature feature); - - @Keep - private native Feature[] nativeGetClusterLeaves(Feature feature, long limit, long offset); - - @Keep - private native int nativeGetClusterExpansionZoom(Feature feature); - - @Override - @Keep - protected native void finalize() throws Throwable; - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.kt new file mode 100644 index 000000000..87b3972b6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.kt @@ -0,0 +1,498 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.Keep +import androidx.annotation.UiThread +import com.mapbox.geojson.Feature +import com.mapbox.geojson.FeatureCollection +import com.mapbox.geojson.Geometry +import com.mapbox.mapboxsdk.style.expressions.Expression +import java.net.URI +import java.net.URL +import java.util.* + +/** + * GeoJson source, allows using FeatureCollections from Json. + * + * @see [the style specification](https://www.mapbox.com/mapbox-gl-style-spec/.sources-geojson) + */ +@UiThread +class GeoJsonSource : Source { + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + @Keep + internal constructor(nativePtr: Long) : super(nativePtr) { + } + + /** + * Create an empty GeoJsonSource + * + * @param id the source id + */ + constructor(id: String?) : super() { + initialize(id, null) + setGeoJson(FeatureCollection.fromFeatures(ArrayList())) + } + + /** + * Create an empty GeoJsonSource with non-default GeoJsonOptions. + * + * @param id the source id + * @param options options + */ + constructor(id: String?, options: GeoJsonOptions?) : super() { + initialize(id, options) + setGeoJson(FeatureCollection.fromFeatures(ArrayList())) + } + + /** + * Create a GeoJsonSource from a raw json string + * + * @param id the source id + * @param geoJson raw Json FeatureCollection + */ + constructor(id: String?, geoJson: String?) : super() { + require(!(geoJson == null || geoJson.startsWith("http"))) { "Expected a raw json body" } + initialize(id, null) + setGeoJson(geoJson) + } + + /** + * Create a GeoJsonSource from a raw json string and non-default GeoJsonOptions + * + * @param id the source id + * @param geoJson raw Json body + * @param options options + */ + constructor(id: String?, geoJson: String?, options: GeoJsonOptions?) : super() { + require(!(geoJson == null || geoJson.startsWith("http") || geoJson.startsWith("asset") || geoJson.startsWith("file"))) { "Expected a raw json body" } + initialize(id, options) + setGeoJson(geoJson) + } + + /** + * Create a GeoJsonSource from a remote geo json file + * + * @param id the source id + * @param url remote json file + */ + @Deprecated("use {@link #GeoJsonSource(String, URI)} instead") + constructor(id: String?, url: URL) : super() { + initialize(id, null) + nativeSetUrl(url.toExternalForm()) + } + + /** + * Create a GeoJsonSource from a remote geo json file and non-default GeoJsonOptions + * + * @param id the source id + * @param url remote json file + * @param options options + */ + @Deprecated("use {@link #GeoJsonSource(String, URI, GeoJsonOptions)} instead") + constructor(id: String?, url: URL, options: GeoJsonOptions?) : super() { + initialize(id, options) + nativeSetUrl(url.toExternalForm()) + } + + /** + * Create a GeoJsonSource from a geo json URI + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri unique resource identifier + */ + constructor(id: String?, uri: URI) : super() { + initialize(id, null) + nativeSetUrl(uri.toString()) + } + + /** + * Create a GeoJsonSource from a geo json URI and non-default GeoJsonOptions + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri remote json file + * @param options options + */ + constructor(id: String?, uri: URI, options: GeoJsonOptions?) : super() { + initialize(id, options) + nativeSetUrl(uri.toString()) + } + + /** + * Create a GeoJsonSource from a FeatureCollection. + * + * @param id the source id + * @param features the features + */ + constructor(id: String?, features: FeatureCollection?) : super() { + initialize(id, null) + setGeoJson(features) + } + + /** + * Create a GeoJsonSource from a FeatureCollection and non-default GeoJsonOptions. + * + * @param id the source id + * @param features the features + * @param options options + */ + constructor(id: String?, features: FeatureCollection?, options: GeoJsonOptions?) : super() { + initialize(id, options) + setGeoJson(features) + } + + /** + * Create a GeoJsonSource from a [Feature] + * + * @param id the source id + * @param feature the feature + */ + constructor(id: String?, feature: Feature?) : super() { + initialize(id, null) + setGeoJson(feature) + } + + /** + * Create a GeoJsonSource from a [Feature] and non-default [GeoJsonOptions] + * + * @param id the source id + * @param feature the feature + * @param options options + */ + constructor(id: String?, feature: Feature?, options: GeoJsonOptions?) : super() { + initialize(id, options) + setGeoJson(feature) + } + + /** + * Create a GeoJsonSource from a [Geometry] + * + * @param id the source id + * @param geometry the geometry + */ + constructor(id: String?, geometry: Geometry?) : super() { + initialize(id, null) + setGeoJson(geometry) + } + + /** + * Create a GeoJsonSource from a [Geometry] and non-default [GeoJsonOptions] + * + * @param id the source id + * @param geometry the geometry + * @param options options + */ + constructor(id: String?, geometry: Geometry?, options: GeoJsonOptions?) : super() { + initialize(id, options) + setGeoJson(geometry) + } + + /** + * Updates the GeoJson with a single feature. The update is performed asynchronously, + * so the data won't be immediately visible or available to query when this method returns. + * + * @param feature the GeoJSON [Feature] to set + */ + fun setGeoJson(feature: Feature?) { + if (detached) { + return + } + checkThread() + nativeSetFeature(feature) + } + + /** + * Updates the GeoJson with a single geometry. The update is performed asynchronously, + * so the data won't be immediately visible or available to query when this method returns. + * + * @param geometry the GeoJSON [Geometry] to set + */ + fun setGeoJson(geometry: Geometry?) { + if (detached) { + return + } + checkThread() + nativeSetGeometry(geometry) + } + + /** + * Updates the GeoJson. The update is performed asynchronously, + * so the data won't be immediately visible or available to query when this method returns. + * + * @param featureCollection the GeoJSON FeatureCollection + */ + fun setGeoJson(featureCollection: FeatureCollection?) { + if (detached) { + return + } + checkThread() + if (featureCollection != null && featureCollection.features() != null) { + val features = featureCollection.features() + val featuresCopy: List = ArrayList(features) + nativeSetFeatureCollection(FeatureCollection.fromFeatures(featuresCopy)) + } else { + nativeSetFeatureCollection(featureCollection) + } + } + + /** + * Updates the GeoJson. The update is performed asynchronously, + * so the data won't be immediately visible or available to query when this method returns. + * + * @param json the raw GeoJson FeatureCollection string + */ + fun setGeoJson(json: String) { + if (detached) { + return + } + checkThread() + nativeSetGeoJsonString(json) + } + + /** + * Updates the url + * + * @param url the GeoJSON FeatureCollection url + */ + @Deprecated("use {@link #setUri(URI)} instead") + fun setUrl(url: URL) { + checkThread() + this.url = url.toExternalForm() + } + + /** + * Updates the URI of the source. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param uri the GeoJSON FeatureCollection uri + */ + fun setUri(uri: URI) { + setUri(uri.toString()) + } + + /** + * Updates the URI of the source. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param uri the GeoJSON FeatureCollection uri + */ + fun setUri(uri: String?) { + checkThread() + nativeSetUrl(uri) + } + + private fun setUrlInternal(url: String?) { + checkThread() + nativeSetUrl(url) + } + + private fun getUrlInternal(): String? { + checkThread() + return nativeGetUrl() + } + + var url: String? + + /** + * @return The url or null + */ + @get:Deprecated("use {@link #getUri()} instead") + get() { + return getUrlInternal() + } + + /** + * Updates the url + * + * @param url the GeoJSON FeatureCollection url + */ + @Deprecated("use {@link #setUri(String)} instead") + set(value) { + setUrlInternal(value) + } + + /** + * Get the URI of the source. + * + * @return The uri or null + */ + val uri: String? + get() { + checkThread() + return nativeGetUrl() + } + + /** + * Queries the source for features. + * + * @param filter an optional filter expression to filter the returned Features + * @return the features + */ + fun querySourceFeatures(filter: Expression?): List { + checkThread() + val features = querySourceFeatures(filter?.toArray()) + return if (features != null) Arrays.asList(*features) else ArrayList() + } + + /** + * Returns the children of a cluster (on the next zoom level) given its id (cluster_id value from feature properties). + * + * + * Requires configuring this source as a cluster by calling [GeoJsonOptions.withCluster]. + * + * + * @param cluster cluster from which to retrieve children from + * @return a list of features for the underlying children + */ + fun getClusterChildren(cluster: Feature): FeatureCollection { + checkThread() + return FeatureCollection.fromFeatures(nativeGetClusterChildren(cluster)!!) + } + + /** + * Returns all the leaves of a cluster (given its cluster_id), with pagination support: limit is the number of leaves + * to return (set to Infinity for all points), and offset is the amount of points to skip (for pagination). + * + * + * Requires configuring this source as a cluster by calling [GeoJsonOptions.withCluster]. + * + * + * @param cluster cluster from which to retrieve leaves from + * @param limit limit is the number of points to return + * @param offset offset is the amount of points to skip (for pagination) + * @return a list of features for the underlying leaves + */ + fun getClusterLeaves(cluster: Feature, limit: Long, offset: Long): FeatureCollection { + checkThread() + return FeatureCollection.fromFeatures(nativeGetClusterLeaves(cluster, limit, offset)!!) + } + + /** + * Returns the zoom on which the cluster expands into several children (useful for "click to zoom" feature) + * given the cluster's cluster_id (cluster_id value from feature properties). + * + * + * Requires configuring this source as a cluster by calling [GeoJsonOptions.withCluster]. + * + * + * @param cluster cluster from which to retrieve the expansion zoom from + * @return the zoom on which the cluster expands into several children + */ + fun getClusterExpansionZoom(cluster: Feature): Int { + checkThread() + return nativeGetClusterExpansionZoom(cluster) + } + + @Keep + protected external fun initialize(layerId: String?, options: Any?) + + @Keep + protected external fun nativeSetUrl(url: String?) + + @Keep + protected external fun nativeGetUrl(): String? + + @Keep + private external fun nativeSetGeoJsonString(geoJson: String) + + @Keep + private external fun nativeSetFeatureCollection(geoJson: FeatureCollection?) + + @Keep + private external fun nativeSetFeature(feature: Feature?) + + @Keep + private external fun nativeSetGeometry(geometry: Geometry?) + + @Keep + private external fun querySourceFeatures(filter: Array?): Array + + @Keep + private external fun nativeGetClusterChildren(feature: Feature): Array? + + @Keep + private external fun nativeGetClusterLeaves(feature: Feature, limit: Long, offset: Long): Array? + + @Keep + private external fun nativeGetClusterExpansionZoom(feature: Feature): Int + + @Keep + @Throws(Throwable::class) + protected external fun finalize() +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java deleted file mode 100644 index 1ca67011a..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.WorkerThread; - -import com.mapbox.geojson.FeatureCollection; -import com.mapbox.mapboxsdk.geometry.LatLngBounds; - -/** - * Interface that defines methods for working with {@link CustomGeometrySource}. - */ -public interface GeometryTileProvider { - - /*** - * Interface method called by {@link CustomGeometrySource} to request features for a tile. - * - * @param bounds {@link LatLngBounds} of the tile. - * @param zoomLevel Tile zoom level. - * @return Return a @{link FeatureCollection} to be displayed in the requested tile. - */ - @WorkerThread - FeatureCollection getFeaturesForBounds(LatLngBounds bounds, int zoomLevel); -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.kt new file mode 100644 index 000000000..4ad98095f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.kt @@ -0,0 +1,20 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.WorkerThread +import com.mapbox.geojson.FeatureCollection +import com.mapbox.mapboxsdk.geometry.LatLngBounds + +/** + * Interface that defines methods for working with [CustomGeometrySource]. + */ +interface GeometryTileProvider { + /*** + * Interface method called by [CustomGeometrySource] to request features for a tile. + * + * @param bounds [LatLngBounds] of the tile. + * @param zoomLevel Tile zoom level. + * @return Return a @{link FeatureCollection} to be displayed in the requested tile. + */ + @WorkerThread + fun getFeaturesForBounds(bounds: LatLngBounds, zoomLevel: Int): FeatureCollection +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.java deleted file mode 100644 index 0fc393fae..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.java +++ /dev/null @@ -1,273 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; - -import androidx.annotation.DrawableRes; -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; - -import com.mapbox.mapboxsdk.Mapbox; -import com.mapbox.mapboxsdk.geometry.LatLngQuad; -import com.mapbox.mapboxsdk.utils.BitmapUtils; - -import java.net.URI; -import java.net.URL; - - -/** - * Image source, allows a georeferenced raster image to be shown on the map. - *

- * The georeferenced image scales and rotates as the user zooms and rotates the map. - * The geographic location of the raster image content, supplied with `LatLngQuad`, - * can be non-axis aligned. - *

- * * @see the style specification - */ -@UiThread -public class ImageSource extends Source { - - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - @Keep - ImageSource(long nativePtr) { - super(nativePtr); - } - - /** - * Create an ImageSource from coordinates and an image URL - * - * @param id The source id - * @param coordinates The Latitude and Longitude of the four corners of the image - * @param url remote json file - * @deprecated use {@link ImageSource#ImageSource(String, LatLngQuad, URI)} instead - */ - @Deprecated - public ImageSource(String id, LatLngQuad coordinates, @NonNull URL url) { - super(); - initialize(id, coordinates); - setUrl(url); - } - - /** - * Create an ImageSource from coordinates and an image URI - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id The source id - * @param coordinates The Latitude and Longitude of the four corners of the image - * @param uri json file uri - */ - public ImageSource(String id, LatLngQuad coordinates, @NonNull URI uri) { - super(); - initialize(id, coordinates); - setUri(uri); - } - - /** - * Create an ImageSource from coordinates and a bitmap image - * - * @param id The source id - * @param coordinates The Latitude and Longitude of the four corners of the image - * @param bitmap A Bitmap image - */ - public ImageSource(String id, LatLngQuad coordinates, @NonNull Bitmap bitmap) { - super(); - initialize(id, coordinates); - setImage(bitmap); - } - - /** - * Create an ImageSource from coordinates and a bitmap image resource - * - * @param id The source id - * @param coordinates The Latitude and Longitude of the four corners of the image - * @param resourceId The resource ID of a Bitmap image - */ - public ImageSource(String id, LatLngQuad coordinates, @DrawableRes int resourceId) { - super(); - initialize(id, coordinates); - setImage(resourceId); - } - - /** - * Updates the source image url - * - * @param url An Image url - * @deprecated use {@link #setUri(URI)} instead - */ - @Deprecated - public void setUrl(@NonNull URL url) { - setUrl(url.toExternalForm()); - } - - /** - * Updates the source image url - * - * @param url An image url - * @deprecated use {@link #setUri(String)} instead - */ - @Deprecated - public void setUrl(String url) { - checkThread(); - nativeSetUrl(url); - } - - /** - * Updates the source image URI. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param uri An Image uri - */ - public void setUri(@NonNull URI uri) { - checkThread(); - nativeSetUrl(uri.toString()); - } - - /** - * Updates the source image URI. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param uri An image uri - */ - public void setUri(String uri) { - checkThread(); - nativeSetUrl(uri); - } - - /** - * Updates the source image to a bitmap - * - * @param bitmap A Bitmap image - */ - public void setImage(@NonNull android.graphics.Bitmap bitmap) { - checkThread(); - nativeSetImage(bitmap); - } - - /** - * Updates the source image to a bitmap image resource - * - * @param resourceId The resource ID of a Bitmap image - */ - public void setImage(@DrawableRes int resourceId) throws IllegalArgumentException { - checkThread(); - Context context = Mapbox.getApplicationContext(); - Drawable drawable = BitmapUtils.getDrawableFromRes(context, resourceId); - if (drawable instanceof BitmapDrawable) { - BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; - nativeSetImage(bitmapDrawable.getBitmap()); - } else { - throw new IllegalArgumentException("Failed to decode image. The resource provided must be a Bitmap."); - } - } - - /** - * @return The url or null - * @deprecated use {@link #getUri()} instead - */ - @Deprecated - @Nullable - public String getUrl() { - checkThread(); - return nativeGetUrl(); - } - - /** - * Get the source URI. - * - * @return The uri or null - */ - @Nullable - public String getUri() { - checkThread(); - return nativeGetUrl(); - } - - /** - * Updates the latitude and longitude of the four corners of the image - * - * @param latLngQuad latitude and longitude of the four corners of the image - */ - public void setCoordinates(LatLngQuad latLngQuad) { - checkThread(); - nativeSetCoordinates(latLngQuad); - } - - @Keep - protected native void initialize(String layerId, LatLngQuad payload); - - @Keep - protected native void nativeSetUrl(String url); - - @NonNull - @Keep - protected native String nativeGetUrl(); - - @Keep - protected native void nativeSetImage(Bitmap bitmap); - - @Keep - protected native void nativeSetCoordinates(LatLngQuad latLngQuad); - - @Override - @Keep - protected native void finalize() throws Throwable; -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.kt new file mode 100644 index 000000000..00551c51c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/ImageSource.kt @@ -0,0 +1,257 @@ +package com.mapbox.mapboxsdk.style.sources + +import android.graphics.Bitmap +import android.graphics.drawable.BitmapDrawable +import androidx.annotation.DrawableRes +import androidx.annotation.Keep +import androidx.annotation.UiThread +import com.mapbox.mapboxsdk.Mapbox +import com.mapbox.mapboxsdk.geometry.LatLngQuad +import com.mapbox.mapboxsdk.utils.BitmapUtils +import java.net.URI +import java.net.URL +/** + * Image source, allows a georeferenced raster image to be shown on the map. + * + * + * The georeferenced image scales and rotates as the user zooms and rotates the map. + * The geographic location of the raster image content, supplied with `LatLngQuad`, + * can be non-axis aligned. + * + * * @see [the style specification](https://www.mapbox.com/mapbox-gl-style-spec/#sources-image) + */ +@UiThread +class ImageSource : Source { + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + @Keep + internal constructor(nativePtr: Long) : super(nativePtr) { + } + + /** + * Create an ImageSource from coordinates and an image URL + * + * @param id The source id + * @param coordinates The Latitude and Longitude of the four corners of the image + * @param url remote json file + */ + @Deprecated("use {@link ImageSource#ImageSource(String, LatLngQuad, URI)} instead") + constructor(id: String?, coordinates: LatLngQuad?, url: URL) : super() { + initialize(id, coordinates) + setUrl(url) + } + + /** + * Create an ImageSource from coordinates and an image URI + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id The source id + * @param coordinates The Latitude and Longitude of the four corners of the image + * @param uri json file uri + */ + constructor(id: String?, coordinates: LatLngQuad?, uri: URI) : super() { + initialize(id, coordinates) + setUri(uri) + } + + /** + * Create an ImageSource from coordinates and a bitmap image + * + * @param id The source id + * @param coordinates The Latitude and Longitude of the four corners of the image + * @param bitmap A Bitmap image + */ + constructor(id: String?, coordinates: LatLngQuad?, bitmap: Bitmap) : super() { + initialize(id, coordinates) + setImage(bitmap) + } + + /** + * Create an ImageSource from coordinates and a bitmap image resource + * + * @param id The source id + * @param coordinates The Latitude and Longitude of the four corners of the image + * @param resourceId The resource ID of a Bitmap image + */ + constructor(id: String?, coordinates: LatLngQuad?, @DrawableRes resourceId: Int) : super() { + initialize(id, coordinates) + setImage(resourceId) + } + + /** + * Updates the source image url + * + * @param url An Image url + */ + @Deprecated("use {@link #setUri(URI)} instead") + fun setUrl(url: URL) { + setUrl(url.toExternalForm()) + } + + /** + * Updates the source image url + * + * @param url An image url + */ + @Deprecated("use {@link #setUri(String)} instead") + fun setUrl(url: String?) { + checkThread() + nativeSetUrl(url) + } + + /** + * Updates the source image URI. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param uri An Image uri + */ + fun setUri(uri: URI) { + checkThread() + nativeSetUrl(uri.toString()) + } + + /** + * Updates the source image URI. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param uri An image uri + */ + fun setUri(uri: String?) { + checkThread() + nativeSetUrl(uri) + } + + /** + * Updates the source image to a bitmap + * + * @param bitmap A Bitmap image + */ + fun setImage(bitmap: Bitmap) { + checkThread() + nativeSetImage(bitmap) + } + + /** + * Updates the source image to a bitmap image resource + * + * @param resourceId The resource ID of a Bitmap image + */ + @Throws(IllegalArgumentException::class) + fun setImage(@DrawableRes resourceId: Int) { + checkThread() + val context = Mapbox.getApplicationContext() + val drawable = BitmapUtils.getDrawableFromRes(context, resourceId) + if (drawable is BitmapDrawable) { + nativeSetImage(drawable.bitmap) + } else { + throw IllegalArgumentException("Failed to decode image. The resource provided must be a Bitmap.") + } + } + + /** + * @return The url or null + */ + @get:Deprecated("use {@link #getUri()} instead") + val url: String? + get() { + checkThread() + return nativeGetUrl() + } + + /** + * Get the source URI. + * + * @return The uri or null + */ + val uri: String? + get() { + checkThread() + return nativeGetUrl() + } + + /** + * Updates the latitude and longitude of the four corners of the image + * + * @param latLngQuad latitude and longitude of the four corners of the image + */ + fun setCoordinates(latLngQuad: LatLngQuad?) { + checkThread() + nativeSetCoordinates(latLngQuad) + } + + @Keep + protected external fun initialize(layerId: String?, payload: LatLngQuad?) + + @Keep + protected external fun nativeSetUrl(url: String?) + + @Keep + protected external fun nativeGetUrl(): String + + @Keep + protected external fun nativeSetImage(bitmap: Bitmap?) + + @Keep + protected external fun nativeSetCoordinates(latLngQuad: LatLngQuad?) + + @Keep + @Throws(Throwable::class) + protected external fun finalize() +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/PackageInfo.kt similarity index 61% rename from platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/package-info.java rename to platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/PackageInfo.kt index c7c325ee5..211fe62f1 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/package-info.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/PackageInfo.kt @@ -1,4 +1,4 @@ /** * Contains the Mapbox Maps Android Style Sources API classes. */ -package com.mapbox.mapboxsdk.style.sources; +package com.mapbox.mapboxsdk.style.sources diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.java deleted file mode 100644 index 39cf4b327..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; - -import java.net.URI; -import java.net.URL; - -/** - * A raster DEM source. - * - * @see The style specification - */ -@UiThread -public class RasterDemSource extends Source { - public static final int DEFAULT_TILE_SIZE = 512; - - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - @Keep - RasterDemSource(long nativePtr) { - super(nativePtr); - } - - /** - * Create the raster dem source from an URL - * - * @param id the source id - * @param url the source url - * @deprecated use {@link #RasterDemSource(String, URI)} instead - */ - @Deprecated - public RasterDemSource(String id, URL url) { - this(id, url.toExternalForm()); - } - - /** - * Create the raster dem source from an URI. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the source uri - */ - public RasterDemSource(String id, URI uri) { - this(id, uri.toString()); - } - - /** - * Create the raster dem source from an URI - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the source uri - */ - public RasterDemSource(String id, String uri) { - super(); - initialize(id, uri, DEFAULT_TILE_SIZE); - } - - /** - * Create the raster source from an URL with a specific tile size - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the source url - * @param tileSize the tile size - */ - public RasterDemSource(String id, String uri, int tileSize) { - super(); - initialize(id, uri, tileSize); - } - - /** - * Create the raster dem source from a {@link TileSet} - * - * @param id the source id - * @param tileSet the {@link TileSet} - */ - public RasterDemSource(String id, TileSet tileSet) { - super(); - initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE); - } - - /** - * Create the raster source from a {@link TileSet} with a specific tile size - * - * @param id the source id - * @param tileSet the {@link TileSet} - * @param tileSize tje tile size - */ - public RasterDemSource(String id, TileSet tileSet, int tileSize) { - super(); - initialize(id, tileSet.toValueObject(), tileSize); - } - - /** - * @return The url or null - * @deprecated use {@link #getUri()} instead - */ - @Deprecated - @Nullable - public String getUrl() { - checkThread(); - return nativeGetUrl(); - } - - /** - * Get the source URI. - * - * @return The uri or null - */ - @Nullable - public String getUri() { - checkThread(); - return nativeGetUrl(); - } - - @Keep - protected native void initialize(String layerId, Object payload, int tileSize); - - @Override - @Keep - protected native void finalize() throws Throwable; - - @NonNull - @Keep - protected native String nativeGetUrl(); - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.kt new file mode 100644 index 000000000..fc50f2579 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterDemSource.kt @@ -0,0 +1,176 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.Keep +import androidx.annotation.UiThread +import java.net.URI +import java.net.URL + +/** + * A raster DEM source. + * + * @see [The style specification](https://maplibre.org/maplibre-gl-js-docs/style-spec/.sources-raster-dem) + */ + +@UiThread +class RasterDemSource : Source { + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + @Keep + internal constructor(nativePtr: Long) : super(nativePtr) { + } + + /** + * Create the raster dem source from an URL + * + * @param id the source id + * @param url the source url + */ + @Deprecated("use {@link #RasterDemSource(String, URI)} instead") + constructor(id: String?, url: URL) : this(id, url.toExternalForm()) { + } + + /** + * Create the raster dem source from an URI. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the source uri + */ + constructor(id: String?, uri: URI) : this(id, uri.toString()) {} + + /** + * Create the raster dem source from an URI + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the source uri + */ + constructor(id: String?, uri: String?) : super() { + initialize(id, uri, DEFAULT_TILE_SIZE) + } + + /** + * Create the raster source from an URL with a specific tile size + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the source url + * @param tileSize the tile size + */ + constructor(id: String?, uri: String?, tileSize: Int) : super() { + initialize(id, uri, tileSize) + } + + /** + * Create the raster dem source from a [TileSet] + * + * @param id the source id + * @param tileSet the [TileSet] + */ + constructor(id: String?, tileSet: TileSet) : super() { + initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE) + } + + /** + * Create the raster source from a [TileSet] with a specific tile size + * + * @param id the source id + * @param tileSet the [TileSet] + * @param tileSize tje tile size + */ + constructor(id: String?, tileSet: TileSet, tileSize: Int) : super() { + initialize(id, tileSet.toValueObject(), tileSize) + } + + /** + * @return The url or null + */ + @get:Deprecated("use {@link #getUri()} instead") + val url: String? + get() { + checkThread() + return nativeGetUrl() + } + + /** + * Get the source URI. + * + * @return The uri or null + */ + val uri: String? + get() { + checkThread() + return nativeGetUrl() + } + + @Keep + protected external fun initialize(layerId: String?, payload: Any?, tileSize: Int) + + @Keep + @Throws(Throwable::class) + protected external fun finalize() + + @Keep + private external fun nativeGetUrl(): String + + companion object { + const val DEFAULT_TILE_SIZE = 512 + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java deleted file mode 100644 index 9eb9f575c..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.net.URI; -import java.net.URL; - -/** - * Raster source, allows using raster tiles as source. - * - * @see The style specification - */ -public class RasterSource extends Source { - public static final int DEFAULT_TILE_SIZE = 512; - - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - @Keep - RasterSource(long nativePtr) { - super(nativePtr); - } - - /** - * Create the raster source from an URL - * - * @param id the source id - * @param url the source url - * @deprecated use {@link #RasterSource(String, URI)} instead - */ - public RasterSource(String id, URL url) { - this(id, url.toExternalForm()); - } - - /** - * Create the raster source from an URI. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the source uri - */ - public RasterSource(String id, URI uri) { - this(id, uri.toString()); - } - - /** - * Create the raster source from an URI. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the source uri - */ - public RasterSource(String id, String uri) { - super(); - initialize(id, uri, DEFAULT_TILE_SIZE); - } - - /** - * Create the raster source from an URI with a specific tile size. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the source uri - * @param tileSize the tile size - */ - public RasterSource(String id, String uri, int tileSize) { - super(); - initialize(id, uri, tileSize); - } - - /** - * Create the raster source from a {@link TileSet} - * - * @param id the source id - * @param tileSet the {@link TileSet} - */ - public RasterSource(String id, TileSet tileSet) { - super(); - initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE); - } - - /** - * Create the raster source from a {@link TileSet} with a specific tile size - * - * @param id the source id - * @param tileSet the {@link TileSet} - * @param tileSize tje tile size - */ - public RasterSource(String id, TileSet tileSet, int tileSize) { - super(); - initialize(id, tileSet.toValueObject(), tileSize); - } - - /** - * @return The url or null - * @deprecated use {@link #getUri()} instead - */ - @Nullable - @Deprecated - public String getUrl() { - checkThread(); - return nativeGetUrl(); - } - - /** - * Get the source URI. - * - * @return The uri or null - */ - @Nullable - public String getUri() { - checkThread(); - return nativeGetUrl(); - } - - @Keep - protected native void initialize(String layerId, Object payload, int tileSize); - - @Override - @Keep - protected native void finalize() throws Throwable; - - @NonNull - @Keep - protected native String nativeGetUrl(); - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.kt new file mode 100644 index 000000000..a6a821574 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.kt @@ -0,0 +1,173 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.Keep +import java.net.URI +import java.net.URL + +/** + * Raster source, allows using raster tiles as source. + * + * @see [The style specification](https://www.mapbox.com/mapbox-gl-style-spec/.sources-raster) + */ +class RasterSource : Source { + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + @Keep + internal constructor(nativePtr: Long) : super(nativePtr) { + } + + /** + * Create the raster source from an URL + * + * @param id the source id + * @param url the source url + */ + @Deprecated("use {@link #RasterSource(String, URI)} instead") + constructor(id: String?, url: URL) : this(id, url.toExternalForm()) { + } + + /** + * Create the raster source from an URI. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the source uri + */ + constructor(id: String?, uri: URI) : this(id, uri.toString()) {} + + /** + * Create the raster source from an URI. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the source uri + */ + constructor(id: String?, uri: String?) : super() { + initialize(id, uri, DEFAULT_TILE_SIZE) + } + + /** + * Create the raster source from an URI with a specific tile size. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the source uri + * @param tileSize the tile size + */ + constructor(id: String?, uri: String?, tileSize: Int) : super() { + initialize(id, uri, tileSize) + } + + /** + * Create the raster source from a [TileSet] + * + * @param id the source id + * @param tileSet the [TileSet] + */ + constructor(id: String?, tileSet: TileSet) : super() { + initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE) + } + + /** + * Create the raster source from a [TileSet] with a specific tile size + * + * @param id the source id + * @param tileSet the [TileSet] + * @param tileSize tje tile size + */ + constructor(id: String?, tileSet: TileSet, tileSize: Int) : super() { + initialize(id, tileSet.toValueObject(), tileSize) + } + + /** + * @return The url or null + */ + @get:Deprecated("use {@link #getUri()} instead") + val url: String? + get() { + checkThread() + return nativeGetUrl() + } + + /** + * Get the source URI. + * + * @return The uri or null + */ + val uri: String? + get() { + checkThread() + return nativeGetUrl() + } + + @Keep + protected external fun initialize(layerId: String?, payload: Any?, tileSize: Int) + + @Keep + @Throws(Throwable::class) + protected external fun finalize() + + @Keep + protected external fun nativeGetUrl(): String + + companion object { + const val DEFAULT_TILE_SIZE = 512 + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java index a0ef6b985..42dd4f288 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java @@ -174,13 +174,11 @@ public abstract class Source { @Keep protected native Integer nativeGetPrefetchZoomDelta(); - @NonNull @Keep - protected native void nativeSetPrefetchZoomDelta(Integer delta); + protected native void nativeSetPrefetchZoomDelta(@Nullable Integer delta); - @NonNull @Keep - protected native void nativeSetMaxOverscaleFactorForParentTiles(Integer maxOverscaleFactor); + protected native void nativeSetMaxOverscaleFactorForParentTiles(@Nullable Integer maxOverscaleFactor); @NonNull @Keep @@ -190,13 +188,11 @@ public abstract class Source { @Keep protected native Boolean nativeIsVolatile(); - @NonNull @Keep - protected native void nativeSetVolatile(Boolean value); + protected native void nativeSetVolatile(@NonNull Boolean value); - @NonNull @Keep - protected native void nativeSetMinimumTileUpdateInterval(Long interval); + protected native void nativeSetMinimumTileUpdateInterval(@NonNull Long interval); @NonNull @Keep diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java deleted file mode 100644 index 5e8db3839..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java +++ /dev/null @@ -1,341 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.NonNull; -import androidx.annotation.Size; - -import com.mapbox.mapboxsdk.geometry.LatLng; - -import java.util.HashMap; -import java.util.Map; - -/** - * Tile set, allows using TileJson specification as source. - * Note that `encoding` is only relevant to `raster-dem` sources, and is not supported in the TileJson spec. - * - * @see The tileset specification - */ -public class TileSet { - private final String tilejson; - private String name; - private String description; - private String version; - private String attribution; - private String template; - private String legend; - private String scheme; - private final String[] tiles; - private String[] grids; - private String[] data; - private Float minZoom; - private Float maxZoom; - private Float[] bounds; - private Float[] center; - private String encoding; - - /** - * @param tilejson A semver.org style version number. Describes the version of the TileJSON spec that is implemented - * by this JSON object. - * @param tiles An array of tile endpoints. {z}, {x} and {y}, if present, are replaced with the corresponding - * integers. - * If multiple endpoints are specified, clients may use any combination of endpoints. All endpoints - * MUST return the same - * content for the same URL. The array MUST contain at least one endpoint. - * Example: "http:localhost:8888/admin/1.0.0/world-light,broadband/{z}/{x}/{y}.png" - */ - public TileSet(String tilejson, String... tiles) { - this.tilejson = tilejson; - this.tiles = tiles; - } - - public String getTilejson() { - return tilejson; - } - - public String getName() { - return name; - } - - /** - * A name describing the tileset. The name can - * contain any legal character. Implementations SHOULD NOT interpret the - * name as HTML. - * "name": "compositing", - * - * @param name the name to be set - */ - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - /** - * A text description of the tileset. The - * description can contain any legal character. - * Implementations SHOULD NOT - * interpret the description as HTML. - * "description": "A simple, light grey world." - * - * @param description the description to set - */ - public void setDescription(String description) { - this.description = description; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getAttribution() { - return attribution; - } - - /** - * Default: null. Contains an attribution to be displayed - * when the map is shown to a user. Implementations MAY decide to treat this - * as HTML or literal text. For security reasons, make absolutely sure that - * this field can't be abused as a vector for XSS or beacon tracking. - * "attribution": "OSM contributors", - * - * @param attribution the attribution to set - */ - public void setAttribution(String attribution) { - this.attribution = attribution; - } - - public String getTemplate() { - return template; - } - - /** - * Contains a mustache template to be used to - * format data from grids for interaction. - * See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 - * for the interactivity specification. - * "template": "{{#__teaser__}}{{NAME}}{{/__teaser__}}" - * - * @param template the template to set - */ - public void setTemplate(String template) { - this.template = template; - } - - public String getLegend() { - return legend; - } - - /** - * Contains a legend to be displayed with the map. - * Implementations MAY decide to treat this as HTML or literal text. - * For security reasons, make absolutely sure that this field can't be - * abused as a vector for XSS or beacon tracking. - * "legend": "Dangerous zones are red, safe zones are green" - * - * @param legend the legend to set - */ - public void setLegend(String legend) { - this.legend = legend; - } - - public String getScheme() { - return scheme; - } - - /** - * Default: "xyz". Either "xyz" or "tms". Influences the y - * direction of the tile coordinates. - * The global-mercator (aka Spherical Mercator) profile is assumed. - * "scheme": "xyz" - * - * @param scheme the scheme to set - */ - public void setScheme(String scheme) { - this.scheme = scheme; - } - - public String[] getTiles() { - return tiles; - } - - public String[] getGrids() { - return grids; - } - - /** - * An array of interactivity endpoints. {z}, {x} - * and {y}, if present, are replaced with the corresponding integers. If multiple - * endpoints are specified, clients may use any combination of endpoints. - * All endpoints MUST return the same content for the same URL. - * If the array doesn't contain any entries, interactivity is not supported - * for this tileset. See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 - * for the interactivity specification. - *

- * Example: "http:localhost:8888/admin/1.0.0/broadband/{z}/{x}/{y}.grid.json" - *

- * - * @param grids the grids to set - */ - public void setGrids(String... grids) { - this.grids = grids; - } - - public String[] getData() { - return data; - } - - /** - * An array of data files in GeoJSON format. - * {z}, {x} and {y}, if present, - * are replaced with the corresponding integers. If multiple - * endpoints are specified, clients may use any combination of endpoints. - * All endpoints MUST return the same content for the same URL. - * If the array doesn't contain any entries, then no data is present in - * the map. - *

- * "http:localhost:8888/admin/data.geojson" - *

- * - * @param data the data array to set - */ - public void setData(String... data) { - this.data = data; - } - - public float getMinZoom() { - return minZoom; - } - - /** - * 0. >= 0, < 22. An integer specifying the minimum zoom level. - * - * @param minZoom the minZoom level to set - */ - public void setMinZoom(float minZoom) { - this.minZoom = minZoom; - } - - public float getMaxZoom() { - return maxZoom; - } - - /** - * 0. >= 0, <= 22. An integer specifying the maximum zoom level. - * - * @param maxZoom the maxZoom level to set - */ - public void setMaxZoom(float maxZoom) { - this.maxZoom = maxZoom; - } - - public Float[] getBounds() { - return bounds; - } - - /** - * Default: [-180, -90, 180, 90]. The maximum extent of available map tiles. Bounds MUST define an area - * covered by all zoom levels. The bounds are represented in WGS:84 - * latitude and longitude values, in the order left, bottom, right, top. - * Values may be integers or floating point numbers. - * - * @param bounds the Float array to set - */ - public void setBounds(@Size(value = 4) Float... bounds) { - this.bounds = bounds; - } - - public String getEncoding() { - return encoding; - } - - /** - * Default: "mapbox". The encoding formula for a raster-dem tileset. - * Supported values are "mapbox" and "terrarium". - * - * @param encoding the String encoding formula to set - */ - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public Float[] getCenter() { - return center; - } - - /** - * The first value is the longitude, the second is latitude (both in - * WGS:84 values), the third value is the zoom level as an integer. - * Longitude and latitude MUST be within the specified bounds. - * The zoom level MUST be between minzoom and maxzoom. - * Implementations can use this value to set the default location. If the - * value is null, implementations may use their own algorithm for - * determining a default location. - * - * @param center the Float array to set - */ - public void setCenter(@Size(value = 2) Float... center) { - this.center = center; - } - - public void setCenter(@NonNull LatLng center) { - this.center = new Float[] {(float) center.getLongitude(), (float) center.getLatitude()}; - } - - @NonNull - Map toValueObject() { - Map result = new HashMap<>(); - result.put("tilejson", tilejson); - result.put("tiles", tiles); - - if (name != null) { - result.put("name", name); - } - if (description != null) { - result.put("description", description); - } - if (version != null) { - result.put("version", version); - } - if (attribution != null) { - result.put("attribution", attribution); - } - if (template != null) { - result.put("template", template); - } - if (legend != null) { - result.put("legend", legend); - } - if (scheme != null) { - result.put("scheme", scheme); - } - if (grids != null) { - result.put("grids", grids); - } - if (data != null) { - result.put("data", data); - } - if (minZoom != null) { - result.put("minzoom", minZoom); - } - if (maxZoom != null) { - result.put("maxzoom", maxZoom); - } - if (bounds != null) { - result.put("bounds", bounds); - } - if (center != null) { - result.put("center", center); - } - if (encoding != null) { - result.put("encoding", encoding); - } - - - return result; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.kt new file mode 100644 index 000000000..1221a1585 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.kt @@ -0,0 +1,259 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.Size +import com.mapbox.mapboxsdk.geometry.LatLng +/** + * Tile set, allows using TileJson specification as source. + * Note that `encoding` is only relevant to `raster-dem` sources, and is not supported in the TileJson spec. + * + * @see [The tileset specification](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0) + */ +class TileSet(val tilejson: String, vararg tiles: String) { + + /** + * A name describing the tileset. The name can + * contain any legal character. Implementations SHOULD NOT interpret the + * name as HTML. + * "name": "compositing", + * + * @param name the name to be set + */ + var name: String? = null + + /** + * A text description of the tileset. The + * description can contain any legal character. + * Implementations SHOULD NOT + * interpret the description as HTML. + * "description": "A simple, light grey world." + * + * @param description the description to set + */ + var description: String? = null + var version: String? = null + + /** + * Default: null. Contains an attribution to be displayed + * when the map is shown to a user. Implementations MAY decide to treat this + * as HTML or literal text. For security reasons, make absolutely sure that + * this field can't be abused as a vector for XSS or beacon tracking. + * "attribution": "[OSM contributors](http:openstreetmap.org)", + * + * @param attribution the attribution to set + */ + var attribution: String? = null + + /** + * Contains a mustache template to be used to + * format data from grids for interaction. + * See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 + * for the interactivity specification. + * "template": "{{#__teaser__}}{{NAME}}{{/__teaser__}}" + * + * @param template the template to set + */ + var template: String? = null + + /** + * Contains a legend to be displayed with the map. + * Implementations MAY decide to treat this as HTML or literal text. + * For security reasons, make absolutely sure that this field can't be + * abused as a vector for XSS or beacon tracking. + * "legend": "Dangerous zones are red, safe zones are green" + * + * @param legend the legend to set + */ + var legend: String? = null + + /** + * Default: "xyz". Either "xyz" or "tms". Influences the y + * direction of the tile coordinates. + * The global-mercator (aka Spherical Mercator) profile is assumed. + * "scheme": "xyz" + * + * @param scheme the scheme to set + */ + var scheme: String? = null + val tiles: Array + var grids: Array? = null + private set + var data: Array? = null + private set + + @JvmField + var minZoom: Float? = null + + @JvmField + var maxZoom: Float? = null + + var bounds: FloatArray? = null + private set + var center: FloatArray? = null + private set + + /** + * Default: "mapbox". The encoding formula for a raster-dem tileset. + * Supported values are "mapbox" and "terrarium". + * + * @param encoding the String encoding formula to set + */ + var encoding: String? = null + + /** + * @param tilejson A semver.org style version number. Describes the version of the TileJSON spec that is implemented + * by this JSON object. + * @param tiles An array of tile endpoints. {z}, {x} and {y}, if present, are replaced with the corresponding + * integers. + * If multiple endpoints are specified, clients may use any combination of endpoints. All endpoints + * MUST return the same + * content for the same URL. The array MUST contain at least one endpoint. + * Example: "http:localhost:8888/admin/1.0.0/world-light,broadband/{z}/{x}/{y}.png" + */ + init { + this.tiles = arrayOf(*tiles) + } + + /** + * An array of interactivity endpoints. {z}, {x} + * and {y}, if present, are replaced with the corresponding integers. If multiple + * endpoints are specified, clients may use any combination of endpoints. + * All endpoints MUST return the same content for the same URL. + * If the array doesn't contain any entries, interactivity is not supported + * for this tileset. See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 + * for the interactivity specification. + * + * + * Example: "http:localhost:8888/admin/1.0.0/broadband/{z}/{x}/{y}.grid.json" + * + * + * @param grids the grids to set + */ + fun setGrids(vararg grids: String) { + this.grids = arrayOf(*grids) + } + + /** + * An array of data files in GeoJSON format. + * {z}, {x} and {y}, if present, + * are replaced with the corresponding integers. If multiple + * endpoints are specified, clients may use any combination of endpoints. + * All endpoints MUST return the same content for the same URL. + * If the array doesn't contain any entries, then no data is present in + * the map. + * + * + * "http:localhost:8888/admin/data.geojson" + * + * + * @param data the data array to set + */ + fun setData(vararg data: String) { + this.data = arrayOf(*data) + } + + fun getMinZoom(): Float { + return minZoom!! + } + + /** + * 0. >= 0, < 22. An integer specifying the minimum zoom level. + * + * @param minZoom the minZoom level to set + */ + fun setMinZoom(minZoom: Float) { + this.minZoom = minZoom + } + + fun getMaxZoom(): Float { + return maxZoom!! + } + + /** + * 0. >= 0, <= 22. An integer specifying the maximum zoom level. + * + * @param maxZoom the maxZoom level to set + */ + fun setMaxZoom(maxZoom: Float) { + this.maxZoom = maxZoom + } + + /** + * Default: [-180, -90, 180, 90]. The maximum extent of available map tiles. Bounds MUST define an area + * covered by all zoom levels. The bounds are represented in WGS:84 + * latitude and longitude values, in the order left, bottom, right, top. + * Values may be integers or floating point numbers. + * + * @param bounds the Float array to set + */ + fun setBounds(@Size(value = 4) vararg bounds: Float) { + this.bounds = bounds + } + + /** + * The first value is the longitude, the second is latitude (both in + * WGS:84 values), the third value is the zoom level as an integer. + * Longitude and latitude MUST be within the specified bounds. + * The zoom level MUST be between minzoom and maxzoom. + * Implementations can use this value to set the default location. If the + * value is null, implementations may use their own algorithm for + * determining a default location. + * + * @param center the Float array to set + */ + fun setCenter(@Size(value = 2) vararg center: Float) { + this.center = center + } + + fun setCenter(center: LatLng) { + this.center = floatArrayOf(center.longitude.toFloat(), center.latitude.toFloat()) + } + + fun toValueObject(): Map { + val result: MutableMap = HashMap() + result["tilejson"] = tilejson + result["tiles"] = tiles + if (name != null) { + result["name"] = name!! + } + if (description != null) { + result["description"] = description!! + } + if (version != null) { + result["version"] = version!! + } + if (attribution != null) { + result["attribution"] = attribution!! + } + if (template != null) { + result["template"] = template!! + } + if (legend != null) { + result["legend"] = legend!! + } + if (scheme != null) { + result["scheme"] = scheme!! + } + if (grids != null) { + result["grids"] = grids!! + } + if (data != null) { + result["data"] = data!! + } + if (minZoom != null) { + result["minzoom"] = minZoom!! + } + if (maxZoom != null) { + result["maxzoom"] = maxZoom!! + } + if (bounds != null) { + result["bounds"] = bounds!! + } + if (center != null) { + result["center"] = center!! + } + if (encoding != null) { + result["encoding"] = encoding!! + } + return result + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.java deleted file mode 100644 index 1fc3878f9..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import androidx.annotation.Keep; -import androidx.annotation.UiThread; - -/** - * An unknown type of source - */ -@UiThread -@Keep -public class UnknownSource extends Source { - - /** - * Creates a UnknownSource. - * - * @param nativePtr pointer used by core - */ - UnknownSource(long nativePtr) { - super(nativePtr); - } - - protected native void initialize(); - - @Override - protected native void finalize() throws Throwable; - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.kt new file mode 100644 index 000000000..3b3b5206e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/UnknownSource.kt @@ -0,0 +1,21 @@ +package com.mapbox.mapboxsdk.style.sources + +import androidx.annotation.Keep +import androidx.annotation.UiThread +/** + * An unknown type of source + */ +@UiThread +@Keep +class UnknownSource +/** + * Creates a UnknownSource. + * + * @param nativePtr pointer used by core + */ +internal constructor(nativePtr: Long) : Source(nativePtr) { + protected external fun initialize() + + @Throws(Throwable::class) + protected external fun finalize() +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java deleted file mode 100644 index 6c48715c0..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.mapbox.mapboxsdk.style.sources; - -import android.net.Uri; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.Size; -import androidx.annotation.UiThread; - -import com.mapbox.geojson.Feature; -import com.mapbox.mapboxsdk.style.expressions.Expression; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Vector source, allows the use of vector tiles. - * - * @see the style specification - */ -@UiThread -public class VectorSource extends Source { - - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - @Keep - VectorSource(long nativePtr) { - super(nativePtr); - } - - /** - * Create a vector source from a remote url pointing to a TileJSON resource - * - * @param id the source id - * @param url the TileJSON resource url - * @deprecated use {@link #VectorSource(String, Uri)} instead - */ - @Deprecated - public VectorSource(String id, URL url) { - this(id, url.toExternalForm()); - } - - /** - * Create a vector source from an URI. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the TileJSON resource uri - */ - public VectorSource(String id, Uri uri) { - this(id, uri.toString()); - } - - /** - * Create a vector source from an URI. - *

- * An URI is a combination of a protocol and a resource path. - * The following URI protocol schemes are supported: - *

- *
    - *
  • http://
  • - *
      - *
    • load resources using HyperText Transfer Protocol
    • - *
    - *
  • file://
  • - *
      - *
    • load resources from the Android file system
    • - *
    - *
  • asset://
  • - *
      - *
    • load resources from the binary packaged assets folder
    • - *
    - *
- * - * @param id the source id - * @param uri the uri - */ - public VectorSource(String id, String uri) { - super(); - initialize(id, uri); - } - - /** - * Create a vector source from a tileset - * - * @param id the source id - * @param tileSet the tileset - */ - public VectorSource(String id, TileSet tileSet) { - super(); - initialize(id, tileSet.toValueObject()); - } - - /** - * Queries the source for features. - * - * @param sourceLayerIds the source layer identifiers. At least one must be specified. - * @param filter an optional filter expression to filter the returned Features - * @return the features - */ - @NonNull - public List querySourceFeatures(@Size(min = 1) String[] sourceLayerIds, - @Nullable Expression filter) { - checkThread(); - Feature[] features = querySourceFeatures( - sourceLayerIds, - filter != null ? filter.toArray() : null); - return features != null ? Arrays.asList(features) : new ArrayList(); - } - - /** - * @return The url or null - * @deprecated use {@link #getUri()} instead - */ - @Nullable - @Deprecated - public String getUrl() { - checkThread(); - return nativeGetUrl(); - } - - /** - * Get the source URI. - * - * @return The uri or null - */ - @Nullable - public String getUri() { - checkThread(); - return nativeGetUrl(); - } - - @Keep - protected native void initialize(String layerId, Object payload); - - @Override - @Keep - protected native void finalize() throws Throwable; - - @NonNull - @Keep - protected native String nativeGetUrl(); - - @NonNull - @Keep - private native Feature[] querySourceFeatures(String[] sourceLayerId, - Object[] filter); - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.kt new file mode 100644 index 000000000..8f9155eef --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.kt @@ -0,0 +1,151 @@ +package com.mapbox.mapboxsdk.style.sources + +import android.net.Uri +import androidx.annotation.Keep +import androidx.annotation.Size +import androidx.annotation.UiThread +import com.mapbox.geojson.Feature +import com.mapbox.mapboxsdk.style.expressions.Expression +import java.net.URL +import java.util.* +import kotlin.collections.ArrayList + +/** + * Vector source, allows the use of vector tiles. + * + * @see [the style specification](https://www.mapbox.com/mapbox-gl-style-spec/.sources-vector) + */ +@UiThread +class VectorSource : Source { + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + @Keep + internal constructor(nativePtr: Long) : super(nativePtr) { + } + + /** + * Create a vector source from a remote url pointing to a TileJSON resource + * + * @param id the source id + * @param url the TileJSON resource url + */ + @Deprecated("use {@link #VectorSource(String, Uri)} instead") + constructor(id: String?, url: URL) : this(id, url.toExternalForm()) { + } + + /** + * Create a vector source from an URI. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the TileJSON resource uri + */ + constructor(id: String?, uri: Uri) : this(id, uri.toString()) {} + + /** + * Create a vector source from an URI. + * + * + * An URI is a combination of a protocol and a resource path. + * The following URI protocol schemes are supported: + * + * + * * http:// + * + * * load resources using HyperText Transfer Protocol + * + * * file:// + * + * * load resources from the Android file system + * + * * asset:// + * + * * load resources from the binary packaged assets folder + * + * + * + * @param id the source id + * @param uri the uri + */ + constructor(id: String?, uri: String?) : super() { + initialize(id, uri) + } + + /** + * Create a vector source from a tileset + * + * @param id the source id + * @param tileSet the tileset + */ + constructor(id: String?, tileSet: TileSet) : super() { + initialize(id, tileSet.toValueObject()) + } + + /** + * Queries the source for features. + * + * @param sourceLayerIds the source layer identifiers. At least one must be specified. + * @param filter an optional filter expression to filter the returned Features + * @return the features + */ + fun querySourceFeatures(@Size(min = 1) sourceLayerIds: Array, filter: Expression?): List { + checkThread() + val features = querySourceFeatures(sourceLayerIds, filter?.toArray()) + return if (features != null) Arrays.asList(*features) else ArrayList() + } + + /** + * @return The url or null + */ + @get:Deprecated("use {@link #getUri()} instead") + val url: String? + get() { + checkThread() + return nativeGetUrl() + } + + /** + * Get the source URI. + * + * @return The uri or null + */ + val uri: String? + get() { + checkThread() + return nativeGetUrl() + } + + @Keep + protected external fun initialize(layerId: String?, payload: Any?) + + @Keep + @Throws(Throwable::class) + protected external fun finalize() + + @Keep + protected external fun nativeGetUrl(): String? + + @Keep + private external fun querySourceFeatures(sourceLayerId: Array, filter: Array?): Array +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java deleted file mode 100644 index a8a5739e5..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.mapbox.mapboxsdk.style.types; - -import androidx.annotation.Keep; -import androidx.annotation.Nullable; - -import java.util.Arrays; - -/** - * Represents a string broken into sections annotated with separate formatting options. - * - * @see Style specification - */ -@Keep -public class Formatted { - private final FormattedSection[] formattedSections; - - /** - * Create a new formatted text. - * - * @param formattedSections sections with formatting options - */ - public Formatted(FormattedSection... formattedSections) { - this.formattedSections = formattedSections; - } - - /** - * Returns sections with separate formatting options that are a part of this formatted text. - * - * @return formatted sections - */ - public FormattedSection[] getFormattedSections() { - return formattedSections; - } - - public Object[] toArray() { - Object[] sections = new Object[formattedSections.length]; - for (int i = 0; i < formattedSections.length; i++) { - sections[i] = formattedSections[i].toArray(); - } - return sections; - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Formatted formatted = (Formatted) o; - - return Arrays.equals(formattedSections, formatted.formattedSections); - } - - @Override - public int hashCode() { - return Arrays.hashCode(formattedSections); - } - - @Override - public String toString() { - return "Formatted{" - + "formattedSections=" - + Arrays.toString(formattedSections) - + '}'; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.kt new file mode 100644 index 000000000..5263a1b88 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.kt @@ -0,0 +1,55 @@ +package com.mapbox.mapboxsdk.style.types + +import androidx.annotation.Keep +import java.util.* + +/** + * Represents a string broken into sections annotated with separate formatting options. + * + * @see [Style specification](https://maplibre.org/maplibre-gl-js-docs/style-spec/.types-formatted) + */ +@Keep +class Formatted(vararg formattedSections: FormattedSection) { + /** + * Returns sections with separate formatting options that are a part of this formatted text. + * + * @return formatted sections + */ + val formattedSections: Array + + /** + * Create a new formatted text. + * + * @param formattedSections sections with formatting options + */ + init { + this.formattedSections = formattedSections + } + + fun toArray(): Array { + val sections = arrayOfNulls(formattedSections.size) + for (i in formattedSections.indices) { + sections[i] = formattedSections[i].toArray() + } + return sections + } + + override fun equals(o: Any?): Boolean { + if (this === o) { + return true + } + if (o == null || javaClass != o.javaClass) { + return false + } + val formatted = o as Formatted + return Arrays.equals(formattedSections, formatted.formattedSections) + } + + override fun hashCode(): Int { + return Arrays.hashCode(formattedSections) + } + + override fun toString(): String { + return ("Formatted{" + "formattedSections=" + Arrays.toString(formattedSections) + '}') + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/PackageInfo.kt similarity index 67% rename from platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/package-info.java rename to platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/PackageInfo.kt index 084ba9019..74f3ebea5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/package-info.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/PackageInfo.kt @@ -1,4 +1,4 @@ /** * Contains the Mapbox Maps Android Formatted Expression Types API classes. */ -package com.mapbox.mapboxsdk.style.types; \ No newline at end of file +package com.mapbox.mapboxsdk.style.types diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.kt index 6fe1ead9d..ae66dfade 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.kt @@ -531,7 +531,7 @@ class DataDrivenStyleActivity : AppCompatActivity() { // Add a fill layer mapboxMap.style!! .addLayer( - FillLayer(AMSTERDAM_PARKS_LAYER, source.getId()) + FillLayer(AMSTERDAM_PARKS_LAYER, source.id) .withProperties( PropertyFactory.fillColor(Expression.color(Color.GREEN)), PropertyFactory.fillOutlineColor(Expression.rgb(0, 0, 255)), diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.kt index bd333bb0a..e4a753cc5 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.kt @@ -33,26 +33,25 @@ class GridSourceActivity : AppCompatActivity(), OnMapReadyCallback { * grid. */ internal class GridProvider : GeometryTileProvider { - override fun getFeaturesForBounds(bounds: LatLngBounds, zoom: Int): FeatureCollection { + override fun getFeaturesForBounds(bounds: LatLngBounds, zoomLevel: Int): FeatureCollection { val features: MutableList = ArrayList() - val gridSpacing: Double - gridSpacing = if (zoom >= 13) { + val gridSpacing = if (zoomLevel >= 13) { 0.01 - } else if (zoom >= 11) { + } else if (zoomLevel >= 11) { 0.05 - } else if (zoom == 10) { + } else if (zoomLevel == 10) { .1 - } else if (zoom == 9) { + } else if (zoomLevel == 9) { 0.25 - } else if (zoom == 8) { + } else if (zoomLevel == 8) { 0.5 - } else if (zoom >= 6) { + } else if (zoomLevel >= 6) { 1.0 - } else if (zoom == 5) { + } else if (zoomLevel == 5) { 2.0 - } else if (zoom >= 4) { + } else if (zoomLevel >= 4) { 5.0 - } else if (zoom == 2) { + } else if (zoomLevel == 2) { 10.0 } else { 20.0 diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.kt index fd6ceb572..42eacb53e 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.kt @@ -93,11 +93,8 @@ class RealTimeGeoJsonActivity : AppCompatActivity(), OnMapReadyCallback { private val handler: Handler ) : Runnable { override fun run() { - ( - mapboxMap.style!! - .getSource(ID_GEOJSON_SOURCE) as GeoJsonSource? - )!!.url = - URL_GEOJSON_SOURCE + val geoJsonSource = mapboxMap.style!!.getSource(ID_GEOJSON_SOURCE) as GeoJsonSource + geoJsonSource.url = URL_GEOJSON_SOURCE handler.postDelayed(this, 2000) } }