From 9d99adc431483bd5b70d21376bdcf38d8a95c333 Mon Sep 17 00:00:00 2001
From: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Date: Mon, 9 Jan 2023 08:51:27 +0100
Subject: [PATCH] Port most Android TestApp utils to kotlin (#668)
---
.../mapboxsdk/testapp/MapLibreApplication.kt | 4 +-
.../activity/camera/LatLngBoundsActivity.kt | 4 +-
.../activity/offline/OfflineActivity.kt | 30 +--
.../offline/UpdateMetadataActivity.kt | 10 +-
.../mapboxsdk/testapp/utils/ApiKeyUtils.java | 39 ----
.../mapboxsdk/testapp/utils/ApiKeyUtils.kt | 34 +++
.../mapboxsdk/testapp/utils/FontCache.java | 26 ---
.../mapboxsdk/testapp/utils/FontCache.kt | 25 ++
.../mapboxsdk/testapp/utils/GeoParseUtil.java | 51 -----
.../mapboxsdk/testapp/utils/GeoParseUtil.kt | 52 +++++
.../mapboxsdk/testapp/utils/IconUtils.java | 32 ---
.../mapboxsdk/testapp/utils/IconUtils.kt | 31 +++
.../testapp/utils/IdleZoomListener.java | 26 ---
.../testapp/utils/IdleZoomListener.kt | 15 ++
.../mapboxsdk/testapp/utils/OfflineUtils.java | 37 ---
.../mapboxsdk/testapp/utils/OfflineUtils.kt | 32 +++
.../utils/TileLoadingMeasurementUtils.java | 216 ------------------
.../utils/TileLoadingMeasurementUtils.kt | 192 ++++++++++++++++
18 files changed, 408 insertions(+), 448 deletions(-)
delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.java
create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.kt
delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.kt
delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.kt
delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.java
create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.kt
delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.java
create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.kt
delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.kt
delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.java
create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.kt
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapLibreApplication.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapLibreApplication.kt
index 1c501263e..ad3155059 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapLibreApplication.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapLibreApplication.kt
@@ -57,7 +57,9 @@ class MapLibreApplication : MultiDexApplication() {
private fun initializeMapbox() {
val apiKey = ApiKeyUtils.getApiKey(applicationContext)
- validateApiKey(apiKey)
+ if (apiKey != null) {
+ validateApiKey(apiKey)
+ }
Mapbox.getInstance(applicationContext, apiKey, TILE_SERVER)
TileLoadingMeasurementUtils.setUpTileLoadingMeasurement()
MapStrictMode.setStrictModeEnabled(true)
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.kt
index 60c1cef4c..aa08b72dd 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.kt
@@ -18,7 +18,7 @@ import com.mapbox.mapboxsdk.style.layers.SymbolLayer
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
import com.mapbox.mapboxsdk.testapp.R
import com.mapbox.mapboxsdk.testapp.databinding.ActivityLatlngboundsBinding
-import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil.loadStringFromAssets
+import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil
import com.mapbox.mapboxsdk.utils.BitmapUtils
import java.net.URISyntaxException
@@ -52,7 +52,7 @@ class LatLngBoundsActivity : AppCompatActivity() {
mapboxMap = map
val featureCollection: FeatureCollection =
- fromJson(loadStringFromAssets(this, "points-sf.geojson"))
+ fromJson(GeoParseUtil.loadStringFromAssets(this, "points-sf.geojson"))
bounds = createBounds(featureCollection)
map.getCameraForLatLngBounds(bounds, createPadding(peekHeight))?.let {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.kt
index e4865d1d8..fd385f133 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.kt
@@ -209,21 +209,23 @@ class OfflineActivity : AppCompatActivity(), DownloadRegionDialogListener {
val metadata = OfflineUtils.convertRegionName(regionName)
// Create region
- offlineManager!!.createOfflineRegion(
- definition,
- metadata,
- object : CreateOfflineRegionCallback {
- override fun onCreate(offlineRegion: OfflineRegion) {
- Timber.d("Offline region created: %s", regionName)
- this@OfflineActivity.offlineRegion = offlineRegion
- launchDownload()
- }
+ if (metadata != null) {
+ offlineManager!!.createOfflineRegion(
+ definition,
+ metadata,
+ object : CreateOfflineRegionCallback {
+ override fun onCreate(offlineRegion: OfflineRegion) {
+ Timber.d("Offline region created: %s", regionName)
+ this@OfflineActivity.offlineRegion = offlineRegion
+ launchDownload()
+ }
- override fun onError(error: String) {
- Timber.e("Error: %s", error)
+ override fun onError(error: String) {
+ Timber.e("Error: %s", error)
+ }
}
- }
- )
+ )
+ }
}
private fun launchDownload() {
@@ -308,7 +310,7 @@ class OfflineActivity : AppCompatActivity(), DownloadRegionDialogListener {
companion object {
// JSON encoding/decoding
- const val JSON_CHARSET = "UTF-8"
+ val JSON_CHARSET = Charsets.UTF_8
const val JSON_FIELD_REGION_NAME = "FIELD_REGION_NAME"
// Style URL
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.kt
index 8a58424df..18fe60d84 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.kt
@@ -55,10 +55,12 @@ class UpdateMetadataActivity :
builder.setPositiveButton(
"OK"
) { dialog: DialogInterface?, which: Int ->
- updateMetadata(
- region,
- OfflineUtils.convertRegionName(input.text.toString())
- )
+ OfflineUtils.convertRegionName(input.text.toString())?.let {
+ updateMetadata(
+ region,
+ it
+ )
+ }
}
builder.setNegativeButton("Cancel") { dialog: DialogInterface, which: Int -> dialog.cancel() }
builder.show()
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.java
deleted file mode 100644
index f5ad602c4..000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-
-import com.mapbox.mapboxsdk.Mapbox;
-
-public class ApiKeyUtils {
-
- /**
- *
- * Returns the ApiKey set in the app resources.
- *
- * It will first search for a api key in the Mapbox object. If not found it
- * will then attempt to load the api key from the
- * {@code res/values/dev.xml} development file.
- *
- * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}.
- * @return The api key or null if not found.
- */
- public static String getApiKey(@NonNull Context context) {
- try {
- // Read out AndroidManifest
- String apiKey = Mapbox.getApiKey();
- if (apiKey == null || apiKey.isEmpty()) {
- throw new IllegalArgumentException();
- }
- return apiKey;
- } catch (Exception exception) {
- // Use fallback on string resource, used for development
- //TODO:PP
- int apiKeyResId = context.getResources()
- .getIdentifier("api_key", "string", context.getPackageName());
- return apiKeyResId != 0 ? context.getString(apiKeyResId) : null;
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.kt
new file mode 100644
index 000000000..07175f1f8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiKeyUtils.kt
@@ -0,0 +1,34 @@
+package com.mapbox.mapboxsdk.testapp.utils
+
+import android.content.Context
+import com.mapbox.mapboxsdk.Mapbox
+import java.lang.Exception
+
+object ApiKeyUtils {
+ /**
+ *
+ *
+ * Returns the ApiKey set in the app resources.
+ *
+ * It will first search for a api key in the Mapbox object. If not found it
+ * will then attempt to load the api key from the
+ * `res/values/dev.xml` development file.
+ *
+ * @param context The [Context] of the [android.app.Activity] or [android.app.Fragment].
+ * @return The api key or null if not found.
+ */
+ fun getApiKey(context: Context): String? {
+ return try {
+ // Read out AndroidManifest
+ val apiKey = Mapbox.getApiKey()
+ require(!(apiKey == null || apiKey.isEmpty()))
+ apiKey
+ } catch (exception: Exception) {
+ // Use fallback on string resource, used for development
+ // TODO:PP
+ val apiKeyResId = context.resources
+ .getIdentifier("api_key", "string", context.packageName)
+ if (apiKeyResId != 0) context.getString(apiKeyResId) else null
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
deleted file mode 100644
index a4352d0b1..000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.content.Context;
-import android.graphics.Typeface;
-
-import java.util.Hashtable;
-
-import timber.log.Timber;
-
-public class FontCache {
-
- private static Hashtable fontCache = new Hashtable<>();
-
- public static Typeface get(String name, Context context) {
- Typeface tf = fontCache.get(name);
- if (tf == null) {
- try {
- tf = Typeface.createFromAsset(context.getAssets(), name);
- fontCache.put(name, tf);
- } catch (Exception exception) {
- Timber.e("Font not found");
- }
- }
- return tf;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.kt
new file mode 100644
index 000000000..5a6d1e9aa
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.kt
@@ -0,0 +1,25 @@
+package com.mapbox.mapboxsdk.testapp.utils
+
+import android.content.Context
+import android.graphics.Typeface
+import timber.log.Timber
+import java.lang.Exception
+import java.util.*
+
+object FontCache {
+ private val fontCache = Hashtable()
+
+ @JvmStatic
+ operator fun get(name: String, context: Context): Typeface? {
+ var tf = fontCache[name]
+ if (tf == null) {
+ try {
+ tf = Typeface.createFromAsset(context.assets, name)
+ fontCache[name] = tf
+ } catch (exception: Exception) {
+ Timber.e("Font not found")
+ }
+ }
+ return tf
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
deleted file mode 100644
index c21e47965..000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.content.Context;
-import android.text.TextUtils;
-
-import com.mapbox.geojson.Feature;
-import com.mapbox.geojson.FeatureCollection;
-import com.mapbox.geojson.Point;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-
-public class GeoParseUtil {
-
- public static String loadStringFromAssets(final Context context, final String fileName) throws IOException {
- if (TextUtils.isEmpty(fileName)) {
- throw new NullPointerException("No GeoJSON File Name passed in.");
- }
- InputStream is = context.getAssets().open(fileName);
- BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
- return readAll(rd);
- }
-
- public static List parseGeoJsonCoordinates(String geojsonStr) {
- List latLngs = new ArrayList<>();
- FeatureCollection featureCollection = FeatureCollection.fromJson(geojsonStr);
- for (Feature feature : featureCollection.features()) {
- if (feature.geometry() instanceof Point) {
- Point point = (Point) feature.geometry();
- latLngs.add(new LatLng(point.latitude(), point.longitude()));
- }
- }
- return latLngs;
- }
-
- private static String readAll(Reader rd) throws IOException {
- StringBuilder sb = new StringBuilder();
- int cp;
- while ((cp = rd.read()) != -1) {
- sb.append((char) cp);
- }
- return sb.toString();
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.kt
new file mode 100644
index 000000000..8a1094a36
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.kt
@@ -0,0 +1,52 @@
+package com.mapbox.mapboxsdk.testapp.utils
+
+import android.content.Context
+import android.text.TextUtils
+import com.mapbox.geojson.FeatureCollection
+import com.mapbox.geojson.Point
+import com.mapbox.mapboxsdk.geometry.LatLng
+import java.io.BufferedReader
+import java.io.IOException
+import java.io.InputStreamReader
+import java.io.Reader
+import java.lang.NullPointerException
+import java.lang.StringBuilder
+import java.util.ArrayList
+import kotlin.Throws
+
+class GeoParseUtil {
+
+ companion object {
+ @Throws(IOException::class)
+ fun loadStringFromAssets(context: Context, fileName: String?): String {
+ if (TextUtils.isEmpty(fileName)) {
+ throw NullPointerException("No GeoJSON File Name passed in.")
+ }
+ val `is` = context.assets.open(fileName!!)
+ val rd = BufferedReader(InputStreamReader(`is`, Charsets.UTF_8))
+ return readAll(rd)
+ }
+
+ fun parseGeoJsonCoordinates(geojsonStr: String?): List {
+ val latLngs: MutableList = ArrayList()
+ val featureCollection = FeatureCollection.fromJson(geojsonStr!!)
+ for (feature in featureCollection.features()!!) {
+ if (feature.geometry() is Point) {
+ val point = feature.geometry() as Point?
+ latLngs.add(LatLng(point!!.latitude(), point.longitude()))
+ }
+ }
+ return latLngs
+ }
+
+ @Throws(IOException::class)
+ private fun readAll(rd: Reader): String {
+ val sb = StringBuilder()
+ var cp: Int
+ while (rd.read().also { cp = it } != -1) {
+ sb.append(cp.toChar())
+ }
+ return sb.toString()
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.java
deleted file mode 100644
index c0711d862..000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.core.content.res.ResourcesCompat;
-import androidx.core.graphics.drawable.DrawableCompat;
-
-import com.mapbox.mapboxsdk.annotations.Icon;
-import com.mapbox.mapboxsdk.annotations.IconFactory;
-
-public class IconUtils {
-
- /**
- * Demonstrates converting any Drawable to an Icon, for use as a marker icon.
- */
- public static Icon drawableToIcon(@NonNull Context context, @DrawableRes int id, @ColorInt int colorRes) {
- Drawable vectorDrawable = ResourcesCompat.getDrawable(context.getResources(), id, context.getTheme());
- Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
- vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
- DrawableCompat.setTint(vectorDrawable, colorRes);
- vectorDrawable.draw(canvas);
- return IconFactory.getInstance(context).fromBitmap(bitmap);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.kt
new file mode 100644
index 000000000..6922ad6c1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IconUtils.kt
@@ -0,0 +1,31 @@
+package com.mapbox.mapboxsdk.testapp.utils
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import androidx.annotation.ColorInt
+import androidx.annotation.DrawableRes
+import androidx.core.content.res.ResourcesCompat
+import androidx.core.graphics.drawable.DrawableCompat
+import com.mapbox.mapboxsdk.annotations.Icon
+import com.mapbox.mapboxsdk.annotations.IconFactory
+
+object IconUtils {
+ /**
+ * Demonstrates converting any Drawable to an Icon, for use as a marker icon.
+ */
+ @JvmStatic
+ fun drawableToIcon(context: Context, @DrawableRes id: Int, @ColorInt colorRes: Int): Icon {
+ val vectorDrawable = ResourcesCompat.getDrawable(context.resources, id, context.theme)
+ val bitmap = Bitmap.createBitmap(
+ vectorDrawable!!.intrinsicWidth,
+ vectorDrawable.intrinsicHeight,
+ Bitmap.Config.ARGB_8888
+ )
+ val canvas = Canvas(bitmap)
+ vectorDrawable.setBounds(0, 0, canvas.width, canvas.height)
+ DrawableCompat.setTint(vectorDrawable, colorRes)
+ vectorDrawable.draw(canvas)
+ return IconFactory.getInstance(context).fromBitmap(bitmap)
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.java
deleted file mode 100644
index 848ed2781..000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.content.Context;
-import android.widget.TextView;
-
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.R;
-
-public class IdleZoomListener implements MapboxMap.OnCameraIdleListener {
-
- private MapboxMap mapboxMap;
- private TextView textView;
-
- public IdleZoomListener(MapboxMap mapboxMap, TextView textView) {
- this.mapboxMap = mapboxMap;
- this.textView = textView;
- }
-
- @Override
- public void onCameraIdle() {
- Context context = textView.getContext();
- CameraPosition position = mapboxMap.getCameraPosition();
- textView.setText(String.format(context.getString(R.string.debug_zoom), position.zoom));
- }
-}
\ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.kt
new file mode 100644
index 000000000..f045cd9cd
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/IdleZoomListener.kt
@@ -0,0 +1,15 @@
+package com.mapbox.mapboxsdk.testapp.utils
+
+import android.widget.TextView
+import com.mapbox.mapboxsdk.maps.MapboxMap
+import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraIdleListener
+import com.mapbox.mapboxsdk.testapp.R
+
+class IdleZoomListener(private val mapboxMap: MapboxMap, private val textView: TextView) :
+ OnCameraIdleListener {
+ override fun onCameraIdle() {
+ val context = textView.context
+ val position = mapboxMap.cameraPosition
+ textView.text = String.format(context.getString(R.string.debug_zoom), position.zoom)
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
deleted file mode 100644
index 79709f59c..000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import androidx.annotation.NonNull;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-
-import timber.log.Timber;
-
-import static com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity.JSON_CHARSET;
-import static com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity.JSON_FIELD_REGION_NAME;
-
-public class OfflineUtils {
-
- public static String convertRegionName(@NonNull byte[] metadata) {
- try {
- String json = new String(metadata, JSON_CHARSET);
- JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class);
- String name = jsonObject.get(JSON_FIELD_REGION_NAME).getAsString();
- return name != null ? name : "";
- } catch (Exception exception) {
- return "";
- }
- }
-
- public static byte[] convertRegionName(String regionName) {
- try {
- JsonObject jsonObject = new JsonObject();
- jsonObject.addProperty(JSON_FIELD_REGION_NAME, regionName);
- return jsonObject.toString().getBytes(JSON_CHARSET);
- } catch (Exception exception) {
- Timber.e(exception, "Failed to encode metadata: ");
- }
- return null;
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.kt
new file mode 100644
index 000000000..57f872a68
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.kt
@@ -0,0 +1,32 @@
+package com.mapbox.mapboxsdk.testapp.utils
+
+import com.google.gson.Gson
+import com.google.gson.JsonObject
+import com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity
+import timber.log.Timber
+import java.lang.Exception
+
+object OfflineUtils {
+ fun convertRegionName(metadata: ByteArray): String {
+ return try {
+ val json = String(metadata, OfflineActivity.JSON_CHARSET)
+ val jsonObject = Gson().fromJson(json, JsonObject::class.java)
+ val name = jsonObject[OfflineActivity.JSON_FIELD_REGION_NAME].asString
+ name ?: ""
+ } catch (exception: Exception) {
+ ""
+ }
+ }
+
+ @JvmStatic
+ fun convertRegionName(regionName: String?): ByteArray? {
+ try {
+ val jsonObject = JsonObject()
+ jsonObject.addProperty(OfflineActivity.JSON_FIELD_REGION_NAME, regionName)
+ return jsonObject.toString().toByteArray(OfflineActivity.JSON_CHARSET)
+ } catch (exception: Exception) {
+ Timber.e(exception, "Failed to encode metadata: ")
+ }
+ return null
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.java
deleted file mode 100644
index 9803b0089..000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.WindowManager;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.StringDef;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import com.mapbox.mapboxsdk.MapStrictMode;
-import com.mapbox.mapboxsdk.Mapbox;
-import com.mapbox.mapboxsdk.module.http.HttpRequestUtil;
-
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-import okhttp3.Interceptor;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-import timber.log.Timber;
-
-import static com.mapbox.mapboxsdk.constants.MapboxConstants.DEFAULT_MEASURE_TILE_DOWNLOAD_ON;
-import static com.mapbox.mapboxsdk.constants.MapboxConstants.KEY_META_DATA_MEASURE_TILE_DOWNLOAD_ON;
-
-public class TileLoadingMeasurementUtils {
-
- private static final String ATTRIBUTE_REQUEST_URL = "requestUrl";
-
-
- public static void setUpTileLoadingMeasurement() {
- if (isTileLoadingMeasurementOn()) {
- OkHttpClient okHttpClient = new OkHttpClient.Builder()
- .addNetworkInterceptor(new TileLoadingInterceptor())
- .build();
- HttpRequestUtil.setOkHttpClient(okHttpClient);
- }
- }
-
- private static boolean isTileLoadingMeasurementOn() {
- return isBooleanMetaDataValueOn(KEY_META_DATA_MEASURE_TILE_DOWNLOAD_ON,
- DEFAULT_MEASURE_TILE_DOWNLOAD_ON);
- }
-
- private static boolean isBooleanMetaDataValueOn(@NonNull String propKey, boolean defaultValue) {
-
- try {
- // Try getting a custom value from the app Manifest
- Context context = Mapbox.getApplicationContext();
- ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(),
- PackageManager.GET_META_DATA);
- if (appInfo.metaData != null) {
- return appInfo.metaData.getBoolean(propKey, defaultValue);
- }
- } catch (PackageManager.NameNotFoundException exception) {
- Timber.e("Failed to read the package metadata: " + exception);
- MapStrictMode.strictModeViolation(exception);
- } catch (Exception exception) {
- Timber.e("Failed to read key: " + propKey + " " + exception);
- MapStrictMode.strictModeViolation(exception);
- }
- return defaultValue;
- }
-
-
- /**
- * This Interceptor allows to measure time spent getting a response object over network.
- * The following data will be collected:
- * responseCode, elapsedMS
- * requestUrl (request string till the question mark),
- * and device metadata.
- */
- static class TileLoadingInterceptor implements Interceptor {
-
- private static String metadata = null;
-
- @StringDef( {CONNECTION_NONE, CONNECTION_CELLULAR, CONNECTION_WIFI})
- @Retention(RetentionPolicy.SOURCE)
- @interface ConnectionState {
- }
- private static final String CONNECTION_NONE = "none";
- private static final String CONNECTION_CELLULAR = "cellular";
- private static final String CONNECTION_WIFI = "wifi";
-
- @Override
- public Response intercept(Chain chain) throws IOException {
- Request request = chain.request();
- long elapsed = System.nanoTime();
-
- Response response = chain.proceed(request);
- elapsed = System.nanoTime() - elapsed;
-
- triggerPerformanceEvent(response, elapsed / 1000000);
-
- return response;
- }
-
- private void triggerPerformanceEvent(Response response, long elapsedMs) {
- List> attributes = new ArrayList<>();
- String request = getUrl(response.request());
- attributes.add(new Attribute<>("requestUrl", request));
- attributes.add(new Attribute<>("responseCode", String.valueOf(response.code())));
- attributes.add(
- new Attribute<>("connectionState", getConnectionState()));
-
- List> counters = new ArrayList();
- counters.add(new Attribute<>("elapsedMS", elapsedMs));
-
- Bundle bundle = new Bundle();
- Gson gson = new Gson();
- bundle.putString("attributes", gson.toJson(attributes));
- bundle.putString("counters", gson.toJson(counters));
- bundle.putString("metadata", getMetadata());
- }
-
- private static String getUrl(Request request) {
- String url = request.url().toString();
- return url.substring(0, url.indexOf('?'));
- }
-
- private static String getMetadata() {
- if (metadata == null) {
- JsonObject metaData = new JsonObject();
- metaData.addProperty("os", "android");
- metaData.addProperty("manufacturer", Build.MANUFACTURER);
- metaData.addProperty("brand", Build.BRAND);
- metaData.addProperty("device", Build.MODEL);
- metaData.addProperty("version", Build.VERSION.RELEASE);
- metaData.addProperty("abi", Build.CPU_ABI);
- metaData.addProperty("country", Locale.getDefault().getISO3Country());
- metaData.addProperty("ram", getRam());
- metaData.addProperty("screenSize", getWindowSize());
-
- metadata = metaData.toString();
- }
- return metadata;
- }
-
- private static String getRam() {
- ActivityManager actManager =
- (ActivityManager) Mapbox.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
- actManager.getMemoryInfo(memInfo);
- return String.valueOf(memInfo.totalMem);
- }
-
- private static String getWindowSize() {
- WindowManager windowManager =
- (WindowManager) Mapbox.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
- Display display = windowManager.getDefaultDisplay();
- DisplayMetrics metrics = new DisplayMetrics();
- display.getMetrics(metrics);
- int width = metrics.widthPixels;
- int height = metrics.heightPixels;
- return "{" + width + "," + height + "}";
- }
-
- @ConnectionState
- private static String getConnectionState() {
- Context appContext = Mapbox.getApplicationContext();
- ConnectivityManager connectivityManager =
- (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (connectivityManager != null) {
- NetworkCapabilities capabilities =
- connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
- if (capabilities != null) {
- if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
- return CONNECTION_WIFI;
- } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- return CONNECTION_CELLULAR;
- }
- }
- }
- } else {
- if (connectivityManager != null) {
- NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
- if (activeNetwork != null) {
- if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
- return CONNECTION_WIFI;
- } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
- return CONNECTION_CELLULAR;
- }
- }
- }
- }
- return CONNECTION_NONE;
- }
- }
-
- private static class Attribute {
- private String name;
- private T value;
-
- Attribute(String name, T value) {
- this.name = name;
- this.value = value;
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.kt
new file mode 100644
index 000000000..7df2e1c5b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TileLoadingMeasurementUtils.kt
@@ -0,0 +1,192 @@
+package com.mapbox.mapboxsdk.testapp.utils
+
+import android.app.ActivityManager
+import android.content.Context
+import android.content.pm.PackageManager
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.os.Build
+import android.os.Bundle
+import android.util.DisplayMetrics
+import android.view.WindowManager
+import androidx.annotation.StringDef
+import com.google.gson.Gson
+import com.google.gson.JsonObject
+import com.mapbox.mapboxsdk.MapStrictMode
+import com.mapbox.mapboxsdk.Mapbox
+import com.mapbox.mapboxsdk.constants.MapboxConstants
+import com.mapbox.mapboxsdk.module.http.HttpRequestUtil
+import okhttp3.Interceptor
+import okhttp3.Interceptor.Chain
+import okhttp3.OkHttpClient
+import okhttp3.OkHttpClient.Builder
+import okhttp3.Request
+import okhttp3.Response
+import timber.log.Timber
+import java.io.IOException
+import java.util.*
+
+class TileLoadingMeasurementUtils {
+
+ companion object {
+
+ private const val ATTRIBUTE_REQUEST_URL = "requestUrl"
+ fun setUpTileLoadingMeasurement() {
+ if (isTileLoadingMeasurementOn) {
+ val okHttpClient: OkHttpClient = Builder()
+ .addNetworkInterceptor(TileLoadingInterceptor())
+ .build()
+ HttpRequestUtil.setOkHttpClient(okHttpClient)
+ }
+ }
+
+ private val isTileLoadingMeasurementOn: Boolean
+ private get() = isBooleanMetaDataValueOn(
+ MapboxConstants.KEY_META_DATA_MEASURE_TILE_DOWNLOAD_ON,
+ MapboxConstants.DEFAULT_MEASURE_TILE_DOWNLOAD_ON
+ )
+
+ private fun isBooleanMetaDataValueOn(propKey: String, defaultValue: Boolean): Boolean {
+ try {
+ // Try getting a custom value from the app Manifest
+ val context = Mapbox.getApplicationContext()
+ val appInfo = context.packageManager.getApplicationInfo(
+ context.packageName,
+ PackageManager.GET_META_DATA
+ )
+ if (appInfo.metaData != null) {
+ return appInfo.metaData.getBoolean(propKey, defaultValue)
+ }
+ } catch (exception: PackageManager.NameNotFoundException) {
+ Timber.e("Failed to read the package metadata: $exception")
+ MapStrictMode.strictModeViolation(exception)
+ } catch (exception: Exception) {
+ Timber.e("Failed to read key: $propKey $exception")
+ MapStrictMode.strictModeViolation(exception)
+ }
+ return defaultValue
+ }
+
+ /**
+ * This Interceptor allows to measure time spent getting a response object over network.
+ * The following data will be collected:
+ * responseCode, elapsedMS
+ * requestUrl (request string till the question mark),
+ * and device metadata.
+ */
+ internal class TileLoadingInterceptor : Interceptor {
+ @StringDef(*[CONNECTION_NONE, CONNECTION_CELLULAR, CONNECTION_WIFI])
+ @kotlin.annotation.Retention(AnnotationRetention.SOURCE)
+ internal annotation class ConnectionState
+
+ @Throws(IOException::class)
+ override fun intercept(chain: Chain): Response {
+ val request: Request = chain.request()
+ var elapsed = System.nanoTime()
+ val response: Response = chain.proceed(request)
+ elapsed = System.nanoTime() - elapsed
+ triggerPerformanceEvent(response, elapsed / 1000000)
+ return response
+ }
+
+ private fun triggerPerformanceEvent(response: Response, elapsedMs: Long) {
+ val attributes: MutableList> = ArrayList()
+ val request = getUrl(response.request)
+ attributes.add(Attribute("requestUrl", request))
+ attributes.add(Attribute("responseCode", response.code.toString()))
+ attributes.add(
+ Attribute("connectionState", connectionState)
+ )
+ val counters: MutableList?> = ArrayList()
+ counters.add(Attribute("elapsedMS", elapsedMs))
+ val bundle = Bundle()
+ val gson = Gson()
+ bundle.putString("attributes", gson.toJson(attributes))
+ bundle.putString("counters", gson.toJson(counters))
+ bundle.putString("metadata", metadata)
+ }
+
+ companion object {
+ private var metadata: String? = null
+ private get() {
+ if (field == null) {
+ val metaData = JsonObject()
+ metaData.addProperty("os", "android")
+ metaData.addProperty("manufacturer", Build.MANUFACTURER)
+ metaData.addProperty("brand", Build.BRAND)
+ metaData.addProperty("device", Build.MODEL)
+ metaData.addProperty("version", Build.VERSION.RELEASE)
+ metaData.addProperty("abi", Build.CPU_ABI)
+ metaData.addProperty("country", Locale.getDefault().isO3Country)
+ metaData.addProperty("ram", ram)
+ metaData.addProperty("screenSize", windowSize)
+ field = metaData.toString()
+ }
+ return field
+ }
+ private const val CONNECTION_NONE = "none"
+ private const val CONNECTION_CELLULAR = "cellular"
+ private const val CONNECTION_WIFI = "wifi"
+ private fun getUrl(request: Request): String {
+ val url = request.url.toString()
+ return url.substring(0, url.indexOf('?'))
+ }
+
+ private val ram: String
+ private get() {
+ val actManager = Mapbox.getApplicationContext()
+ .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ val memInfo = ActivityManager.MemoryInfo()
+ actManager.getMemoryInfo(memInfo)
+ return memInfo.totalMem.toString()
+ }
+ private val windowSize: String
+ private get() {
+ val windowManager = Mapbox.getApplicationContext()
+ .getSystemService(Context.WINDOW_SERVICE) as WindowManager
+ val display = windowManager.defaultDisplay
+ val metrics = DisplayMetrics()
+ display.getMetrics(metrics)
+ val width = metrics.widthPixels
+ val height = metrics.heightPixels
+ return "{$width,$height}"
+ }
+
+ @get:ConnectionState
+ private val connectionState: String
+ private get() {
+ val appContext = Mapbox.getApplicationContext()
+ val connectivityManager =
+ appContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (connectivityManager != null) {
+ val capabilities =
+ connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
+ if (capabilities != null) {
+ if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+ return CONNECTION_WIFI
+ } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return CONNECTION_CELLULAR
+ }
+ }
+ }
+ } else {
+ if (connectivityManager != null) {
+ val activeNetwork = connectivityManager.activeNetworkInfo
+ if (activeNetwork != null) {
+ if (activeNetwork.type == ConnectivityManager.TYPE_WIFI) {
+ return CONNECTION_WIFI
+ } else if (activeNetwork.type == ConnectivityManager.TYPE_MOBILE) {
+ return CONNECTION_CELLULAR
+ }
+ }
+ }
+ }
+ return CONNECTION_NONE
+ }
+ }
+ }
+
+ private class Attribute internal constructor(private val name: String, private val value: T)
+ }
+}