diff --git a/.gitignore b/.gitignore index 4133ad85f..5312c2ca9 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,5 @@ __generated__ cache.sqlite cache.sqlite-journal out.png +/test/android/app/.cxx +/test/android/app/build diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapFragment.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapFragment.java index 33842b6f2..9df2c8295 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapFragment.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapFragment.java @@ -1,6 +1,5 @@ package org.maplibre.android.maps; -import android.app.Fragment; import android.content.Context; import android.os.Bundle; import android.util.AttributeSet; @@ -10,6 +9,7 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import org.maplibre.android.utils.MapFragmentUtils; diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/module/http/HttpRequestImpl.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/module/http/HttpRequestImpl.java index ab365e24e..183e90e2a 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/module/http/HttpRequestImpl.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/module/http/HttpRequestImpl.java @@ -44,7 +44,7 @@ public class HttpRequestImpl implements HttpRequest { BuildConfig.MAPLIBRE_VERSION_STRING, BuildConfig.GIT_REVISION_SHORT, Build.VERSION.SDK_INT, - Build.CPU_ABI) + Build.SUPPORTED_ABIS[0]) ); @VisibleForTesting diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/CustomGeometrySource.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/CustomGeometrySource.kt index 69a656a1d..aff0ce0b6 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/CustomGeometrySource.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/CustomGeometrySource.kt @@ -9,7 +9,6 @@ import org.maplibre.android.geometry.LatLngBounds import org.maplibre.android.geometry.LatLngBounds.Companion.from import org.maplibre.android.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 @@ -19,7 +18,6 @@ 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 /** @@ -108,7 +106,7 @@ class CustomGeometrySource @UiThread constructor(id: String?, options: CustomGeo fun querySourceFeatures(filter: Expression?): List { checkThread() val features = querySourceFeatures(filter?.toArray()) - return if (features != null) Arrays.asList(*features) else ArrayList() + return listOf(*features) } @Keep @@ -246,18 +244,17 @@ class CustomGeometrySource @UiThread constructor(id: String?, options: CustomGeo internal class TileID(var z: Int, var x: Int, var y: Int) { override fun hashCode(): Int { - return Arrays.hashCode(intArrayOf(z, x, y)) + return intArrayOf(z, x, y).contentHashCode() } - override fun equals(`object`: Any?): Boolean { - if (`object` === this) { + override fun equals(other: Any?): Boolean { + if (other === this) { return true } - if (`object` == null || javaClass != `object`.javaClass) { + if (other == null || javaClass != other.javaClass) { return false } - if (`object` is TileID) { - val other = `object` + if (other is TileID) { return z == other.z && x == other.x && y == other.y } return false @@ -299,7 +296,7 @@ class CustomGeometrySource @UiThread constructor(id: String?, options: CustomGeo 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) { + if (!isCancelled() && source != null) { source.setTileData(id, data) } } @@ -324,14 +321,14 @@ class CustomGeometrySource @UiThread constructor(id: String?, options: CustomGeo return cancelled!!.get() } - override fun equals(o: Any?): Boolean { - if (this === o) { + override fun equals(other: Any?): Boolean { + if (this === other) { return true } - if (o == null || javaClass != o.javaClass) { + if (other == null || javaClass != other.javaClass) { return false } - val request = o as GeometryTileRequest + val request = other as GeometryTileRequest return id == request.id } } diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/VectorSource.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/VectorSource.kt index 8727c69a3..4293d4c84 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/VectorSource.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/VectorSource.kt @@ -112,7 +112,7 @@ class VectorSource : Source { 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 listOf(*features) } /** diff --git a/platform/android/MapLibreAndroidTestApp/build.gradle b/platform/android/MapLibreAndroidTestApp/build.gradle index 741a22aa7..550cd2890 100644 --- a/platform/android/MapLibreAndroidTestApp/build.gradle +++ b/platform/android/MapLibreAndroidTestApp/build.gradle @@ -120,7 +120,7 @@ dependencies { androidTestImplementation libs.appCenter androidTestImplementation libs.androidxTestExtJUnit androidTestImplementation libs.androidxTestCoreKtx - + androidTestImplementation libs.kotlinxCoroutinesTest } apply from: "${rootDir}/gradle/gradle-make.gradle" diff --git a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationComponentTest.kt b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationComponentTest.kt index 1ebfa8178..fc5e09765 100644 --- a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationComponentTest.kt +++ b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationComponentTest.kt @@ -192,7 +192,7 @@ class LocationComponentTest : EspressoTest() { uiController: UiController, context: Context ) { - maplibreMap.setStyle(Style.Builder().fromUrl(TestStyles.getPredefinedStyleWithFallback("Bright"))) + maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Bright"))) component.activateLocationComponent( LocationComponentActivationOptions @@ -677,7 +677,7 @@ class LocationComponentTest : EspressoTest() { component.isLocationComponentEnabled = true component.forceLocationUpdate(location) component.isLocationComponentEnabled = false - maplibreMap.setStyle(Style.Builder().fromUrl(TestStyles.getPredefinedStyleWithFallback("Bright"))) + maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Bright"))) component.isLocationComponentEnabled = true TestingAsyncUtils.waitForLayer(uiController, mapView) @@ -823,7 +823,7 @@ class LocationComponentTest : EspressoTest() { .build() ) component.isLocationComponentEnabled = true - maplibreMap.setStyle(Style.Builder().fromUrl(TestStyles.getPredefinedStyleWithFallback("Bright"))) + maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Bright"))) component.onStop() component.onStart() TestingAsyncUtils.waitForLayer(uiController, mapView) @@ -910,7 +910,7 @@ class LocationComponentTest : EspressoTest() { ) component.isLocationComponentEnabled = true component.forceLocationUpdate(location) - maplibreMap.setStyle(Style.Builder().fromUrl(TestStyles.getPredefinedStyleWithFallback("Bright"))) + maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Bright"))) component.onStop() TestingAsyncUtils.waitForLayer(uiController, mapView) component.onStart() diff --git a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationLayerControllerTest.kt b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationLayerControllerTest.kt index c4cbc54be..c472dfb34 100644 --- a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationLayerControllerTest.kt +++ b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/location/LocationLayerControllerTest.kt @@ -30,10 +30,10 @@ import org.maplibre.android.testapp.utils.TestingAsyncUtils import org.maplibre.android.utils.BitmapUtils import org.hamcrest.CoreMatchers.`is` import org.hamcrest.CoreMatchers.notNullValue +import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.After import org.junit.Assert.assertEquals -import org.junit.Assert.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test @@ -504,7 +504,7 @@ class LocationLayerControllerTest : EspressoTest() { `is`(true) ) - maplibreMap.setStyle(Style.Builder().fromUrl(TestStyles.getPredefinedStyleWithFallback("Bright"))) + maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Bright"))) TestingAsyncUtils.waitForLayer(uiController, mapView) assertThat( @@ -676,7 +676,7 @@ class LocationLayerControllerTest : EspressoTest() { assertThat( Math.abs(zoom - maplibreMap.cameraPosition.zoom) < 0.1 && Math.abs(target.latitude - maplibreMap.cameraPosition.target!!.latitude) < 0.1 && - Math.abs(target!!.longitude - maplibreMap.cameraPosition.target!!.longitude) < 0.1, + Math.abs(target.longitude - maplibreMap.cameraPosition.target!!.longitude) < 0.1, `is`(true) ) @@ -722,7 +722,7 @@ class LocationLayerControllerTest : EspressoTest() { assertThat( abs(zoom - maplibreMap.cameraPosition.zoom) < 0.1 && abs(target.latitude - maplibreMap.cameraPosition.target!!.latitude) < 0.1 && - abs(target!!.longitude - maplibreMap.cameraPosition.target!!.longitude) < 0.1, + abs(target.longitude - maplibreMap.cameraPosition.target!!.longitude) < 0.1, `is`(true) ) diff --git a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/offline/OfflineManagerTest.kt b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/offline/OfflineManagerTest.kt index 090086943..c8ebafc2d 100644 --- a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/offline/OfflineManagerTest.kt +++ b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/offline/OfflineManagerTest.kt @@ -3,6 +3,8 @@ package org.maplibre.android.testapp.offline import android.content.Context import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner import androidx.test.rule.ActivityTestRule +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest import java.io.IOException import java.util.concurrent.CountDownLatch import org.junit.After @@ -50,6 +52,7 @@ class OfflineManagerTest : AppCenter() { latch.await() } + @OptIn(ExperimentalCoroutinesApi::class) @Test(timeout = 30_000) fun combinedTest() { @@ -59,18 +62,19 @@ class OfflineManagerTest : AppCenter() { val latch1 = CountDownLatch(1) rule.activity.runOnUiThread { - FileUtils.CopyFileFromAssetsTask( - rule.activity, - object : FileUtils.OnFileCopiedFromAssetsListener { - override fun onFileCopiedFromAssets() { - latch1.countDown() - } - - override fun onError() { - throw IOException("Unable to copy DB file.") - } - } - ).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(rule.activity)) + var copied = false + runTest { + copied = FileUtils.copyFileFromAssetsTask( + rule.activity, + TEST_DB_FILE_NAME, + FileSource.getResourcesCachePath(rule.activity) + ) + } + if (copied) { + latch1.countDown() + } else { + throw IOException("Unable to copy DB file.") + } } latch1.await() diff --git a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/style/ImageTest.kt b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/style/ImageTest.kt index d540fd564..9905f2055 100644 --- a/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/style/ImageTest.kt +++ b/platform/android/MapLibreAndroidTestApp/src/androidTest/java/org/maplibre/android/testapp/style/ImageTest.kt @@ -26,7 +26,7 @@ class ImageTest : EspressoTest() { fun testAddGetImage() { validateTestSetup() MapLibreMapAction.invoke(maplibreMap) { uiController, maplibreMap -> - val drawable = rule.activity.resources.getDrawable(R.drawable.ic_launcher_round) + val drawable = rule.activity.resources.getDrawable(R.drawable.ic_launcher_round, null) assertTrue(drawable is BitmapDrawable) val bitmapSet = (drawable as BitmapDrawable).bitmap diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/FeatureOverviewActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/FeatureOverviewActivity.kt index cb0b8c337..855d6ba20 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/FeatureOverviewActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/FeatureOverviewActivity.kt @@ -5,17 +5,17 @@ import android.content.Intent import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.content.res.Resources.NotFoundException -import android.os.AsyncTask -import android.os.Build import android.os.Bundle -import android.util.Log import android.view.View -import androidx.annotation.RequiresApi import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.SimpleOnItemTouchListener +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.maplibre.android.testapp.R import org.maplibre.android.testapp.adapter.FeatureAdapter import org.maplibre.android.testapp.adapter.FeatureSectionAdapter @@ -37,7 +37,6 @@ class FeatureOverviewActivity : AppCompatActivity() { private var sectionAdapter: FeatureSectionAdapter? = null private var features: List? = null - @RequiresApi(Build.VERSION_CODES.TIRAMISU) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_feature_overview) @@ -65,22 +64,26 @@ class FeatureOverviewActivity : AppCompatActivity() { } private fun loadFeatures() { - try { - LoadFeatureTask().execute( - packageManager.getPackageInfo( - packageName, - PackageManager.GET_ACTIVITIES or PackageManager.GET_META_DATA + lifecycleScope.launch(Dispatchers.IO) { + try { + features = loadFeaturesTask( + packageManager.getPackageInfo( + packageName, + PackageManager.GET_ACTIVITIES or PackageManager.GET_META_DATA + ) ) - ) - } catch (exception: PackageManager.NameNotFoundException) { - Timber.e(exception, "Could not resolve package info") + withContext(Dispatchers.Main) { + onFeaturesLoaded(features) + } + } catch (exception: PackageManager.NameNotFoundException) { + Timber.e(exception, "Could not resolve package info") + } } } - @RequiresApi(Build.VERSION_CODES.TIRAMISU) private fun onFeaturesLoaded(featuresList: List?) { features = featuresList - if (featuresList == null || featuresList.isEmpty()) { + if (featuresList.isNullOrEmpty()) { return } val sections: MutableList = ArrayList() @@ -100,7 +103,7 @@ class FeatureOverviewActivity : AppCompatActivity() { FeatureAdapter(features!!) ) sectionAdapter!!.setSections(sections.toTypedArray()) - recyclerView!!.adapter = sectionAdapter + recyclerView.adapter = sectionAdapter } private fun startFeature(feature: Feature) { @@ -114,59 +117,52 @@ class FeatureOverviewActivity : AppCompatActivity() { outState.putParcelableArrayList(KEY_STATE_FEATURES, features as ArrayList?) } - private inner class LoadFeatureTask : AsyncTask>() { - protected override fun doInBackground(vararg p0: PackageInfo?): List? { - val features: MutableList = ArrayList() - val app = p0[0] - val packageName = FeatureOverviewActivity.javaClass.`package`.name - val metaDataKey = getString(R.string.category) - if (app != null) { - for (info in app.activities) { - if (info.labelRes != 0 && info.name.startsWith(packageName) && - info.name != FeatureOverviewActivity::class.java.name - ) { - val label = getString(info.labelRes) - val description = resolveString(info.descriptionRes) - val category = resolveMetaData(info.metaData, metaDataKey) - features.add(Feature(info.name, label, description, category!!)) - } + private fun loadFeaturesTask(vararg p0: PackageInfo?): List { + val features: MutableList = ArrayList() + val app = p0[0] + val packageName = FeatureOverviewActivity::class.java.`package`!!.name + val metaDataKey = getString(R.string.category) + if (app != null) { + for (info in app.activities) { + if (info.labelRes != 0 && info.name.startsWith(packageName) && + info.name != FeatureOverviewActivity::class.java.name + ) { + val label = getString(info.labelRes) + val description = resolveString(info.descriptionRes) + val category = resolveMetaData(info.metaData, metaDataKey) + features.add(Feature(info.name, label, description, category!!)) } } - if (!features.isEmpty()) { - val comparator = Comparator { lhs: Feature, rhs: Feature -> - var result = lhs.category.compareTo(rhs.category, ignoreCase = true) - if (result == 0) { - result = lhs.getLabel().compareTo(rhs.getLabel(), ignoreCase = true) - } - result + } + if (features.isNotEmpty()) { + val comparator = Comparator { lhs: Feature, rhs: Feature -> + var result = lhs.category.compareTo(rhs.category, ignoreCase = true) + if (result == 0) { + result = lhs.getLabel().compareTo(rhs.getLabel(), ignoreCase = true) } - Collections.sort(features, comparator) + result } - return features + Collections.sort(features, comparator) } + return features + } - private fun resolveMetaData(bundle: Bundle?, key: String): String? { - var category: String? = null - if (bundle != null) { - category = bundle.getString(key) - } - return category + private fun resolveMetaData(bundle: Bundle?, key: String): String? { + var category: String? = null + if (bundle != null) { + category = bundle.getString(key) } + return category + } - private fun resolveString(@StringRes stringRes: Int): String { - return try { - getString(stringRes) - } catch (exception: NotFoundException) { - "-" - } - } - - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - override fun onPostExecute(features: List) { - super.onPostExecute(features) - onFeaturesLoaded(features) + private fun resolveString(@StringRes stringRes: Int): String { + return try { + getString(stringRes) + } catch (exception: NotFoundException) { + "-" } } + companion object { private const val KEY_STATE_FEATURES = "featureList" } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/BulkMarkerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/BulkMarkerActivity.kt index 12efb441f..30d842dba 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/BulkMarkerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/BulkMarkerActivity.kt @@ -1,7 +1,6 @@ package org.maplibre.android.testapp.activity.annotation import android.app.ProgressDialog -import android.os.AsyncTask import android.os.Bundle import android.view.Menu import android.view.View @@ -10,20 +9,22 @@ import android.widget.AdapterView.OnItemSelectedListener import android.widget.ArrayAdapter import android.widget.Spinner import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.MenuItemCompat +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.maplibre.android.annotations.MarkerOptions import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.testapp.R import org.maplibre.android.testapp.styles.TestStyles import org.maplibre.android.testapp.utils.GeoParseUtil import timber.log.Timber import java.io.IOException -import java.lang.ref.WeakReference import java.text.DecimalFormat import java.util.* +import kotlin.math.min /** * Test activity showcasing adding a large amount of Markers. @@ -38,7 +39,7 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { setContentView(R.layout.activity_marker_bulk) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync(OnMapReadyCallback { maplibreMap: MapLibreMap -> initMap(maplibreMap) }) + mapView.getMapAsync { initMap(it) } } private fun initMap(maplibreMap: MapLibreMap) { @@ -55,7 +56,7 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) menuInflater.inflate(R.menu.menu_bulk_marker, menu) val item = menu.findItem(R.id.spinner) - val spinner = MenuItemCompat.getActionView(item) as Spinner + val spinner = item.actionView as Spinner spinner.adapter = spinnerAdapter spinner.onItemSelectedListener = this@BulkMarkerActivity return true @@ -65,7 +66,12 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { val amount = Integer.valueOf(resources.getStringArray(R.array.bulk_marker_list)[position]) if (locations == null) { progressDialog = ProgressDialog.show(this, "Loading", "Fetching markers", false) - LoadLocationTask(this, amount).execute() + lifecycleScope.launch(Dispatchers.IO) { + locations = loadLocationTask(this@BulkMarkerActivity) + withContext(Dispatchers.Main) { + onLatLngListLoaded(locations, amount) + } + } } else { showMarkers(amount) } @@ -78,15 +84,11 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { } private fun showMarkers(amount: Int) { - var amount = amount - if (maplibreMap == null || locations == null || mapView.isDestroyed) { + if (!this::maplibreMap.isInitialized || locations == null || mapView.isDestroyed) { return } maplibreMap.clear() - if (locations!!.size < amount) { - amount = locations!!.size - } - showGlMarkers(amount) + showGlMarkers(min(amount, locations!!.size)) } private fun showGlMarkers(amount: Int) { @@ -149,38 +151,18 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { mapView.onLowMemory() } - private class LoadLocationTask constructor( + private fun loadLocationTask( activity: BulkMarkerActivity, - private val amount: Int - ) : AsyncTask?>() { - private val activity: WeakReference - override fun doInBackground(vararg p0: Void?): List? { - val activity = activity.get() - if (activity != null) { - var json: String? = null - try { - json = GeoParseUtil.loadStringFromAssets( - activity.applicationContext, - "points.geojson" - ) - } catch (exception: IOException) { - Timber.e(exception, "Could not add markers") - } - if (json != null) { - return GeoParseUtil.parseGeoJsonCoordinates(json) - } - } - return null - } - - override fun onPostExecute(locations: List?) { - super.onPostExecute(locations) - val activity = activity.get() - activity?.onLatLngListLoaded(locations, amount) - } - - init { - this.activity = WeakReference(activity) + ) : List? { + try { + val json = GeoParseUtil.loadStringFromAssets( + activity.applicationContext, + "points.geojson" + ) + return GeoParseUtil.parseGeoJsonCoordinates(json) + } catch (exception: IOException) { + Timber.e(exception, "Could not add markers") } + return null } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/DynamicMarkerChangeActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/DynamicMarkerChangeActivity.kt index a671fe12e..7552abe5b 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/DynamicMarkerChangeActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/DynamicMarkerChangeActivity.kt @@ -1,7 +1,6 @@ package org.maplibre.android.testapp.activity.annotation import android.os.Bundle -import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat @@ -30,9 +29,9 @@ class DynamicMarkerChangeActivity : AppCompatActivity() { mapView.setTag(false) mapView.onCreate(savedInstanceState) mapView.getMapAsync( - OnMapReadyCallback { maplibreMap: MapLibreMap -> - maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) - this@DynamicMarkerChangeActivity.maplibreMap = maplibreMap + OnMapReadyCallback { map: MapLibreMap -> + map.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) + maplibreMap = map // Create marker val markerOptions = MarkerOptions() .position(LAT_LNG_CHELSEA) @@ -45,14 +44,12 @@ class DynamicMarkerChangeActivity : AppCompatActivity() { ) .title(getString(R.string.dynamic_marker_chelsea_title)) .snippet(getString(R.string.dynamic_marker_chelsea_snippet)) - marker = maplibreMap.addMarker(markerOptions) + marker = map.addMarker(markerOptions) } ) val fab = findViewById(R.id.fab) fab.setColorFilter(ContextCompat.getColor(this, R.color.primary)) - fab.setOnClickListener { view: View? -> - updateMarker() - } + fab.setOnClickListener { updateMarker() } } private fun updateMarker() { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/JsonApiActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/JsonApiActivity.kt index a9d904043..848503309 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/JsonApiActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/JsonApiActivity.kt @@ -103,7 +103,7 @@ class JsonApiActivity : AppCompatActivity() { // Intentionally specify package name // This makes copy from another project easier org.maplibre.android.R.drawable.maplibre_info_icon_default, - null + theme )!! val bitmapBlue = infoIconDrawable.toBitmap() val bitmapRed = infoIconDrawable diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PolylineActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PolylineActivity.kt index a61c63794..781bb7990 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PolylineActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PolylineActivity.kt @@ -12,7 +12,6 @@ import org.maplibre.android.annotations.PolylineOptions import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.testapp.R import org.maplibre.android.testapp.styles.TestStyles import java.util.* @@ -33,6 +32,7 @@ class PolylineActivity : AppCompatActivity() { private var showPolylines = true private var width = true private var color = true + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_polyline) @@ -43,23 +43,21 @@ class PolylineActivity : AppCompatActivity() { } mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { maplibreMap: MapLibreMap -> - this@PolylineActivity.maplibreMap = maplibreMap - maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Satellite Hybrid")) - maplibreMap.setOnPolylineClickListener { polyline: Polyline -> - Toast.makeText( - this@PolylineActivity, - "You clicked on polyline with id = " + polyline.id, - Toast.LENGTH_SHORT - ).show() - } - polylines = maplibreMap.addPolylines(polylineOptions!!) + mapView.getMapAsync { + maplibreMap = it + it.setStyle(TestStyles.getPredefinedStyleWithFallback("Satellite Hybrid")) + it.setOnPolylineClickListener { polyline: Polyline -> + Toast.makeText( + this@PolylineActivity, + "You clicked on polyline with id = " + polyline.id, + Toast.LENGTH_SHORT + ).show() } - ) + polylines = it.addPolylines(polylineOptions!!) + } val fab = findViewById(R.id.fab) - fab?.setOnClickListener { view: View? -> - if (maplibreMap != null) { + fab?.setOnClickListener { + if (this::maplibreMap.isInitialized) { if (polylines != null && polylines!!.size > 0) { if (polylines!!.size == 1) { // test for removing annotation @@ -70,14 +68,14 @@ class PolylineActivity : AppCompatActivity() { } } polylineOptions!!.clear() - polylineOptions!!.addAll(randomLine) + polylineOptions!!.add(allPolylines.random()) polylines = maplibreMap.addPolylines(polylineOptions!!) } } } private val allPolylines: List - private get() { + get() { val options: MutableList = ArrayList() options.add(generatePolyline(ANDORRA, LUXEMBOURG, "#F44336")) options.add(generatePolyline(ANDORRA, MONACO, "#FF5722")) @@ -96,17 +94,6 @@ class PolylineActivity : AppCompatActivity() { return line } - val randomLine: List - get() { - val randomLines = allPolylines - Collections.shuffle(randomLines) - return object : ArrayList() { - init { - add(randomLines[0]) - } - } - } - override fun onStart() { super.onStart() mapView.onStart() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PressForMarkerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PressForMarkerActivity.kt index 2c0addea1..acc92833f 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PressForMarkerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/annotation/PressForMarkerActivity.kt @@ -25,6 +25,7 @@ class PressForMarkerActivity : AppCompatActivity() { private lateinit var mapView: MapView private lateinit var maplibreMap: MapLibreMap private var markerList: ArrayList? = ArrayList() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_press_for_marker) @@ -45,7 +46,7 @@ class PressForMarkerActivity : AppCompatActivity() { } maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) if (savedInstanceState != null) { - markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST) + markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST, MarkerOptions::class.java) if (markerList != null) { maplibreMap.addMarkers(markerList!!) } @@ -69,11 +70,10 @@ class PressForMarkerActivity : AppCompatActivity() { } private fun resetMap() { - if (maplibreMap == null) { - return + if (this::maplibreMap.isInitialized) { + markerList?.clear() + maplibreMap.removeAnnotations() } - markerList!!.clear() - maplibreMap.removeAnnotations() } override fun onCreateOptionsMenu(menu: Menu): Boolean { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/benchmark/BenchmarkActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/benchmark/BenchmarkActivity.kt index d88a55774..4ac306b43 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/benchmark/BenchmarkActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/benchmark/BenchmarkActivity.kt @@ -36,8 +36,6 @@ import org.maplibre.android.testapp.utils.BenchmarkResults import org.maplibre.android.testapp.utils.FrameTimeStore import java.io.File -import java.util.* - data class BenchmarkInputData( val styleNames: List, val styleURLs: List, @@ -120,18 +118,6 @@ class BenchmarkActivity : AppCompatActivity() { // ``` private lateinit var inputData: BenchmarkInputData - @SuppressLint("DiscouragedApi") - private fun getStringFromResources(name: String): String { - return try { - resources.getString(applicationContext.resources.getIdentifier( - name, - "string", - applicationContext.packageName)) - } catch (e: Throwable) { - "" - } - } - @SuppressLint("DiscouragedApi") private fun getArrayFromResources(name: String): Array { return try { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt index 73e184d0b..739eeafc6 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt @@ -50,7 +50,7 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback { private lateinit var mapView: MapView private var cameraState = false private val cameraIdleListener = OnCameraIdleListener { - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { Timber.w(maplibreMap.cameraPosition.toString()) } } @@ -114,7 +114,7 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback { } private val nextLatLng: LatLng - private get() { + get() { cameraState = !cameraState return if (cameraState) LAT_LNG_TOWER_BRIDGE else LAT_LNG_LONDON_EYE } @@ -146,7 +146,7 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback { override fun onDestroy() { super.onDestroy() - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.removeOnCameraIdleListener(cameraIdleListener) } mapView.onDestroy() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimatorActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimatorActivity.kt index f8db4bfc1..e2b31edab 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimatorActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimatorActivity.kt @@ -208,7 +208,7 @@ class CameraAnimatorActivity : AppCompatActivity(), OnMapReadyCallback { for (i in 0 until animators.size()) { animators[animators.keyAt(i)]!!.cancel() } - if (set != null) { + if (this::set.isInitialized) { set.cancel() } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/GestureDetectorActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/GestureDetectorActivity.kt index 5c184a065..14648af0e 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/GestureDetectorActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/GestureDetectorActivity.kt @@ -4,7 +4,11 @@ import android.annotation.SuppressLint import android.os.Bundle import android.os.Handler import android.os.Looper -import android.view.* +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup import android.widget.RelativeLayout import android.widget.TextView import androidx.annotation.ColorInt @@ -13,21 +17,26 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.mapbox.android.gestures.* +import com.mapbox.android.gestures.AndroidGesturesManager +import com.mapbox.android.gestures.MoveGestureDetector +import com.mapbox.android.gestures.RotateGestureDetector +import com.mapbox.android.gestures.ShoveGestureDetector +import com.mapbox.android.gestures.StandardScaleGestureDetector import org.maplibre.android.annotations.Marker import org.maplibre.android.annotations.MarkerOptions import org.maplibre.android.camera.CameraUpdateFactory import org.maplibre.android.geometry.LatLng -import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.MapLibreMap.* -import org.maplibre.android.maps.OnMapReadyCallback +import org.maplibre.android.maps.MapLibreMap.CancelableCallback +import org.maplibre.android.maps.MapLibreMap.OnMoveListener +import org.maplibre.android.maps.MapLibreMap.OnRotateListener +import org.maplibre.android.maps.MapLibreMap.OnScaleListener +import org.maplibre.android.maps.MapLibreMap.OnShoveListener +import org.maplibre.android.maps.MapView import org.maplibre.android.testapp.R import org.maplibre.android.testapp.styles.TestStyles import org.maplibre.android.testapp.utils.FontCache import org.maplibre.android.testapp.utils.ResourceUtils -import java.lang.annotation.Retention -import java.lang.annotation.RetentionPolicy /** Test activity showcasing APIs around gestures implementation. */ class GestureDetectorActivity : AppCompatActivity() { @@ -43,13 +52,11 @@ class GestureDetectorActivity : AppCompatActivity() { setContentView(R.layout.activity_gesture_detector) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { maplibreMap: MapLibreMap -> - this@GestureDetectorActivity.maplibreMap = maplibreMap - maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) - initializeMap() - } - ) + mapView.getMapAsync { map: MapLibreMap -> + maplibreMap = map + maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) + initializeMap() + } recyclerView = findViewById(R.id.alerts_recycler) recyclerView.setLayoutManager(LinearLayoutManager(this)) gestureAlertsAdapter = GestureAlertsAdapter() @@ -94,10 +101,10 @@ class GestureDetectorActivity : AppCompatActivity() { private fun initializeMap() { gesturesManager = maplibreMap.gesturesManager - val layoutParams = recyclerView!!.layoutParams as RelativeLayout.LayoutParams + val layoutParams = recyclerView.layoutParams as RelativeLayout.LayoutParams layoutParams.height = (mapView.height / 1.75).toInt() layoutParams.width = mapView.width / 3 - recyclerView!!.layoutParams = layoutParams + recyclerView.layoutParams = layoutParams attachListeners() fixedFocalPointEnabled(maplibreMap.uiSettings.focalPoint != null) } @@ -313,8 +320,6 @@ class GestureDetectorActivity : AppCompatActivity() { class ViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) { var alertMessageTv: TextView - @ColorInt var textColor = 0 - init { val typeface = FontCache.get("Roboto-Regular.ttf", view.context) alertMessageTv = view.findViewById(R.id.alert_message) @@ -371,25 +376,24 @@ class GestureDetectorActivity : AppCompatActivity() { } } - private class GestureAlert - internal constructor( + private class GestureAlert( @field:Type @param:Type val alertType: Int, val message: String? ) { - @Retention(RetentionPolicy.SOURCE) + @Retention(AnnotationRetention.SOURCE) @IntDef(TYPE_NONE, TYPE_START, TYPE_PROGRESS, TYPE_END, TYPE_OTHER) - internal annotation class Type + annotation class Type @ColorInt var color = 0 - override fun equals(o: Any?): Boolean { - if (this === o) { + override fun equals(other: Any?): Boolean { + if (this === other) { return true } - if (o == null || javaClass != o.javaClass) { + if (other == null || javaClass != other.javaClass) { return false } - val that = o as GestureAlert + val that = other as GestureAlert if (alertType != that.alertType) { return false } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/LatLngBoundsActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/LatLngBoundsActivity.kt index 434c1d677..e5b07a40f 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/LatLngBoundsActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/LatLngBoundsActivity.kt @@ -99,7 +99,7 @@ class LatLngBoundsActivity : AppCompatActivity() { private fun initBottomSheet() { bottomSheetBehavior = BottomSheetBehavior.from(binding.bottomSheet) - bottomSheetBehavior.setBottomSheetCallback( + bottomSheetBehavior.addBottomSheetCallback( object : BottomSheetBehavior.BottomSheetCallback() { override fun onSlide(bottomSheet: View, slideOffset: Float) { val offset = convertSlideOffset(slideOffset) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/MaxMinZoomActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/MaxMinZoomActivity.kt index a261b1fdd..897c59a53 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/MaxMinZoomActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/MaxMinZoomActivity.kt @@ -3,7 +3,6 @@ package org.maplibre.android.testapp.activity.camera import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import org.maplibre.android.maps.MapView -import org.maplibre.android.maps.MapView.OnDidFinishLoadingStyleListener import org.maplibre.android.maps.MapLibreMap import org.maplibre.android.maps.MapLibreMap.OnMapClickListener import org.maplibre.android.maps.OnMapReadyCallback @@ -17,7 +16,7 @@ class MaxMinZoomActivity : AppCompatActivity(), OnMapReadyCallback { private lateinit var mapView: MapView private lateinit var maplibreMap: MapLibreMap private val clickListener = OnMapClickListener { - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Outdoor"))) } true @@ -26,12 +25,10 @@ class MaxMinZoomActivity : AppCompatActivity(), OnMapReadyCallback { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_maxmin_zoom) - mapView = findViewById(R.id.mapView) + mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) mapView.getMapAsync(this) - mapView.addOnDidFinishLoadingStyleListener( - OnDidFinishLoadingStyleListener { Timber.d("Style Loaded") } - ) + mapView.addOnDidFinishLoadingStyleListener { Timber.d("Style Loaded") } } override fun onMapReady(map: MapLibreMap) { @@ -69,7 +66,7 @@ class MaxMinZoomActivity : AppCompatActivity(), OnMapReadyCallback { override fun onDestroy() { super.onDestroy() - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.removeOnMapClickListener(clickListener) } mapView.onDestroy() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ScrollByActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ScrollByActivity.kt index 0b5883638..6da5ca7cb 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ScrollByActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ScrollByActivity.kt @@ -46,7 +46,7 @@ class ScrollByActivity : AppCompatActivity(), OnMapReadyCallback { PixelBarChangeListener(textViewY, R.string.scrollby_y_value) ) mapView = findViewById(R.id.mapView) - mapView.setTag(true) + mapView.tag = true mapView.onCreate(savedInstanceState) mapView.getMapAsync(this) } @@ -59,10 +59,10 @@ class ScrollByActivity : AppCompatActivity(), OnMapReadyCallback { uiSettings.isAttributionEnabled = false val fab = findViewById(R.id.fab) fab.setColorFilter(ContextCompat.getColor(this@ScrollByActivity, R.color.primary)) - fab.setOnClickListener { view: View? -> + fab.setOnClickListener { _: View? -> maplibreMap.scrollBy( - (seekBarX!!.progress * MULTIPLIER_PER_PIXEL).toFloat(), - (seekBarY!!.progress * MULTIPLIER_PER_PIXEL).toFloat() + (seekBarX.progress * MULTIPLIER_PER_PIXEL).toFloat(), + (seekBarY.progress * MULTIPLIER_PER_PIXEL).toFloat() ) } } @@ -105,15 +105,14 @@ class ScrollByActivity : AppCompatActivity(), OnMapReadyCallback { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { - onBackPressed() + onBackPressedDispatcher.onBackPressed() true } else -> super.onOptionsItemSelected(item) } } - private class PixelBarChangeListener - internal constructor( + private class PixelBarChangeListener( private val valueView: TextView, @field:StringRes @param:StringRes private val prefixTextResource: Int diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/customlayer/CustomLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/customlayer/CustomLayerActivity.kt index 7bdffa06b..229f96d9b 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/customlayer/CustomLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/customlayer/CustomLayerActivity.kt @@ -11,7 +11,6 @@ import org.maplibre.android.camera.CameraUpdateFactory import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.style.layers.CustomLayer import org.maplibre.android.testapp.R @@ -35,30 +34,26 @@ class CustomLayerActivity : AppCompatActivity() { setContentView(R.layout.activity_custom_layer) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap? -> - maplibreMap = map!! - maplibreMap.moveCamera( - CameraUpdateFactory.newLatLngZoom( - LatLng(39.91448, -243.60947), - 10.0 - ) + mapView.getMapAsync { map: MapLibreMap -> + maplibreMap = map + maplibreMap.moveCamera( + CameraUpdateFactory.newLatLngZoom( + LatLng(39.91448, -243.60947), + 10.0 ) - maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style? -> initFab() } - } - ) + ) + maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { _: Style? -> initFab() } + } } private fun initFab() { fab = findViewById(R.id.fab) fab.setColorFilter(ContextCompat.getColor(this, R.color.primary)) - fab.setOnClickListener( - View.OnClickListener { view: View? -> - if (maplibreMap != null) { - swapCustomLayer() - } + fab.setOnClickListener { _: View? -> + if (this::maplibreMap.isInitialized) { + swapCustomLayer() } - ) + } } private fun swapCustomLayer() { @@ -66,19 +61,19 @@ class CustomLayerActivity : AppCompatActivity() { if (customLayer != null) { style!!.removeLayer(customLayer!!) customLayer = null - fab!!.setImageResource(R.drawable.ic_layers) + fab.setImageResource(R.drawable.ic_layers) } else { customLayer = CustomLayer( "custom", ExampleCustomLayer.createContext() ) style!!.addLayerBelow(customLayer!!, "building") - fab!!.setImageResource(R.drawable.ic_layers_clear) + fab.setImageResource(R.drawable.ic_layers_clear) } } private fun updateLayer() { - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.triggerRepaint() } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.kt index 5ee9b0617..b52e8fbd3 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.view.MenuItem import android.view.View import android.widget.Toast +import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import org.maplibre.geojson.Feature import org.maplibre.android.maps.MapView @@ -26,6 +27,13 @@ class QueryRenderedFeaturesBoxCountActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + // activity uses singleInstance for testing purposes + // code below provides a default navigation when using the app + NavUtils.navigateHome(this@QueryRenderedFeaturesBoxCountActivity) + } + }) setContentView(R.layout.activity_query_features_box) val selectionBox = findViewById(R.id.selection_box) @@ -35,7 +43,7 @@ class QueryRenderedFeaturesBoxCountActivity : AppCompatActivity() { mapView.getMapAsync { maplibreMap: MapLibreMap -> this@QueryRenderedFeaturesBoxCountActivity.maplibreMap = maplibreMap maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.AMERICANA)) - selectionBox.setOnClickListener { view: View? -> + selectionBox.setOnClickListener { _: View? -> // Query val top = selectionBox.top - mapView.top val left = selectionBox.left - mapView.left @@ -132,16 +140,10 @@ class QueryRenderedFeaturesBoxCountActivity : AppCompatActivity() { android.R.id.home -> { // activity uses singleInstance for testing purposes // code below provides a default navigation when using the app - onBackPressed() + NavUtils.navigateHome(this) return true } } return super.onOptionsItemSelected(item) } - - override fun onBackPressed() { - // activity uses singleInstance for testing purposes - // code below provides a default navigation when using the app - NavUtils.navigateHome(this) - } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.kt index 7307eb088..0786577cf 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.kt @@ -161,7 +161,7 @@ class QueryRenderedFeaturesPropertiesActivity : AppCompatActivity() { override fun onDestroy() { super.onDestroy() - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.removeOnMapClickListener(mapClickListener) } mapView.onDestroy() @@ -172,7 +172,7 @@ class QueryRenderedFeaturesPropertiesActivity : AppCompatActivity() { mapView.onLowMemory() } - private class CustomMarker internal constructor( + private class CustomMarker constructor( baseMarkerOptions: BaseMarkerOptions<*, *>?, val features: List? ) : Marker(baseMarkerOptions) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/FragmentBackStackActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/FragmentBackStackActivity.kt index 136e18b6b..92a2fdd42 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/FragmentBackStackActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/FragmentBackStackActivity.kt @@ -1,6 +1,7 @@ package org.maplibre.android.testapp.activity.fragment import android.os.Bundle +import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import org.maplibre.android.maps.MapLibreMap import org.maplibre.android.maps.SupportMapFragment @@ -26,6 +27,18 @@ class FragmentBackStackActivity : AppCompatActivity() { binding = ActivityBackstackFragmentBinding.inflate(layoutInflater) setContentView(binding.root) + onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + if (supportFragmentManager.backStackEntryCount == 0) { + // activity uses singleInstance for testing purposes + // code below provides a default navigation when using the app + NavUtils.navigateHome(this@FragmentBackStackActivity) + } else { + finish() + } + } + }) + if (savedInstanceState == null) { mapFragment = SupportMapFragment.newInstance() mapFragment.getMapAsync { initMap(it) } @@ -61,14 +74,4 @@ class FragmentBackStackActivity : AppCompatActivity() { addToBackStack("map_empty_fragment") }.commit() } - - override fun onBackPressed() { - if (supportFragmentManager.backStackEntryCount == 0) { - // activity uses singleInstance for testing purposes - // code below provides a default navigation when using the app - NavUtils.navigateHome(this) - } else { - super.onBackPressed() - } - } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/MapFragmentActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/MapFragmentActivity.kt index dd6dbb41b..37280a32f 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/MapFragmentActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/MapFragmentActivity.kt @@ -32,12 +32,12 @@ class MapFragmentActivity : val mapFragment: MapFragment if (savedInstanceState == null) { mapFragment = MapFragment.newInstance(createFragmentOptions()) - fragmentManager + supportFragmentManager .beginTransaction() .add(R.id.fragment_container, mapFragment, TAG) .commit() } else { - mapFragment = fragmentManager.findFragmentByTag(TAG) as MapFragment + mapFragment = supportFragmentManager.findFragmentByTag(TAG) as MapFragment } mapFragment.getMapAsync(this) } @@ -73,13 +73,13 @@ class MapFragmentActivity : override fun onDestroy() { super.onDestroy() - if (mapView != null) { + if (this::mapView.isInitialized) { mapView.removeOnDidFinishRenderingFrameListener(this) } } override fun onDidFinishRenderingFrame(fully: Boolean, frameEncodingTime: Double, frameRenderingTime: Double) { - if (initialCameraAnimation && fully && maplibreMap != null) { + if (initialCameraAnimation && fully && this::maplibreMap.isInitialized) { maplibreMap.animateCamera( CameraUpdateFactory.newCameraPosition(CameraPosition.Builder().tilt(45.0).build()), 5000 diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/NestedViewPagerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/NestedViewPagerActivity.kt index a36880fe1..284a66443 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/NestedViewPagerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/NestedViewPagerActivity.kt @@ -8,6 +8,8 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentStatePagerAdapter import org.maplibre.android.camera.CameraPosition import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapLibreMapOptions @@ -99,7 +101,7 @@ class NestedViewPagerActivity : AppCompatActivity() { } } - class MapPagerAdapter(private val context: Context, fm: androidx.fragment.app.FragmentManager) : androidx.fragment.app.FragmentStatePagerAdapter(fm) { + class MapPagerAdapter(private val context: Context, fm: FragmentManager) : FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { override fun getItem(position: Int): androidx.fragment.app.Fragment { val options = MapLibreMapOptions.createFromAttributes(context) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/SupportMapFragmentActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/SupportMapFragmentActivity.kt index f2c412175..e4e88ccbf 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/SupportMapFragmentActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/SupportMapFragmentActivity.kt @@ -77,7 +77,7 @@ class SupportMapFragmentActivity : } override fun onDidFinishRenderingFrame(fully: Boolean, frameEncodingTime: Double, frameRenderingTime: Double) { - if (initialCameraAnimation && fully && maplibreMap != null) { + if (initialCameraAnimation && fully && this::maplibreMap.isInitialized) { maplibreMap.animateCamera( CameraUpdateFactory.newCameraPosition(CameraPosition.Builder().tilt(45.0).build()), 5000 diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/ViewPagerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/ViewPagerActivity.kt index f994e10f6..73d307b35 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/ViewPagerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/fragment/ViewPagerActivity.kt @@ -3,6 +3,8 @@ package org.maplibre.android.testapp.activity.fragment import android.content.Context import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentStatePagerAdapter import org.maplibre.android.camera.CameraPosition import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapLibreMapOptions @@ -38,7 +40,7 @@ class ViewPagerActivity : AppCompatActivity() { } } - internal class MapFragmentAdapter(private val context: Context, fragmentManager: androidx.fragment.app.FragmentManager) : androidx.fragment.app.FragmentStatePagerAdapter(fragmentManager) { + internal class MapFragmentAdapter(private val context: Context, fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) { override fun getCount(): Int { return NUM_ITEMS diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/imagegenerator/PrintActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/imagegenerator/PrintActivity.kt index 07e22a03f..db7653be0 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/imagegenerator/PrintActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/imagegenerator/PrintActivity.kt @@ -7,12 +7,11 @@ import androidx.appcompat.app.AppCompatActivity import androidx.print.PrintHelper import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.testapp.R import org.maplibre.android.testapp.styles.TestStyles /** - * Test activity showcasing using the Snaphot API to print a Map. + * Test activity showcasing using the Snapshot API to print a Map. */ class PrintActivity : AppCompatActivity(), MapLibreMap.SnapshotReadyCallback { private lateinit var mapView: MapView @@ -22,10 +21,10 @@ class PrintActivity : AppCompatActivity(), MapLibreMap.SnapshotReadyCallback { setContentView(R.layout.activity_print) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync(OnMapReadyCallback { maplibreMap: MapLibreMap -> initMap(maplibreMap) }) + mapView.getMapAsync(this::initMap) val fab = findViewById(R.id.fab) - fab?.setOnClickListener { view: View? -> - if (maplibreMap != null && maplibreMap.style != null) { + fab?.setOnClickListener { _: View? -> + if (this::maplibreMap.isInitialized && maplibreMap.style != null) { maplibreMap.snapshot(this@PrintActivity) } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.kt index 16bc191db..08326abbb 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.kt @@ -61,13 +61,13 @@ class DynamicInfoWindowAdapterActivity : AppCompatActivity(), OnMapReadyCallback map.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) // Add info window adapter - addCustomInfoWindowAdapter(maplibreMap!!) + addCustomInfoWindowAdapter(maplibreMap) // Keep info windows open on click maplibreMap.uiSettings.isDeselectMarkersOnTap = false // Add a marker - marker = addMarker(maplibreMap!!) + marker = addMarker(maplibreMap) maplibreMap.selectMarker(marker!!) // On map click, change the info window contents @@ -130,7 +130,7 @@ class DynamicInfoWindowAdapterActivity : AppCompatActivity(), OnMapReadyCallback override fun onDestroy() { super.onDestroy() - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.removeOnMapClickListener(mapClickListener) } mapView.onDestroy() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/InfoWindowActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/InfoWindowActivity.kt index be2ec258a..8b998860c 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/InfoWindowActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/infowindow/InfoWindowActivity.kt @@ -164,7 +164,7 @@ class InfoWindowActivity : override fun onDestroy() { super.onDestroy() - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.removeOnMapLongClickListener(mapLongClickListener) } mapView.onDestroy() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/BasicLocationPulsingCircleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/BasicLocationPulsingCircleActivity.kt index 9c50878ed..b655c7bdd 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/BasicLocationPulsingCircleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/BasicLocationPulsingCircleActivity.kt @@ -32,12 +32,13 @@ class BasicLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyCallba private var permissionsManager: PermissionsManager? = null private var locationComponent: LocationComponent? = null private lateinit var maplibreMap: MapLibreMap + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_location_layer_basic_pulsing_circle) mapView = findViewById(R.id.mapView) if (savedInstanceState != null) { - lastLocation = savedInstanceState.getParcelable(SAVED_STATE_LOCATION) + lastLocation = savedInstanceState.getParcelable(SAVED_STATE_LOCATION, Location::class.java) } mapView.onCreate(savedInstanceState) checkPermissions() @@ -94,35 +95,41 @@ class BasicLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyCallba return super.onOptionsItemSelected(item) } val id = item.itemId - if (id == R.id.action_map_style_change) { - loadNewStyle() - return true - } else if (id == R.id.action_component_disable) { - locationComponent!!.isLocationComponentEnabled = false - return true - } else if (id == R.id.action_component_enabled) { - locationComponent!!.isLocationComponentEnabled = true - return true - } else if (id == R.id.action_stop_pulsing) { - locationComponent!!.applyStyle( - LocationComponentOptions.builder( - this@BasicLocationPulsingCircleActivity + when (id) { + R.id.action_map_style_change -> { + loadNewStyle() + return true + } + R.id.action_component_disable -> { + locationComponent!!.isLocationComponentEnabled = false + return true + } + R.id.action_component_enabled -> { + locationComponent!!.isLocationComponentEnabled = true + return true + } + R.id.action_stop_pulsing -> { + locationComponent!!.applyStyle( + LocationComponentOptions.builder( + this@BasicLocationPulsingCircleActivity + ) + .pulseEnabled(false) + .build() ) - .pulseEnabled(false) - .build() - ) - return true - } else if (id == R.id.action_start_pulsing) { - locationComponent!!.applyStyle( - LocationComponentOptions.builder( - this@BasicLocationPulsingCircleActivity + return true + } + R.id.action_start_pulsing -> { + locationComponent!!.applyStyle( + LocationComponentOptions.builder( + this@BasicLocationPulsingCircleActivity + ) + .pulseEnabled(true) + .build() ) - .pulseEnabled(true) - .build() - ) - return true + return true + } + else -> return super.onOptionsItemSelected(item) } - return super.onOptionsItemSelected(item) } private fun loadNewStyle() { @@ -206,6 +213,5 @@ class BasicLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyCallba companion object { private const val SAVED_STATE_LOCATION = "saved_state_location" - private const val TAG = "Mbgl-BasicLocationPulsingCircleActivity" } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/CustomizedLocationPulsingCircleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/CustomizedLocationPulsingCircleActivity.kt index fddc1c535..c63ee8aa7 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/CustomizedLocationPulsingCircleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/CustomizedLocationPulsingCircleActivity.kt @@ -43,6 +43,8 @@ class CustomizedLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyC private var currentPulseDuration = 0f //endregion + + @SuppressLint("SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_location_layer_customized_pulsing_circle) @@ -58,12 +60,7 @@ class CustomizedLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyC ) } pulsingCircleDurationButton = findViewById(R.id.button_location_circle_duration) - pulsingCircleDurationButton.setText( - String.format( - "%sms", - LOCATION_CIRCLE_PULSE_DURATION.toString() - ) - ) + pulsingCircleDurationButton.text = "${LOCATION_CIRCLE_PULSE_DURATION}ms" pulsingCircleDurationButton.setOnClickListener( View.OnClickListener setOnClickListener@{ v: View? -> if (locationComponent == null) { @@ -165,36 +162,42 @@ class CustomizedLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyC return super.onOptionsItemSelected(item) } val id = item.itemId - if (id == R.id.action_map_style_change) { - loadNewStyle() - return true - } else if (id == R.id.action_component_disable) { - locationComponent!!.isLocationComponentEnabled = false - return true - } else if (id == R.id.action_component_enabled) { - locationComponent!!.isLocationComponentEnabled = true - return true - } else if (id == R.id.action_stop_pulsing) { - locationComponent!!.applyStyle( - LocationComponentOptions.builder( - this@CustomizedLocationPulsingCircleActivity + when (id) { + R.id.action_map_style_change -> { + loadNewStyle() + return true + } + R.id.action_component_disable -> { + locationComponent!!.isLocationComponentEnabled = false + return true + } + R.id.action_component_enabled -> { + locationComponent!!.isLocationComponentEnabled = true + return true + } + R.id.action_stop_pulsing -> { + locationComponent!!.applyStyle( + LocationComponentOptions.builder( + this@CustomizedLocationPulsingCircleActivity + ) + .pulseEnabled(false) + .build() ) - .pulseEnabled(false) - .build() - ) - return true - } else if (id == R.id.action_start_pulsing) { - locationComponent!!.applyStyle( - buildLocationComponentOptions( - LOCATION_CIRCLE_PULSE_COLOR, - LOCATION_CIRCLE_PULSE_DURATION + return true + } + R.id.action_start_pulsing -> { + locationComponent!!.applyStyle( + buildLocationComponentOptions( + LOCATION_CIRCLE_PULSE_COLOR, + LOCATION_CIRCLE_PULSE_DURATION + ) + .pulseEnabled(true) + .build() ) - .pulseEnabled(true) - .build() - ) - return true + return true + } + else -> return super.onOptionsItemSelected(item) } - return super.onOptionsItemSelected(item) } private fun loadNewStyle() { @@ -241,7 +244,7 @@ class CustomizedLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyC listPopup.anchorView = pulsingCircleDurationButton listPopup.setOnItemClickListener { parent: AdapterView<*>?, itemView: View?, position: Int, id: Long -> val selectedMode = modes[position] - pulsingCircleDurationButton!!.text = selectedMode + pulsingCircleDurationButton.text = selectedMode if (selectedMode.contentEquals( String.format( "%sms", @@ -300,7 +303,7 @@ class CustomizedLocationPulsingCircleActivity : AppCompatActivity(), OnMapReadyC listPopup.anchorView = pulsingCircleColorButton listPopup.setOnItemClickListener { parent: AdapterView<*>?, itemView: View?, position: Int, id: Long -> val selectedTrackingType = trackingTypes[position] - pulsingCircleColorButton!!.text = selectedTrackingType + pulsingCircleColorButton.text = selectedTrackingType if (selectedTrackingType.contentEquals("Blue")) { LOCATION_CIRCLE_PULSE_COLOR = Color.BLUE setNewLocationComponentOptions(currentPulseDuration, Color.BLUE) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationFragmentActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationFragmentActivity.kt index ccfd73952..079c362b9 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationFragmentActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationFragmentActivity.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment import org.maplibre.android.camera.CameraUpdateFactory import org.maplibre.android.geometry.LatLng import org.maplibre.android.location.LocationComponentActivationOptions @@ -41,7 +42,7 @@ class LocationFragmentActivity : AppCompatActivity() { .addToBackStack("transaction2") .commit() } else { - this.onBackPressed() + finish() } } supportActionBar?.setDisplayHomeAsUpEnabled(true) @@ -85,7 +86,7 @@ class LocationFragmentActivity : AppCompatActivity() { permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults) } - class LocationFragment : androidx.fragment.app.Fragment(), LocationEngineCallback { + class LocationFragment : Fragment(), LocationEngineCallback { companion object { const val TAG = "LFragment" fun newInstance(): LocationFragment { @@ -167,7 +168,7 @@ class LocationFragmentActivity : AppCompatActivity() { } } - class EmptyFragment : androidx.fragment.app.Fragment() { + class EmptyFragment : Fragment() { companion object { const val TAG = "EmptyFragment" fun newInstance(): EmptyFragment { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationMapChangeActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationMapChangeActivity.kt index 1aca985dd..b71946861 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationMapChangeActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationMapChangeActivity.kt @@ -26,7 +26,7 @@ class LocationMapChangeActivity : AppCompatActivity(), OnMapReadyCallback { mapView = findViewById(R.id.mapView) val stylesFab = findViewById(R.id.fabStyles) stylesFab.setOnClickListener { v: View? -> - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.setStyle(Style.Builder().fromUri(Utils.nextStyle())) } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationModesActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationModesActivity.kt index ade37ecae..b4996cbd1 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationModesActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/location/LocationModesActivity.kt @@ -54,6 +54,7 @@ class LocationModesActivity : @RenderMode.Mode private var renderMode = RenderMode.NORMAL private var lastLocation: Location? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_location_layer_mode) @@ -80,7 +81,7 @@ class LocationModesActivity : if (savedInstanceState != null) { cameraMode = savedInstanceState.getInt(SAVED_STATE_CAMERA) renderMode = savedInstanceState.getInt(SAVED_STATE_RENDER) - lastLocation = savedInstanceState.getParcelable(SAVED_STATE_LOCATION) + lastLocation = savedInstanceState.getParcelable(SAVED_STATE_LOCATION, Location::class.java) } mapView.onCreate(savedInstanceState) if (PermissionsManager.areLocationPermissionsGranted(this)) { @@ -230,9 +231,7 @@ class LocationModesActivity : if (defaultStyle) R.style.maplibre_LocationComponent else R.style.CustomLocationComponent ) if (defaultStyle) { - val padding: IntArray - padding = - if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { + val padding: IntArray = if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { intArrayOf(0, 750, 0, 0) } else { intArrayOf(0, 250, 0, 0) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/BottomSheetActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/BottomSheetActivity.kt index aa2984260..261f0943f 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/BottomSheetActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/BottomSheetActivity.kt @@ -4,6 +4,7 @@ import android.content.Context import android.os.Bundle import android.view.* import android.widget.Toast +import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -13,6 +14,8 @@ import org.maplibre.android.maps.* import org.maplibre.android.testapp.R import org.maplibre.android.testapp.styles.TestStyles import org.maplibre.android.utils.MapFragmentUtils +import kotlin.math.max +import kotlin.math.min /** * Test activity showcasing using a bottomView with a MapView and stacking map fragments below. @@ -22,6 +25,16 @@ class BottomSheetActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bottom_sheet) + onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + val fragmentManager = supportFragmentManager + if (fragmentManager.backStackEntryCount > 0) { + fragmentManager.popBackStack() + } else { + finish() + } + } + }) val actionBar = supportActionBar actionBar?.setDisplayHomeAsUpEnabled(true) findViewById(R.id.fabFragment).setOnClickListener { v: View? -> addMapFragment() } @@ -35,20 +48,11 @@ class BottomSheetActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == android.R.id.home) { - onBackPressed() + onBackPressedDispatcher.onBackPressed() } return super.onOptionsItemSelected(item) } - override fun onBackPressed() { - val fragmentManager = supportFragmentManager - if (fragmentManager.backStackEntryCount > 0) { - fragmentManager.popBackStack() - } else { - super.onBackPressed() - } - } - private fun addMapFragment() { val fragmentManager = supportFragmentManager val fragmentCount = fragmentManager.backStackEntryCount @@ -124,8 +128,8 @@ class BottomSheetActivity : AppCompatActivity() { maplibreMap.setStyle( Style.Builder().fromUri( STYLES[ - Math.min( - Math.max(arguments!!.getInt("mapcounter"), 0), + min( + max(requireArguments().getInt("mapcounter"), 0), STYLES.size - 1 ) ] diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/DebugModeActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/DebugModeActivity.kt index 79d7b8bbd..0690fdcb1 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/DebugModeActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/DebugModeActivity.kt @@ -61,7 +61,7 @@ open class DebugModeActivity : AppCompatActivity(), OnMapReadyCallback, OnFpsCha mapView = MapView(this, maplibreMapOptions) (findViewById(R.id.coordinator_layout) as ViewGroup).addView(mapView, 0) mapView.addOnDidFinishLoadingStyleListener { - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { setupNavigationView(maplibreMap.style!!.layers) } } @@ -137,7 +137,7 @@ open class DebugModeActivity : AppCompatActivity(), OnMapReadyCallback, OnFpsCha private fun setupDebugChangeView() { val fabDebug = findViewById(R.id.fabDebug) fabDebug.setOnClickListener { view: View? -> - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.isDebugActive = !maplibreMap.isDebugActive Timber.d("Debug FAB: isDebug Active? %s", maplibreMap.isDebugActive) } @@ -147,7 +147,7 @@ open class DebugModeActivity : AppCompatActivity(), OnMapReadyCallback, OnFpsCha private fun setupStyleChangeView() { val fabStyles = findViewById(R.id.fabStyles) fabStyles.setOnClickListener { view: View? -> - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { currentStyleIndex++ if (currentStyleIndex == STYLES.size) { currentStyleIndex = 0 @@ -205,7 +205,7 @@ open class DebugModeActivity : AppCompatActivity(), OnMapReadyCallback, OnFpsCha override fun onDestroy() { super.onDestroy() - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.removeOnCameraMoveListener(cameraMoveListener!!) } mapView.onDestroy() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt index 3839526dc..9a4827ba6 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt @@ -7,7 +7,6 @@ import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import org.maplibre.android.maps.MapView -import org.maplibre.android.maps.Style import org.maplibre.android.testapp.R import org.maplibre.android.testapp.databinding.ActivityRecyclerviewBinding @@ -49,7 +48,7 @@ open class GLSurfaceRecyclerViewActivity : AppCompatActivity() { class ItemAdapter(private val activity: GLSurfaceRecyclerViewActivity, private val inflater: LayoutInflater) : androidx.recyclerview.widget.RecyclerView.Adapter() { - private val items = listOf( + private val items: List = listOf( "one", "two", "three", "four", "five", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty-one" diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapInDialogActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapInDialogActivity.kt index 11ddf9f2b..86e26c715 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapInDialogActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapInDialogActivity.kt @@ -40,13 +40,11 @@ class MapInDialogActivity : AppCompatActivity() { super.onViewCreated(view, savedInstanceState) mapView = view.findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { maplibreMap: MapLibreMap -> - maplibreMap.setStyle( - TestStyles.getPredefinedStyleWithFallback("Outdoor") - ) - } - ) + mapView.getMapAsync { + it.setStyle( + TestStyles.getPredefinedStyleWithFallback("Outdoor") + ) + } } override fun onStart() { @@ -76,14 +74,14 @@ class MapInDialogActivity : AppCompatActivity() { override fun onLowMemory() { super.onLowMemory() - if (mapView != null) { + if (this::mapView.isInitialized) { mapView.onLowMemory() } } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - if (mapView != null) { + if (this::mapView.isInitialized) { mapView.onSaveInstanceState(outState) } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapPaddingActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapPaddingActivity.kt index e03952550..e6ea32aa1 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapPaddingActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/MapPaddingActivity.kt @@ -24,22 +24,20 @@ class MapPaddingActivity : AppCompatActivity() { mapView = findViewById(R.id.mapView) mapView.setTag(true) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { maplibreMap: MapLibreMap -> - this@MapPaddingActivity.maplibreMap = maplibreMap - maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) - val paddingLeft = resources.getDimension(R.dimen.map_padding_left).toInt() - val paddingBottom = resources.getDimension(R.dimen.map_padding_bottom).toInt() - val paddingRight = resources.getDimension(R.dimen.map_padding_right).toInt() - val paddingTop = resources.getDimension(R.dimen.map_padding_top).toInt() - maplibreMap.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom) - val settings = maplibreMap.uiSettings - settings.setLogoMargins(paddingLeft, 0, 0, paddingBottom) - settings.setCompassMargins(0, paddingTop, paddingRight, 0) - settings.isAttributionEnabled = false - moveToBangalore() - } - ) + mapView.getMapAsync { + maplibreMap = it + it.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) + val paddingLeft = resources.getDimension(R.dimen.map_padding_left).toInt() + val paddingBottom = resources.getDimension(R.dimen.map_padding_bottom).toInt() + val paddingRight = resources.getDimension(R.dimen.map_padding_right).toInt() + val paddingTop = resources.getDimension(R.dimen.map_padding_top).toInt() + it.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom) + val settings = it.uiSettings + settings.setLogoMargins(paddingLeft, 0, 0, paddingBottom) + settings.setCompassMargins(0, paddingTop, paddingRight, 0) + settings.isAttributionEnabled = false + moveToBangalore() + } } override fun onStart() { @@ -97,7 +95,7 @@ class MapPaddingActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.action_bangalore -> { - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { moveToBangalore() } true diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt index 2728fafd3..8afad9bf9 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt @@ -2,6 +2,7 @@ package org.maplibre.android.testapp.activity.maplayout import android.os.Bundle import android.view.MenuItem +import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import org.maplibre.android.maps.* import org.maplibre.android.testapp.R @@ -15,23 +16,30 @@ class SimpleMapActivity : AppCompatActivity() { private lateinit var mapView: MapView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + onBackPressedDispatcher.addCallback(this, object: OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + // activity uses singleInstance for testing purposes + // code below provides a default navigation when using the app + NavUtils.navigateHome(this@SimpleMapActivity) + } + }) setContentView(R.layout.activity_map_simple) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { maplibreMap: MapLibreMap -> - var key = ApiKeyUtils.getApiKey(applicationContext) - if (key == null || key == "YOUR_API_KEY_GOES_HERE") { - maplibreMap.setStyle(Style.Builder().fromUri("https://demotiles.maplibre.org/style.json")) - } else { - val styles = Style.getPredefinedStyles() - if (styles != null && styles.size > 0) { - val styleUrl = styles[0].url - maplibreMap.setStyle(Style.Builder().fromUri(styleUrl)) - } + mapView.getMapAsync { + val key = ApiKeyUtils.getApiKey(applicationContext) + if (key == null || key == "YOUR_API_KEY_GOES_HERE") { + it.setStyle( + Style.Builder().fromUri("https://demotiles.maplibre.org/style.json") + ) + } else { + val styles = Style.getPredefinedStyles() + if (styles.isNotEmpty()) { + val styleUrl = styles[0].url + it.setStyle(Style.Builder().fromUri(styleUrl)) } } - ) + } } override fun onStart() { @@ -74,16 +82,10 @@ class SimpleMapActivity : AppCompatActivity() { android.R.id.home -> { // activity uses singleInstance for testing purposes // code below provides a default navigation when using the app - onBackPressed() + onBackPressedDispatcher.onBackPressed() return true } } return super.onOptionsItemSelected(item) } - - override fun onBackPressed() { - // activity uses singleInstance for testing purposes - // code below provides a default navigation when using the app - NavUtils.navigateHome(this) - } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/MergeOfflineRegionsActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/MergeOfflineRegionsActivity.kt index a22b78417..d248e679a 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/MergeOfflineRegionsActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/MergeOfflineRegionsActivity.kt @@ -3,6 +3,10 @@ package org.maplibre.android.testapp.activity.offline import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.maplibre.android.MapLibre import org.maplibre.android.log.Logger import org.maplibre.android.maps.Style @@ -12,6 +16,7 @@ import org.maplibre.android.storage.FileSource import org.maplibre.android.testapp.databinding.ActivityMergeOfflineRegionsBinding import org.maplibre.android.testapp.styles.TestStyles import org.maplibre.android.testapp.utils.FileUtils +import java.util.Locale class MergeOfflineRegionsActivity : AppCompatActivity() { @@ -23,25 +28,6 @@ class MergeOfflineRegionsActivity : AppCompatActivity() { private var TEST_STYLE = TestStyles.getPredefinedStyleWithFallback("Satellite Hybrid") } - private val onFileCopiedListener = object : FileUtils.OnFileCopiedFromAssetsListener { - override fun onFileCopiedFromAssets() { - Toast.makeText( - this@MergeOfflineRegionsActivity, - String.format("OnFileCopied."), - Toast.LENGTH_LONG - ).show() - mergeDb() - } - - override fun onError() { - Toast.makeText( - this@MergeOfflineRegionsActivity, - String.format("Error copying DB file."), - Toast.LENGTH_LONG - ).show() - } - } - private val onRegionMergedListener = object : OfflineManager.MergeOfflineRegionsCallback { override fun onMerge(offlineRegions: Array?) { binding.mapView.getMapAsync { @@ -49,7 +35,7 @@ class MergeOfflineRegionsActivity : AppCompatActivity() { } Toast.makeText( this@MergeOfflineRegionsActivity, - String.format("Merged %d regions.", offlineRegions?.size ?: 0), + String.format(Locale.ENGLISH, "Merged %d regions.", offlineRegions?.size ?: 0), Toast.LENGTH_LONG ).show() } @@ -105,7 +91,29 @@ class MergeOfflineRegionsActivity : AppCompatActivity() { private fun copyAsset() { // copy db asset to internal memory - FileUtils.CopyFileFromAssetsTask(this, onFileCopiedListener).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(this)) + lifecycleScope.launch(Dispatchers.IO) { + val copied = FileUtils.copyFileFromAssetsTask( + this@MergeOfflineRegionsActivity, + TEST_DB_FILE_NAME, + FileSource.getResourcesCachePath(this@MergeOfflineRegionsActivity) + ) + withContext(Dispatchers.Main) { + if (copied) { + Toast.makeText( + this@MergeOfflineRegionsActivity, + String.format("OnFileCopied."), + Toast.LENGTH_LONG + ).show() + mergeDb() + } else { + Toast.makeText( + this@MergeOfflineRegionsActivity, + String.format("Error copying DB file."), + Toast.LENGTH_LONG + ).show() + } + } + } } private fun mergeDb() { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/UpdateMetadataActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/UpdateMetadataActivity.kt index 71b4670e3..cec016fd6 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/UpdateMetadataActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/offline/UpdateMetadataActivity.kt @@ -47,7 +47,7 @@ class UpdateMetadataActivity : val input = EditText(this) input.setText(metadata) input.inputType = InputType.TYPE_CLASS_TEXT - if (metadata != null) { + if (metadata.isNotEmpty()) { input.setSelection(metadata.length) } builder.setView(input) @@ -113,7 +113,7 @@ class UpdateMetadataActivity : OfflineManager.getInstance(this).listOfflineRegions(object : ListOfflineRegionsCallback { override fun onList(offlineRegions: Array?) { if (offlineRegions != null && offlineRegions.size > 0) { - adapter!!.setOfflineRegions(Arrays.asList(*offlineRegions)) + adapter!!.setOfflineRegions(listOf(*offlineRegions)) } } @@ -129,7 +129,7 @@ class UpdateMetadataActivity : override fun onDestroy() { super.onDestroy() - if (mapView != null) { + if (this::mapView.isInitialized) { mapView.onPause() mapView.onStop() mapView.onDestroy() @@ -172,7 +172,7 @@ class UpdateMetadataActivity : return convertView!! } - internal class ViewHolder { + class ViewHolder { var text: TextView? = null } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/render/RenderTestActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/render/RenderTestActivity.kt index fdf8fb125..959dd48a3 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/render/RenderTestActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/render/RenderTestActivity.kt @@ -2,7 +2,6 @@ package org.maplibre.android.testapp.activity.render import android.content.res.AssetManager import android.graphics.Bitmap -import android.os.AsyncTask import android.os.Bundle import android.os.Environment import android.view.Gravity @@ -10,8 +9,12 @@ import android.view.ViewGroup import android.widget.FrameLayout import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import com.google.gson.Gson import com.google.gson.JsonObject +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.maplibre.android.snapshotter.MapSnapshot import org.maplibre.android.snapshotter.MapSnapshotter import okio.buffer @@ -20,7 +23,6 @@ import timber.log.Timber import java.io.File import java.io.FileOutputStream import java.io.IOException -import java.lang.ref.WeakReference import java.nio.charset.Charset /** @@ -50,91 +52,58 @@ class RenderTestActivity : AppCompatActivity() { // // Loads the ignore tests from assets folder // - private class LoadRenderIgnoreTask internal constructor(renderTestActivity: RenderTestActivity?) : - AsyncTask>() { - private val renderTestActivityWeakReference: WeakReference - protected override fun doInBackground(vararg p0: Void?): List? { - return loadIgnoreList( - renderTestActivityWeakReference.get()!!.assets - ) - } - - override fun onPostExecute(strings: List) { - super.onPostExecute(strings) - if (renderTestActivityWeakReference.get() != null) { - renderTestActivityWeakReference.get()!!.onLoadIgnoreList(strings) - } - } - - init { - renderTestActivityWeakReference = WeakReference(renderTestActivity) - } - } + private fun loadRenderIgnoreTask(renderTestActivity: RenderTestActivity) : List = loadIgnoreList(renderTestActivity.assets) // // Loads the render test definitions from assets folder // - private class LoadRenderDefinitionTask internal constructor(renderTestActivity: RenderTestActivity) : - AsyncTask>() { - private val renderTestActivityWeakReference: WeakReference - protected override fun doInBackground(vararg p0: Void?): List? { - val definitions: MutableList = ArrayList() - val assetManager = renderTestActivityWeakReference.get()!!.assets - val categories = - try { - assetManager.list(RENDER_TEST_BASE_PATH) - } catch (exception: IOException) { - Timber.e(exception) - throw exception - } + private fun loadRenderDefinitionTask(renderTestActivity: RenderTestActivity) : List { + val definitions: MutableList = ArrayList() + val assetManager = renderTestActivity.assets + val categories = + try { + assetManager.list(RENDER_TEST_BASE_PATH) + } catch (exception: IOException) { + Timber.e(exception) + throw exception + } - for (counter in categories!!.indices.reversed()) { - try { - val tests = assetManager.list( - String.format( - "%s/%s", - RENDER_TEST_BASE_PATH, + for (counter in categories!!.indices.reversed()) { + try { + val tests = assetManager.list( + String.format( + "%s/%s", + RENDER_TEST_BASE_PATH, + categories[counter] + ) + ) + for (test in tests!!) { + val styleJson = loadStyleJson(assetManager, categories[counter], test) + val renderTestStyleDefinition = Gson() + .fromJson(styleJson, RenderTestStyleDefinition::class.java) + val definition = RenderTestDefinition( + categories[counter], + test, + styleJson, + renderTestStyleDefinition + ) + if (!definition.hasOperations()) { + if (!EXCLUDED_TESTS.contains(definition.name + "," + definition.category)) { + definitions.add(definition) + } + } else { + Timber.e( + "could not add test, test requires operations: %s from %s", + test, categories[counter] ) - ) - for (test in tests!!) { - val styleJson = loadStyleJson(assetManager, categories[counter], test) - val renderTestStyleDefinition = Gson() - .fromJson(styleJson, RenderTestStyleDefinition::class.java) - val definition = RenderTestDefinition( - categories[counter], - test, - styleJson, - renderTestStyleDefinition - ) - if (!definition.hasOperations()) { - if (!EXCLUDED_TESTS.contains(definition.name + "," + definition.category)) { - definitions.add(definition) - } - } else { - Timber.e( - "could not add test, test requires operations: %s from %s", - test, - categories[counter] - ) - } } - } catch (exception: Exception) { - Timber.e(exception) } + } catch (exception: Exception) { + Timber.e(exception) } - return definitions - } - - override fun onPostExecute(renderTestDefinitions: List) { - super.onPostExecute(renderTestDefinitions) - val renderTestActivity = renderTestActivityWeakReference.get() - renderTestActivity?.startRenderTests(renderTestDefinitions) - } - - init { - renderTestActivityWeakReference = WeakReference(renderTestActivity) } + return definitions } private fun startRenderTests(renderTestDefinitions: List) { @@ -177,53 +146,49 @@ class RenderTestActivity : AppCompatActivity() { } private fun finishTesting() { - SaveResultToDiskTask(onRenderTestCompletionListener, renderResultMap).execute() + lifecycleScope.launch(Dispatchers.IO) { + saveResultToDiskTask(renderResultMap) + withContext(Dispatchers.Main) { + onRenderTestCompletionListener?.onFinish() + } + } } // // Save tests results to disk // - private class SaveResultToDiskTask internal constructor( - private val onRenderTestCompletionListener: OnRenderTestCompletionListener?, - private val renderResultMap: Map - ) : AsyncTask() { - protected override fun doInBackground(vararg p0: Void?): Void? { - if (isExternalStorageWritable) { - try { - val testResultDir = FileUtils.createTestResultRootFolder() - val basePath = testResultDir.absolutePath - for (testResult in renderResultMap.entries) { - writeResultToDisk(basePath, testResult) - } - } catch (exception: Exception) { - Timber.e(exception) + private fun saveResultToDiskTask( + renderResultMap: Map + ) { + if (isExternalStorageWritable) { + try { + val testResultDir = FileUtils.createTestResultRootFolder() + val basePath = testResultDir.absolutePath + for (testResult in renderResultMap.entries) { + writeResultToDisk(basePath, testResult) } + } catch (exception: Exception) { + Timber.e(exception) } - return null - } - - private fun writeResultToDisk( - path: String, - result: Map.Entry - ) { - val definition = result.key - val categoryName = definition.category - val categoryPath = String.format("%s/%s", path, categoryName) - FileUtils.createCategoryDirectory(categoryPath) - val testName = result.key.name - val testDir = FileUtils.createTestDirectory(categoryPath, testName) - FileUtils.writeTestResultToDisk(testDir, result.value) - } - - private val isExternalStorageWritable: Boolean - private get() = Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() - - override fun onPostExecute(aVoid: Void?) { - super.onPostExecute(aVoid) - onRenderTestCompletionListener?.onFinish() } } + private fun writeResultToDisk( + path: String, + result: Map.Entry + ) { + val definition = result.key + val categoryName = definition.category + val categoryPath = String.format("%s/%s", path, categoryName) + FileUtils.createCategoryDirectory(categoryPath) + val testName = result.key.name + val testDir = FileUtils.createTestDirectory(categoryPath, testName) + FileUtils.writeTestResultToDisk(testDir, result.value) + } + + private val isExternalStorageWritable: Boolean + get() = Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() + // // Callback configuration to notify test executor of test finishing // @@ -233,13 +198,23 @@ class RenderTestActivity : AppCompatActivity() { fun setOnRenderTestCompletionListener(listener: OnRenderTestCompletionListener?) { onRenderTestCompletionListener = listener - LoadRenderIgnoreTask(this).execute() + lifecycleScope.launch(Dispatchers.IO) { + val ignored = loadRenderIgnoreTask(this@RenderTestActivity) + withContext(Dispatchers.Main) { + onLoadIgnoreList(ignored) + } + } } fun onLoadIgnoreList(ignoreList: List) { Timber.e("We loaded %s of tests to be ignored", ignoreList.size) EXCLUDED_TESTS.addAll(ignoreList) - LoadRenderDefinitionTask(this).execute() + lifecycleScope.launch(Dispatchers.IO) { + val definitions = loadRenderDefinitionTask(this@RenderTestActivity) + withContext(Dispatchers.Main) { + startRenderTests(definitions) + } + } } // diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/snapshot/MapSnapshotterActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/snapshot/MapSnapshotterActivity.kt index dc7f71c0e..f31739c45 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/snapshot/MapSnapshotterActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/snapshot/MapSnapshotterActivity.kt @@ -141,7 +141,7 @@ class MapSnapshotterActivity : AppCompatActivity() { builder.withSource(source) } else if (row == 0 && column == 2) { val carBitmap = BitmapUtils.getBitmapFromDrawable( - ResourcesCompat.getDrawable(resources, R.drawable.ic_directions_car_black, null) + ResourcesCompat.getDrawable(resources, R.drawable.ic_directions_car_black, theme) ) // marker source @@ -207,7 +207,7 @@ class MapSnapshotterActivity : AppCompatActivity() { override fun onStyleImageMissing(imageName: String) { val androidIcon = - BitmapUtils.getBitmapFromDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_android_2, null)) + BitmapUtils.getBitmapFromDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_android_2, theme)) snapshotter.addImage(imageName, androidIcon!!, false) } }) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/AnimatedSymbolLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/AnimatedSymbolLayerActivity.kt index 197a9076f..84a053d23 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/AnimatedSymbolLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/AnimatedSymbolLayerActivity.kt @@ -18,7 +18,6 @@ import org.maplibre.geojson.Point import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.style.expressions.Expression import org.maplibre.android.style.layers.PropertyFactory @@ -48,17 +47,15 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { setContentView(R.layout.activity_animated_marker) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap -> - maplibreMap = map - map.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style? -> - this.style = style - setupCars() - animateRandomRoutes() - animateTaxi() - } + mapView.getMapAsync { + maplibreMap = it + it.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style? -> + this.style = style + setupCars() + animateRandomRoutes() + animateTaxi() } - ) + } } private fun setupCars() { @@ -171,7 +168,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { } private val longestDrive: Car? - private get() { + get() { var longestDrive: Car? = null for (randomCar in randomCars) { if (longestDrive == null) { @@ -199,7 +196,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { } private val duration: Long - private get() = (random.nextInt(DURATION_RANDOM_MAX) + DURATION_BASE).toLong() + get() = (random.nextInt(DURATION_RANDOM_MAX) + DURATION_BASE).toLong() private fun addRandomCars() { var latLng: LatLng @@ -224,7 +221,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { style!!.addSource(randomCarSource!!) style!!.addImage( RANDOM_CAR_IMAGE_ID, - (ResourcesCompat.getDrawable(resources, R.drawable.ic_car_top, null) as BitmapDrawable).bitmap + (ResourcesCompat.getDrawable(resources, R.drawable.ic_car_top, theme) as BitmapDrawable).bitmap ) val symbolLayer = SymbolLayer(RANDOM_CAR_LAYER, RANDOM_CAR_SOURCE) symbolLayer.withProperties( @@ -250,7 +247,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { ) style!!.addImage( PASSENGER, - (ResourcesCompat.getDrawable(resources, R.drawable.icon_burned, null) as BitmapDrawable).bitmap + (ResourcesCompat.getDrawable(resources, R.drawable.icon_burned, theme) as BitmapDrawable).bitmap ) val geoJsonSource = GeoJsonSource(PASSENGER_SOURCE, featureCollection) style!!.addSource(geoJsonSource) @@ -278,7 +275,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { taxi = Car(feature, passenger, duration) style!!.addImage( TAXI, - (ResourcesCompat.getDrawable(resources, R.drawable.ic_taxi_top, null) as BitmapDrawable).bitmap + (ResourcesCompat.getDrawable(resources, R.drawable.ic_taxi_top, theme) as BitmapDrawable).bitmap ) taxiSource = GeoJsonSource(TAXI_SOURCE, featureCollection) style!!.addSource(taxiSource!!) @@ -328,11 +325,9 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { override fun onDestroy() { super.onDestroy() - for (animator in animators) { - if (animator != null) { - animator.removeAllListeners() - animator.cancel() - } + animators.forEach { + it.removeAllListeners() + it.cancel() } mapView.onDestroy() } @@ -354,7 +349,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { } } - private class Car internal constructor(var feature: Feature, next: LatLng?, duration: Long) { + private class Car(var feature: Feature, next: LatLng?, duration: Long) { var next: LatLng? var current: LatLng? val duration: Long diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CustomSpriteActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CustomSpriteActivity.kt index 7cd4fa808..9a89c55c2 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CustomSpriteActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CustomSpriteActivity.kt @@ -13,7 +13,6 @@ import org.maplibre.android.camera.CameraUpdateFactory import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.style.layers.Layer import org.maplibre.android.style.layers.PropertyFactory @@ -36,81 +35,79 @@ class CustomSpriteActivity : AppCompatActivity() { setContentView(R.layout.activity_add_sprite) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap -> - maplibreMap = map - map.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style -> - val fab = findViewById(R.id.fab) - fab.setColorFilter( - ContextCompat.getColor( - this@CustomSpriteActivity, - R.color.primary - ) + mapView.getMapAsync { + maplibreMap = it + it.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style -> + val fab = findViewById(R.id.fab) + fab.setColorFilter( + ContextCompat.getColor( + this@CustomSpriteActivity, + R.color.primary ) - fab.setOnClickListener(object : View.OnClickListener { - private lateinit var point: Point - override fun onClick(view: View) { - if (point == null) { - Timber.i("First click -> Car") - // Add an icon to reference later - style.addImage( - CUSTOM_ICON, - BitmapFactory.decodeResource( - resources, - R.drawable.ic_car_top - ) + ) + fab.setOnClickListener(object : View.OnClickListener { + private lateinit var point: Point + override fun onClick(view: View) { + if (!this::point.isInitialized) { + Timber.i("First click -> Car") + // Add an icon to reference later + style.addImage( + CUSTOM_ICON, + BitmapFactory.decodeResource( + resources, + R.drawable.ic_car_top ) + ) - // Add a source with a geojson point - point = Point.fromLngLat(13.400972, 52.519003) - source = GeoJsonSource( - "point", - FeatureCollection.fromFeatures(arrayOf(Feature.fromGeometry(point))) - ) - maplibreMap.style!!.addSource(source!!) + // Add a source with a geojson point + point = Point.fromLngLat(13.400972, 52.519003) + source = GeoJsonSource( + "point", + FeatureCollection.fromFeatures(arrayOf(Feature.fromGeometry(point))) + ) + maplibreMap.style!!.addSource(source!!) - // Add a symbol layer that references that point source - layer = SymbolLayer("layer", "point") - layer.setProperties( // Set the id of the sprite to use - PropertyFactory.iconImage(CUSTOM_ICON), - PropertyFactory.iconAllowOverlap(true), - PropertyFactory.iconIgnorePlacement(true) - ) + // Add a symbol layer that references that point source + layer = SymbolLayer("layer", "point") + layer.setProperties( // Set the id of the sprite to use + PropertyFactory.iconImage(CUSTOM_ICON), + PropertyFactory.iconAllowOverlap(true), + PropertyFactory.iconIgnorePlacement(true) + ) - // lets add a circle below labels! - maplibreMap.style!!.addLayerBelow(layer, "water_intermittent") - fab.setImageResource(R.drawable.ic_directions_car_black) - } else { - // Update point - point = Point.fromLngLat( - point!!.longitude() + 0.001, - point!!.latitude() + 0.001 - ) - source!!.setGeoJson( - FeatureCollection.fromFeatures( - arrayOf( - Feature.fromGeometry( - point - ) + // lets add a circle below labels! + maplibreMap.style!!.addLayerBelow(layer, "water_intermittent") + fab.setImageResource(R.drawable.ic_directions_car_black) + } else { + // Update point + point = Point.fromLngLat( + point.longitude() + 0.001, + point.latitude() + 0.001 + ) + source!!.setGeoJson( + FeatureCollection.fromFeatures( + arrayOf( + Feature.fromGeometry( + point ) ) ) + ) - // Move the camera as well - maplibreMap.moveCamera( - CameraUpdateFactory.newLatLng( - LatLng( - point.latitude(), - point.longitude() - ) + // Move the camera as well + maplibreMap.moveCamera( + CameraUpdateFactory.newLatLng( + LatLng( + point.latitude(), + point.longitude() ) ) - } + ) } - }) - } + } + }) } - ) + } } override fun onStart() { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DataDrivenStyleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DataDrivenStyleActivity.kt index 2812c0c10..feba5ae95 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DataDrivenStyleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DataDrivenStyleActivity.kt @@ -12,7 +12,6 @@ import org.maplibre.android.camera.CameraUpdateFactory import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.style.expressions.Expression import org.maplibre.android.style.layers.FillLayer @@ -40,29 +39,25 @@ class DataDrivenStyleActivity : AppCompatActivity() { // Initialize map as normal mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap? -> - // Store for later - if (map != null) { - maplibreMap = map - } - maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style? -> - // Add a parks layer - addParksLayer() + mapView.getMapAsync { + // Store for later + maplibreMap = it + it.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style? -> + // Add a parks layer + addParksLayer() - // Add debug overlay - setupDebugZoomView() - } - - // Center and Zoom (Amsterdam, zoomed to streets) - maplibreMap.animateCamera( - CameraUpdateFactory.newLatLngZoom( - LatLng(52.379189, 4.899431), - 14.0 - ) - ) + // Add debug overlay + setupDebugZoomView() } - ) + + // Center and Zoom (Amsterdam, zoomed to streets) + it.animateCamera( + CameraUpdateFactory.newLatLngZoom( + LatLng(52.379189, 4.899431), + 14.0 + ) + ) + } } private fun setupDebugZoomView() { @@ -107,7 +102,7 @@ class DataDrivenStyleActivity : AppCompatActivity() { override fun onDestroy() { super.onDestroy() - if (maplibreMap != null && idleListener != null) { + if (this::maplibreMap.isInitialized && idleListener != null) { maplibreMap.removeOnCameraIdleListener(idleListener!!) } mapView.onDestroy() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DraggableMarkerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DraggableMarkerActivity.kt index 7eab9842e..340e75b8c 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DraggableMarkerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/DraggableMarkerActivity.kt @@ -336,9 +336,7 @@ class DraggableMarkerActivity : AppCompatActivity() { override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) { super.onSaveInstanceState(outState, outPersistentState) - outState?.let { - mapView.onSaveInstanceState(it) - } + mapView.onSaveInstanceState(outState) } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GeoJsonClusteringActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GeoJsonClusteringActivity.kt index bd8f7d83e..c349baa3b 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GeoJsonClusteringActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GeoJsonClusteringActivity.kt @@ -13,7 +13,6 @@ import org.maplibre.android.camera.CameraUpdateFactory import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.style.expressions.Expression import org.maplibre.android.style.layers.CircleLayer @@ -27,7 +26,6 @@ import org.maplibre.android.utils.BitmapUtils import timber.log.Timber import java.net.URI import java.net.URISyntaxException -import java.util.Objects /** * Test activity showcasing using a geojson source and visualise that source as a cluster by using filters. @@ -45,68 +43,68 @@ class GeoJsonClusteringActivity : AppCompatActivity() { mapView = findViewById(R.id.mapView) // noinspection ConstantConditions mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap? -> - if (map != null) { - maplibreMap = map - } - maplibreMap.animateCamera( - CameraUpdateFactory.newLatLngZoom( - LatLng(37.7749, 122.4194), - 0.0 + mapView.getMapAsync { + maplibreMap = it + maplibreMap.animateCamera( + CameraUpdateFactory.newLatLngZoom( + LatLng(37.7749, 122.4194), + 0.0 + ) + ) + val clusterLayers = arrayOf( + intArrayOf( + 150, + ResourcesCompat.getColor( + resources, + R.color.redAccent, + theme + ) + ), + intArrayOf(20, ResourcesCompat.getColor(resources, R.color.greenAccent, theme)), + intArrayOf( + 0, + ResourcesCompat.getColor( + resources, + R.color.blueAccent, + theme ) ) - val clusterLayers = arrayOf( - intArrayOf( - 150, - ResourcesCompat.getColor( - resources, - R.color.redAccent, - theme + ) + try { + maplibreMap.setStyle( + Style.Builder() + .fromUri(TestStyles.getPredefinedStyleWithFallback("Bright")) + .withSource(createClusterSource().also { clusterSource = it }) + .withLayer(createSymbolLayer()) + .withLayer(createClusterLevelLayer(0, clusterLayers)) + .withLayer(createClusterLevelLayer(1, clusterLayers)) + .withLayer(createClusterLevelLayer(2, clusterLayers)) + .withLayer(createClusterTextLayer()) + .withImage( + "icon-id", + BitmapUtils.getBitmapFromDrawable( + ResourcesCompat.getDrawable( + resources, + R.drawable.ic_hearing_black_24dp, + theme + ) + )!!, + true ) - ), - intArrayOf(20, ResourcesCompat.getColor(resources, R.color.greenAccent, theme)), - intArrayOf( - 0, - ResourcesCompat.getColor( - resources, - R.color.blueAccent, - theme - ) - ) ) - try { - maplibreMap.setStyle( - Style.Builder() - .fromUri(TestStyles.getPredefinedStyleWithFallback("Bright")) - .withSource(createClusterSource().also { clusterSource = it }) - .withLayer(createSymbolLayer()) - .withLayer(createClusterLevelLayer(0, clusterLayers)) - .withLayer(createClusterLevelLayer(1, clusterLayers)) - .withLayer(createClusterLevelLayer(2, clusterLayers)) - .withLayer(createClusterTextLayer()) - .withImage( - "icon-id", - Objects.requireNonNull( - BitmapUtils.getBitmapFromDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_hearing_black_24dp, null)) - )!!, - true - ) - ) - } catch (exception: URISyntaxException) { - Timber.e(exception) - } - maplibreMap.addOnMapClickListener { latLng: LatLng? -> - val point = maplibreMap.projection.toScreenLocation(latLng!!) - val features = - maplibreMap.queryRenderedFeatures(point, "cluster-0", "cluster-1", "cluster-2") - if (!features.isEmpty()) { - onClusterClick(features[0], Point(point.x.toInt(), point.y.toInt())) - } - true - } + } catch (exception: URISyntaxException) { + Timber.e(exception) } - ) + maplibreMap.addOnMapClickListener { latLng: LatLng? -> + val point = maplibreMap.projection.toScreenLocation(latLng!!) + val features = + maplibreMap.queryRenderedFeatures(point, "cluster-0", "cluster-1", "cluster-2") + if (!features.isEmpty()) { + onClusterClick(features[0], Point(point.x.toInt(), point.y.toInt())) + } + true + } + } findViewById(R.id.fab).setOnClickListener { v: View? -> updateClickOptionCounter() notifyClickOptionUpdate() @@ -266,7 +264,7 @@ class GeoJsonClusteringActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { - onBackPressed() + onBackPressedDispatcher.onBackPressed() true } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GridSourceActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GridSourceActivity.kt index 19c57a124..39cb401ed 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GridSourceActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/GridSourceActivity.kt @@ -17,6 +17,8 @@ import org.maplibre.android.style.sources.CustomGeometrySource import org.maplibre.android.style.sources.GeometryTileProvider import org.maplibre.android.testapp.R import java.util.* +import kotlin.math.ceil +import kotlin.math.floor /** * Test activity showcasing using CustomGeometrySource to create a grid overlay on the map. @@ -56,30 +58,30 @@ class GridSourceActivity : AppCompatActivity(), OnMapReadyCallback { } else { 20.0 } - var gridLines: MutableList = ArrayList() - var y = Math.ceil(bounds.latitudeNorth / gridSpacing) * gridSpacing - while (y >= Math.floor(bounds.latitudeSouth / gridSpacing) * gridSpacing) { + var gridLines: MutableList> = mutableListOf() + var y = ceil(bounds.latitudeNorth / gridSpacing) * gridSpacing + while (y >= floor(bounds.latitudeSouth / gridSpacing) * gridSpacing) { gridLines.add( - Arrays.asList( + listOf( Point.fromLngLat(bounds.longitudeWest, y), Point.fromLngLat(bounds.longitudeEast, y) ) ) y -= gridSpacing } - features.add(Feature.fromGeometry(MultiLineString.fromLngLats(gridLines as MutableList>))) - gridLines = ArrayList() - var x = Math.floor(bounds.longitudeWest / gridSpacing) * gridSpacing - while (x <= Math.ceil(bounds.longitudeEast / gridSpacing) * gridSpacing) { + features.add(Feature.fromGeometry(MultiLineString.fromLngLats(gridLines))) + gridLines = mutableListOf() + var x = floor(bounds.longitudeWest / gridSpacing) * gridSpacing + while (x <= ceil(bounds.longitudeEast / gridSpacing) * gridSpacing) { gridLines.add( - Arrays.asList( + listOf( Point.fromLngLat(x, bounds.latitudeSouth), Point.fromLngLat(x, bounds.latitudeNorth) ) ) x += gridSpacing } - features.add(Feature.fromGeometry(MultiLineString.fromLngLats(gridLines as MutableList>))) + features.add(Feature.fromGeometry(MultiLineString.fromLngLats(gridLines))) return FeatureCollection.fromFeatures(features) } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ImageInLabelActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ImageInLabelActivity.kt index 9bc6eeecd..374799ac0 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ImageInLabelActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ImageInLabelActivity.kt @@ -3,6 +3,7 @@ package org.maplibre.android.testapp.activity.style import android.graphics.Color import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.res.ResourcesCompat import org.maplibre.geojson.Feature import org.maplibre.geojson.FeatureCollection import org.maplibre.geojson.Point @@ -35,10 +36,11 @@ class ImageInLabelActivity : AppCompatActivity(), OnMapReadyCallback { override fun onMapReady(maplibreMap: MapLibreMap) { maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style -> val us = BitmapUtils.getBitmapFromDrawable( - resources.getDrawable(R.drawable.ic_us) + ResourcesCompat.getDrawable(resources, R.drawable.ic_us, theme) + ) + val android = BitmapUtils.getBitmapFromDrawable( + ResourcesCompat.getDrawable(resources, R.drawable.ic_android, theme) ) - val android = - BitmapUtils.getBitmapFromDrawable(resources.getDrawable(R.drawable.ic_android)) style.addImage("us", us!!) style.addImage("android", android!!) val point = Point.fromLngLat(-10.0, 0.0) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt index d8b13684c..cbd8c83f4 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt @@ -16,7 +16,6 @@ import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap import org.maplibre.android.maps.MapLibreMap.CancelableCallback -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.style.expressions.Expression import org.maplibre.android.style.layers.CircleLayer @@ -38,8 +37,6 @@ import org.maplibre.android.testapp.styles.TestStyles import org.maplibre.android.testapp.utils.ResourceUtils import timber.log.Timber import java.io.IOException -import java.util.Arrays -import java.util.Collections /** * Test activity showcasing the runtime style API. @@ -48,8 +45,8 @@ class RuntimeStyleActivity : AppCompatActivity() { private lateinit var mapView: MapView private lateinit var maplibreMap: MapLibreMap private var styleLoaded = false - var lngLats = listOf( - Arrays.asList( + private var lngLats = listOf( + listOf( Point.fromLngLat( -15.468749999999998, 41.77131167976407 @@ -80,39 +77,34 @@ class RuntimeStyleActivity : AppCompatActivity() { // Initialize map as normal mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap? -> - // Store for later - if (map != null) { - maplibreMap = map - } + mapView.getMapAsync { + // Store for later + maplibreMap = it - // Center and Zoom (Amsterdam, zoomed to streets) - maplibreMap.animateCamera( - CameraUpdateFactory.newLatLngZoom( - LatLng(52.379189, 4.899431), - 1.0 - ) + // Center and Zoom (Amsterdam, zoomed to streets) + maplibreMap.animateCamera( + CameraUpdateFactory.newLatLngZoom( + LatLng(52.379189, 4.899431), + 1.0 ) - maplibreMap.setStyle( - Style.Builder() - .fromUri(TestStyles.getPredefinedStyleWithFallback("Streets")) // set custom transition - .withTransition(TransitionOptions(250, 50)) - ) { style: Style -> - styleLoaded = true - val laber = style.getLayer("country_1") as SymbolLayer? - laber!!.setProperties( - PropertyFactory.textOpacity( - Expression.switchCase( - Expression.within(polygon), - Expression.literal(1.0f), - Expression.literal(0.5f) - ) + ) + maplibreMap.setStyle( + Style.Builder() + .fromUri(TestStyles.getPredefinedStyleWithFallback("Streets")) // set custom transition + .withTransition(TransitionOptions(250, 50)) + ) { style: Style -> + styleLoaded = true + style.getLayer("country_1")?.setProperties( + PropertyFactory.textOpacity( + Expression.switchCase( + Expression.within(polygon), + Expression.literal(1.0f), + Expression.literal(0.5f) ) ) - } + ) } - ) + } } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -337,8 +329,7 @@ class RuntimeStyleActivity : AppCompatActivity() { private fun addParksLayer() { // Add a source - val source: Source - source = try { + val source: Source = try { GeoJsonSource("amsterdam-spots", ResourceUtils.readRawResource(this, R.raw.amsterdam)) } catch (ioException: IOException) { Toast.makeText( @@ -391,8 +382,7 @@ class RuntimeStyleActivity : AppCompatActivity() { private fun addDynamicParksLayer() { // Load some data - val parks: FeatureCollection - parks = try { + val parks: FeatureCollection = try { val json = ResourceUtils.readRawResource(this, R.raw.amsterdam) FeatureCollection.fromJson(json) } catch (ioException: IOException) { @@ -436,7 +426,7 @@ class RuntimeStyleActivity : AppCompatActivity() { val handler = Handler(mainLooper) handler.postDelayed( { - if (maplibreMap == null) { + if (!this::maplibreMap.isInitialized) { return@postDelayed } Timber.d("Updating parks source") @@ -477,7 +467,7 @@ class RuntimeStyleActivity : AppCompatActivity() { val layers = maplibreMap.style!! .layers var latestLayer: Layer? = null - Collections.reverse(layers) + layers.reverse() for (currentLayer in layers) { if (currentLayer is FillLayer && currentLayer.sourceLayer == "road") { latestLayer = currentLayer @@ -584,7 +574,7 @@ class RuntimeStyleActivity : AppCompatActivity() { val handler = Handler(mainLooper) handler.postDelayed( { - if (maplibreMap == null) { + if (!this::maplibreMap.isInitialized) { return@postDelayed } Timber.d("Styling filtered fill layer") @@ -620,7 +610,7 @@ class RuntimeStyleActivity : AppCompatActivity() { val handler = Handler(mainLooper) handler.postDelayed( { - if (maplibreMap == null) { + if (!this::maplibreMap.isInitialized) { return@postDelayed } Timber.d("Styling text size fill layer") @@ -658,7 +648,7 @@ class RuntimeStyleActivity : AppCompatActivity() { val handler = Handler(mainLooper) handler.postDelayed( { - if (maplibreMap == null) { + if (!this::maplibreMap.isInitialized) { return@postDelayed } Timber.d("Styling filtered line layer") @@ -688,7 +678,7 @@ class RuntimeStyleActivity : AppCompatActivity() { val handler = Handler(mainLooper) handler.postDelayed( { - if (maplibreMap == null) { + if (!this::maplibreMap.isInitialized) { return@postDelayed } Timber.d("Styling numeric fill layer") diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StretchableImageActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StretchableImageActivity.kt index 1d19bc5db..6f893cc80 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StretchableImageActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StretchableImageActivity.kt @@ -1,8 +1,12 @@ package org.maplibre.android.testapp.activity.style -import android.os.AsyncTask import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.res.ResourcesCompat +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.maplibre.geojson.Feature import org.maplibre.geojson.FeatureCollection import org.maplibre.geojson.Point @@ -16,7 +20,6 @@ import org.maplibre.android.testapp.utils.GeoParseUtil import org.maplibre.android.utils.BitmapUtils import timber.log.Timber import java.io.IOException -import java.lang.ref.WeakReference import java.util.ArrayList /** @@ -37,10 +40,11 @@ class StretchableImageActivity : AppCompatActivity(), OnMapReadyCallback { this.maplibreMap = maplibreMap maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style -> val popup = BitmapUtils.getBitmapFromDrawable( - resources.getDrawable(R.drawable.popup) + ResourcesCompat.getDrawable(resources, R.drawable.popup, theme) + ) + val popupDebug = BitmapUtils.getBitmapFromDrawable( + ResourcesCompat.getDrawable(resources, R.drawable.popup_debug, theme) ) - val popupDebug = - BitmapUtils.getBitmapFromDrawable(resources.getDrawable(R.drawable.popup_debug)) // The two (blue) columns of pixels that can be stretched horizontally: // - the pixels between x: 25 and x: 55 can be stretched @@ -58,7 +62,12 @@ class StretchableImageActivity : AppCompatActivity(), OnMapReadyCallback { val content = ImageContent(25F, 25F, 115F, 100F) style.addImage(NAME_POPUP, popup!!, stretchX, stretchY, content) style.addImage(NAME_POPUP_DEBUG, popupDebug!!, stretchX, stretchY, content) - LoadFeatureTask(this@StretchableImageActivity).execute() + lifecycleScope.launch(Dispatchers.IO) { + val feature = loadFeatureTask(this@StretchableImageActivity) + withContext(Dispatchers.Main) { + onFeatureLoaded(feature) + } + } } } @@ -93,35 +102,16 @@ class StretchableImageActivity : AppCompatActivity(), OnMapReadyCallback { } } - private class LoadFeatureTask(activity: StretchableImageActivity) : - AsyncTask() { - private val activity: WeakReference - protected override fun doInBackground(vararg p0: Void?): String? { - val activity = activity.get() - if (activity != null) { - var json: String? = null - try { - json = GeoParseUtil.loadStringFromAssets( - activity.applicationContext, - "stretchable_image.geojson" - ) - } catch (exception: IOException) { - Timber.e(exception, "Could not read feature") - } - return json - } - return null - } - - override fun onPostExecute(json: String?) { - super.onPostExecute(json) - val activity = activity.get() - activity?.onFeatureLoaded(json) - } - - init { - this.activity = WeakReference(activity) + private fun loadFeatureTask(activity: StretchableImageActivity) : String? { + try { + return GeoParseUtil.loadStringFromAssets( + activity.applicationContext, + "stretchable_image.geojson" + ) + } catch (exception: IOException) { + Timber.e(exception, "Could not read feature") } + return null } override fun onStart() { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StyleFileActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StyleFileActivity.kt index addf00a9c..20da73c4a 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StyleFileActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/StyleFileActivity.kt @@ -1,16 +1,18 @@ package org.maplibre.android.testapp.activity.style import android.content.Context -import android.os.AsyncTask import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope import com.google.android.material.floatingactionbutton.FloatingActionButton +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.testapp.R import org.maplibre.android.testapp.styles.TestStyles @@ -19,7 +21,6 @@ import timber.log.Timber import java.io.BufferedWriter import java.io.File import java.io.FileWriter -import java.lang.ref.WeakReference /** * Test activity showcasing how to use a file:// resource for the style.json and how to use MapLibreMap#setStyleJson. @@ -32,121 +33,86 @@ class StyleFileActivity : AppCompatActivity() { setContentView(R.layout.activity_style_file) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap? -> - if (map != null) { - maplibreMap = map - } - maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style? -> - val fab = findViewById(R.id.fab_file) - fab.setColorFilter(ContextCompat.getColor(this@StyleFileActivity, R.color.primary)) - fab.setOnClickListener { view: View -> - CreateStyleFileTask( - view.context, - maplibreMap - ).execute() + mapView.getMapAsync { + maplibreMap = it + maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style? -> + val fab = findViewById(R.id.fab_file) + fab.setColorFilter(ContextCompat.getColor(this@StyleFileActivity, R.color.primary)) + fab.setOnClickListener { view: View -> + lifecycleScope.launch(Dispatchers.IO) { + val cacheStylePath = createStyleFileTask(view.context) + withContext(Dispatchers.Main) { + cacheStylePath?.let { + maplibreMap.setStyle( + Style.Builder().fromUri("file://$it") + ) + } + } } - val fabStyleJson = findViewById(R.id.fab_style_json) - fabStyleJson.setColorFilter( - ContextCompat.getColor( - this@StyleFileActivity, - R.color.primary - ) + } + val fabStyleJson = findViewById(R.id.fab_style_json) + fabStyleJson.setColorFilter( + ContextCompat.getColor( + this@StyleFileActivity, + R.color.primary ) - fabStyleJson.setOnClickListener { view: View -> - LoadStyleFileTask( - view.context, - maplibreMap - ).execute() + ) + fabStyleJson.setOnClickListener { view: View -> + lifecycleScope.launch(Dispatchers.IO) { + val json = loadStyleFileTask(view.context) + withContext(Dispatchers.Main) { + Timber.d("Read json, %s", json) + maplibreMap.setStyle(Style.Builder().fromJson(json)) + } } } } - ) + } } /** * Task to read a style file from the raw folder */ - private class LoadStyleFileTask internal constructor(context: Context, maplibreMap: MapLibreMap?) : - AsyncTask() { - private val context: WeakReference - private val maplibreMap: WeakReference - protected override fun doInBackground(vararg p0: Void?): String? { - var styleJson = "" - try { - styleJson = ResourceUtils.readRawResource(context.get(), R.raw.sat_style) - } catch (exception: Exception) { - Timber.e(exception, "Can't load local file style") - } - return styleJson + private fun loadStyleFileTask(context: Context): String = + try { + ResourceUtils.readRawResource(context, R.raw.sat_style) + } catch (exception: Exception) { + Timber.e(exception, "Can't load local file style") + "" } - override fun onPostExecute(json: String) { - super.onPostExecute(json) - Timber.d("Read json, %s", json) - val maplibreMap = maplibreMap.get() - maplibreMap?.setStyle(Style.Builder().fromJson(json)) - } - - init { - this.context = WeakReference(context) - this.maplibreMap = WeakReference(maplibreMap) - } - } - /** * Task to write a style file to local disk and load it in the map view */ - private class CreateStyleFileTask internal constructor( + private fun createStyleFileTask( context: Context, - maplibreMap: MapLibreMap? - ) : AsyncTask() { - private lateinit var cacheStyleFile: File - private val context: WeakReference - private val maplibreMap: WeakReference - protected override fun doInBackground(vararg p0: Void?): Long? { - try { - cacheStyleFile = File.createTempFile("my-", ".style.json") - cacheStyleFile.createNewFile() - Timber.i("Writing style file to: %s", cacheStyleFile.getAbsolutePath()) - val context = context.get() - if (context != null) { - writeToFile( - cacheStyleFile, - ResourceUtils.readRawResource(context, R.raw.local_style) - ) - } - } catch (exception: Exception) { - Toast.makeText( - context.get(), - "Could not create style file in cache dir", - Toast.LENGTH_SHORT - ).show() - } - return 1L - } - - override fun onPostExecute(result: Long) { - // Actual file:// usage - val maplibreMap = maplibreMap.get() - maplibreMap?.setStyle( - Style.Builder().fromUri("file://" + cacheStyleFile!!.absolutePath) + ): String? { + return try { + val cacheStyleFile = File.createTempFile("my-", ".style.json") + cacheStyleFile.createNewFile() + Timber.i("Writing style file to: %s", cacheStyleFile.getAbsolutePath()) + writeToFile( + cacheStyleFile, + ResourceUtils.readRawResource(context, R.raw.local_style) ) + cacheStyleFile.absolutePath + } catch (exception: Exception) { + Toast.makeText( + context, + "Could not create style file in cache dir", + Toast.LENGTH_SHORT + ).show() + null } + } - private fun writeToFile(file: File?, contents: String) { - var writer: BufferedWriter? = null - try { - writer = BufferedWriter(FileWriter(file)) - writer.write(contents) - } finally { - writer?.close() - } - } - - init { - this.context = WeakReference(context) - this.maplibreMap = WeakReference(maplibreMap) + private fun writeToFile(file: File?, contents: String) { + var writer: BufferedWriter? = null + try { + writer = BufferedWriter(FileWriter(file)) + writer.write(contents) + } finally { + writer?.close() } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolGeneratorActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolGeneratorActivity.kt index 4a656144f..314c125a8 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolGeneratorActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolGeneratorActivity.kt @@ -4,14 +4,19 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color -import android.os.AsyncTask +import android.os.Build import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.TextView import android.widget.Toast +import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.maplibre.geojson.FeatureCollection import org.maplibre.android.geometry.LatLng import org.maplibre.android.maps.MapView @@ -28,7 +33,6 @@ import org.maplibre.android.testapp.R import org.maplibre.android.testapp.styles.TestStyles import org.maplibre.android.testapp.utils.ResourceUtils.readRawResource import timber.log.Timber -import java.lang.ref.WeakReference /** * Test activity showcasing using a symbol generator that generates Bitmaps from Android SDK Views. @@ -44,11 +48,17 @@ class SymbolGeneratorActivity : AppCompatActivity(), OnMapReadyCallback { mapView.getMapAsync(this) } + @RequiresApi(Build.VERSION_CODES.M) override fun onMapReady(map: MapLibreMap) { maplibreMap = map map.setStyle(TestStyles.getPredefinedStyleWithFallback("Outdoor")) { style: Style? -> addSymbolClickListener() - LoadDataTask(this@SymbolGeneratorActivity).execute() + lifecycleScope.launch(Dispatchers.IO) { + val featureCollection = loadDataTask(this@SymbolGeneratorActivity) + withContext(Dispatchers.Main) { + featureCollection?.let { onDataLoaded(it) } + } + } } } @@ -164,34 +174,13 @@ class SymbolGeneratorActivity : AppCompatActivity(), OnMapReadyCallback { } } - private class LoadDataTask internal constructor(activity: SymbolGeneratorActivity) : - AsyncTask() { - private val activity: WeakReference - - init { - this.activity = WeakReference(activity) - } - - override fun doInBackground(vararg p0: Void?): FeatureCollection? { - val context: Context? = activity.get() - if (context != null) { - // read local geojson from raw folder - val tinyCountriesJson = readRawResource(context, R.raw.tiny_countries) - return FeatureCollection.fromJson(tinyCountriesJson) - } - return null - } - - override fun onPostExecute(featureCollection: FeatureCollection?) { - super.onPostExecute(featureCollection) - val activity = activity.get() - if (featureCollection == null || activity == null) { - return - } - activity.onDataLoaded(featureCollection) - } + private fun loadDataTask(context: SymbolGeneratorActivity) : FeatureCollection? { + // read local geojson from raw folder + val tinyCountriesJson = readRawResource(context, R.raw.tiny_countries) + return FeatureCollection.fromJson(tinyCountriesJson) } + @RequiresApi(Build.VERSION_CODES.M) fun onDataLoaded(featureCollection: FeatureCollection) { if (mapView.isDestroyed) { return @@ -298,41 +287,30 @@ class SymbolGeneratorActivity : AppCompatActivity(), OnMapReadyCallback { PropertyFactory.textField(textFieldExpressionResult), PropertyFactory.textColor(textColorExpressionResult) ) - GenerateSymbolTask(maplibreMap, this).execute(featureCollection) + lifecycleScope.launch(Dispatchers.IO) { + val bitmapHashMap = generateSymbolTask(this@SymbolGeneratorActivity, featureCollection) + withContext(Dispatchers.Main) { + maplibreMap.getStyle { style -> style.addImagesAsync(bitmapHashMap) } + } + } } - private class GenerateSymbolTask internal constructor( - private val maplibreMap: MapLibreMap?, - context: Context - ) : AsyncTask>() { - private val context: WeakReference - - init { - this.context = WeakReference(context) - } - - override fun doInBackground(vararg p0: FeatureCollection?): HashMap? { - val imagesMap = HashMap() - val context = context.get() - val features = p0[0]?.features() - if (context != null && features != null) { - for (feature in features) { - val countryName = feature.getStringProperty(FEATURE_ID) - val textView = TextView(context) - textView.setBackgroundColor(context.resources.getColor(R.color.blueAccent)) - textView.setPadding(10, 5, 10, 5) - textView.setTextColor(Color.WHITE) - textView.text = countryName - imagesMap[countryName] = SymbolGenerator.generate(textView) - } - } - return imagesMap - } - - override fun onPostExecute(bitmapHashMap: HashMap) { - super.onPostExecute(bitmapHashMap) - maplibreMap?.getStyle { style -> style.addImagesAsync(bitmapHashMap) } + @RequiresApi(Build.VERSION_CODES.M) + private fun generateSymbolTask( + context: Context, + featureCollection: FeatureCollection? + ) : HashMap { + val imagesMap = HashMap() + featureCollection?.features()?.forEach { + val countryName = it.getStringProperty(FEATURE_ID) + val textView = TextView(context) + textView.setBackgroundColor(context.resources.getColor(R.color.blueAccent, null)) + textView.setPadding(10, 5, 10, 5) + textView.setTextColor(Color.WHITE) + textView.text = countryName + imagesMap[countryName] = SymbolGenerator.generate(textView) } + return imagesMap } companion object { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolLayerActivity.kt index 1162ac6d8..328913862 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/SymbolLayerActivity.kt @@ -33,8 +33,6 @@ import org.maplibre.android.style.sources.Source import org.maplibre.android.testapp.R import org.maplibre.android.utils.BitmapUtils import timber.log.Timber -import java.util.Arrays -import java.util.Objects import java.util.Random /** @@ -80,7 +78,7 @@ class SymbolLayerActivity : AppCompatActivity(), OnMapClickListener, OnMapReadyC Timber.e("Adding image with id: %s", id) val androidIcon = BitmapUtils.getBitmapFromDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_android_2, null)) - style.addImage(id!!, Objects.requireNonNull(androidIcon)!!) + style.addImage(id!!, androidIcon!!) } } } @@ -156,7 +154,7 @@ class SymbolLayerActivity : AppCompatActivity(), OnMapClickListener, OnMapReadyC maplibreMap.setStyle( Style.Builder() .fromUri("asset://streets.json") - .withImage("Car", Objects.requireNonNull(carBitmap)!!, false) + .withImage("Car", carBitmap!!, false) .withSources(markerSource, mapboxSignSource, numberFormatSource) .withLayers(markerSymbolLayer, mapboxSignSymbolLayer, numberFormatSymbolLayer) ) @@ -170,7 +168,7 @@ class SymbolLayerActivity : AppCompatActivity(), OnMapClickListener, OnMapReadyC val screenLoc = maplibreMap.projection.toScreenLocation(point) val markerFeatures = maplibreMap.queryRenderedFeatures(screenLoc, MARKER_LAYER) if (!markerFeatures.isEmpty()) { - for (feature in Objects.requireNonNull(markerCollection!!.features())!!) { + for (feature in markerCollection!!.features()!!) { if (feature.getStringProperty(ID_FEATURE_PROPERTY) == markerFeatures[0].getStringProperty(ID_FEATURE_PROPERTY) ) { @@ -230,7 +228,7 @@ class SymbolLayerActivity : AppCompatActivity(), OnMapClickListener, OnMapReadyC private fun toggleTextFont() { if (markerSymbolLayer != null) { - if (Arrays.equals(markerSymbolLayer!!.textFont.getValue(), NORMAL_FONT_STACK)) { + if (markerSymbolLayer!!.textFont.getValue().contentEquals(NORMAL_FONT_STACK)) { markerSymbolLayer!!.setProperties(PropertyFactory.textFont(BOLD_FONT_STACK)) } else { markerSymbolLayer!!.setProperties(PropertyFactory.textFont(NORMAL_FONT_STACK)) @@ -312,7 +310,7 @@ class SymbolLayerActivity : AppCompatActivity(), OnMapClickListener, OnMapReadyC public override fun onDestroy() { super.onDestroy() - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { maplibreMap.removeOnMapClickListener(this) } mapView.onDestroy() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt index e4fa13863..b7647dcdf 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt @@ -11,7 +11,6 @@ import org.maplibre.geojson.Point import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap import org.maplibre.android.maps.MapLibreMap.OnMapClickListener -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.style.expressions.Expression import org.maplibre.android.style.layers.Property @@ -52,16 +51,14 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { setContentView(R.layout.activity_zoom_symbol_layer) mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync( - OnMapReadyCallback { map: MapLibreMap -> - maplibreMap = map - map.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style -> - updateSource(style) - addLayer(style) - map.addOnMapClickListener(mapClickListener) - } + mapView.getMapAsync { map: MapLibreMap -> + maplibreMap = map + map.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets")) { style: Style -> + updateSource(style) + addLayer(style) + map.addOnMapClickListener(mapClickListener) } - ) + } } private fun updateSource(style: Style?) { @@ -121,7 +118,7 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { } override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (maplibreMap != null) { + if (this::maplibreMap.isInitialized) { if (item.itemId == R.id.menu_action_change_location) { isInitialPosition = !isInitialPosition updateSource(maplibreMap.style) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/telemetry/PerformanceMeasurementActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/telemetry/PerformanceMeasurementActivity.kt index 1cb34df3d..b99a6498c 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/telemetry/PerformanceMeasurementActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/telemetry/PerformanceMeasurementActivity.kt @@ -10,8 +10,6 @@ import com.google.gson.Gson import com.google.gson.JsonObject import org.maplibre.android.MapLibre import org.maplibre.android.maps.MapView -import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.maps.Style import org.maplibre.android.module.http.HttpRequestUtil import org.maplibre.android.testapp.R @@ -37,49 +35,47 @@ class PerformanceMeasurementActivity : AppCompatActivity() { .eventListener(eventListener) .build() HttpRequestUtil.setOkHttpClient(okHttpClient) - mapView.getMapAsync( - OnMapReadyCallback { maplibreMap: MapLibreMap -> - maplibreMap.setStyle( - Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Streets")) - ) - } - ) + mapView.getMapAsync { + it.setStyle( + Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Streets")) + ) + } } override fun onStart() { super.onStart() - mapView!!.onStart() + mapView.onStart() } override fun onResume() { super.onResume() - mapView!!.onResume() + mapView.onResume() } override fun onPause() { super.onPause() - mapView!!.onPause() + mapView.onPause() } override fun onStop() { super.onStop() - mapView!!.onStop() + mapView.onStop() } override fun onLowMemory() { super.onLowMemory() - mapView!!.onLowMemory() + mapView.onLowMemory() } override fun onDestroy() { HttpRequestUtil.setOkHttpClient(null) super.onDestroy() - mapView!!.onDestroy() + mapView.onDestroy() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - mapView!!.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) } private class EventListener : okhttp3.EventListener() { @@ -105,7 +101,7 @@ class PerformanceMeasurementActivity : AppCompatActivity() { } } - private class Attribute internal constructor(private val name: String, private val value: T) + private class Attribute(private val name: String, private val value: T) companion object { private fun triggerPerformanceEvent(style: String, elapsed: Long) { val attributes: MutableList> = ArrayList() @@ -123,7 +119,7 @@ class PerformanceMeasurementActivity : AppCompatActivity() { metaData.addProperty("brand", Build.BRAND) metaData.addProperty("device", Build.MODEL) metaData.addProperty("version", Build.VERSION.RELEASE) - metaData.addProperty("abi", Build.CPU_ABI) + metaData.addProperty("abi", Build.SUPPORTED_ABIS[0]) metaData.addProperty("country", Locale.getDefault().isO3Country) metaData.addProperty("ram", ram) metaData.addProperty("screenSize", windowSize) @@ -135,7 +131,7 @@ class PerformanceMeasurementActivity : AppCompatActivity() { } private val ram: String - private get() { + get() { val actManager = MapLibre.getApplicationContext() .getSystemService(ACTIVITY_SERVICE) as ActivityManager val memInfo = ActivityManager.MemoryInfo() @@ -143,7 +139,7 @@ class PerformanceMeasurementActivity : AppCompatActivity() { return memInfo.totalMem.toString() } private val windowSize: String - private get() { + get() { val windowManager = MapLibre.getApplicationContext().getSystemService(WINDOW_SERVICE) as WindowManager val display = windowManager.defaultDisplay diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewDebugModeActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewDebugModeActivity.kt index 8287a4bab..5c80a6f78 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewDebugModeActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewDebugModeActivity.kt @@ -1,5 +1,7 @@ package org.maplibre.android.testapp.activity.textureview +import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.maplibre.android.maps.MapLibreMapOptions import org.maplibre.android.maps.OnMapReadyCallback import org.maplibre.android.testapp.activity.maplayout.DebugModeActivity @@ -9,15 +11,20 @@ import org.maplibre.android.testapp.utils.NavUtils * Test activity showcasing the different debug modes and allows to cycle between the default map styles. */ class TextureViewDebugModeActivity : DebugModeActivity(), OnMapReadyCallback { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + // activity uses singleInstance for testing purposes + // code below provides a default navigation when using the app + NavUtils.navigateHome(this@TextureViewDebugModeActivity) + } + }) + } + override fun setupMapLibreMapOptions(): MapLibreMapOptions { val maplibreMapOptions = super.setupMapLibreMapOptions() maplibreMapOptions.textureMode(true) return maplibreMapOptions } - - override fun onBackPressed() { - // activity uses singleInstance for testing purposes - // code below provides a default navigation when using the app - NavUtils.navigateHome(this) - } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewResizeActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewResizeActivity.kt index 42681f806..a9aa9917e 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewResizeActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/textureview/TextureViewResizeActivity.kt @@ -33,7 +33,7 @@ class TextureViewResizeActivity : AppCompatActivity() { private fun setupMapView(savedInstanceState: Bundle?) { mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) - mapView.getMapAsync(OnMapReadyCallback { maplibreMap: MapLibreMap -> setupMap(maplibreMap) }) + mapView.getMapAsync { setupMap(it) } } private fun setupMap(maplibreMap: MapLibreMap) { @@ -43,7 +43,7 @@ class TextureViewResizeActivity : AppCompatActivity() { private fun setupFab() { val fabDebug = findViewById(R.id.fabResize) fabDebug.setOnClickListener { view: View? -> - if (mapView != null) { + if (this::mapView.isInitialized) { val parent = findViewById(R.id.coordinator_layout) val width = if (parent.width == mapView.width) parent.width / 2 else parent.width val height = diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/annotations/CityStateMarkerOptions.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/annotations/CityStateMarkerOptions.kt index 0ffe31f9f..b0349f2a0 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/annotations/CityStateMarkerOptions.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/annotations/CityStateMarkerOptions.kt @@ -14,7 +14,8 @@ class CityStateMarkerOptions : BaseMarkerOptions(LatLng::class.java.classLoader) as LatLng) snippet(`in`.readString()) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/other/OfflineDownloadRegionDialog.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/other/OfflineDownloadRegionDialog.kt index 00c266d8e..c67e86cd5 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/other/OfflineDownloadRegionDialog.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/model/other/OfflineDownloadRegionDialog.kt @@ -1,14 +1,13 @@ package org.maplibre.android.testapp.model.other -import android.app.Activity import android.app.Dialog +import android.content.Context import android.content.DialogInterface import android.os.Bundle import android.widget.EditText import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment import org.maplibre.android.testapp.R -import org.maplibre.android.testapp.model.other.OfflineDownloadRegionDialog.DownloadRegionDialogListener import timber.log.Timber class OfflineDownloadRegionDialog : DialogFragment() { @@ -17,9 +16,10 @@ class OfflineDownloadRegionDialog : DialogFragment() { } var listener: DownloadRegionDialogListener? = null - override fun onAttach(activity: Activity) { - super.onAttach(activity) - listener = activity as DownloadRegionDialogListener + + override fun onAttach(context: Context) { + super.onAttach(context) + listener = context as? DownloadRegionDialogListener } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { @@ -34,7 +34,7 @@ class OfflineDownloadRegionDialog : DialogFragment() { .setView(regionNameEdit) .setPositiveButton("Start") { dialog: DialogInterface?, which: Int -> val regionName = regionNameEdit.text.toString() - listener!!.onDownloadRegionDialogPositiveClick(regionName) + listener?.onDownloadRegionDialogPositiveClick(regionName) } .setNegativeButton("Cancel") { dialog: DialogInterface?, which: Int -> Timber.d("Download cancelled.") } return builder.create() diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/FileUtils.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/FileUtils.kt index 70570203d..4eb74616f 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/FileUtils.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/FileUtils.kt @@ -1,64 +1,38 @@ package org.maplibre.android.testapp.utils import android.content.Context -import android.os.AsyncTask import java.io.File import java.io.FileOutputStream -import java.lang.ref.WeakReference -class FileUtils { +object FileUtils { /** * Task that copies a file from the assets directory to a provided directory. * The asset's name is going to be kept in the new directory. */ - class CopyFileFromAssetsTask(context: Context, listener: OnFileCopiedFromAssetsListener) : AsyncTask() { - private val contextWeakReference: WeakReference = WeakReference(context) - private val listenerWeakReference: WeakReference = WeakReference(listener) - - override fun doInBackground(vararg strings: String): Boolean? { - val assetName = strings[0] - val destinationPath = strings[1] - contextWeakReference.get()?.let { - try { - copyAsset(it, assetName, destinationPath) - } catch (ex: Exception) { - return false - } - } - - return true + fun copyFileFromAssetsTask( + context: Context, + assetName: String, + destinationPath: String + ) : Boolean = + try { + copyAsset(context, assetName, destinationPath) + true + } catch (ex: Exception) { + false } - override fun onCancelled() { - listenerWeakReference.get()?.onError() + private fun copyAsset(context: Context, assetName: String, destinationPath: String) { + val bufferSize = 1024 + val assetManager = context.assets + val inputStream = assetManager.open(assetName) + val outputStream = FileOutputStream(File(destinationPath, assetName)) + try { + inputStream.copyTo(outputStream, bufferSize) + } finally { + inputStream.close() + outputStream.flush() + outputStream.close() } - - override fun onPostExecute(result: Boolean) { - if (result) { - listenerWeakReference.get()?.onFileCopiedFromAssets() - } else { - listenerWeakReference.get()?.onError() - } - } - - private fun copyAsset(context: Context, assetName: String, destinationPath: String) { - val bufferSize = 1024 - val assetManager = context.assets - val inputStream = assetManager.open(assetName) - val outputStream = FileOutputStream(File(destinationPath, assetName)) - try { - inputStream.copyTo(outputStream, bufferSize) - } finally { - inputStream.close() - outputStream.flush() - outputStream.close() - } - } - } - - interface OnFileCopiedFromAssetsListener { - fun onFileCopiedFromAssets() - fun onError() } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ItemClickSupport.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ItemClickSupport.kt index f7170f489..2ac88d856 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ItemClickSupport.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ItemClickSupport.kt @@ -10,13 +10,13 @@ class ItemClickSupport private constructor(private val recyclerView: RecyclerVie private val onClickListener = View.OnClickListener { view -> onItemClickListener?.let { val holder = recyclerView.getChildViewHolder(view) - it.onItemClicked(recyclerView, holder.adapterPosition, view) + it.onItemClicked(recyclerView, holder.bindingAdapterPosition, view) } } private val onLongClickListener = View.OnLongClickListener { view -> onItemLongClickListener?.let { val holder = recyclerView.getChildViewHolder(view) - it.onItemLongClicked(recyclerView, holder.adapterPosition, view) + it.onItemLongClicked(recyclerView, holder.bindingAdapterPosition, view) } false } @@ -61,9 +61,7 @@ class ItemClickSupport private constructor(private val recyclerView: RecyclerVie fun removeFrom(view: RecyclerView): ItemClickSupport? { val support = view.getTag(R.id.item_click_support) as ItemClickSupport? - support?.let { - it.detach(view) - } + support?.detach(view) return support } } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/TileLoadingMeasurementUtils.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/TileLoadingMeasurementUtils.kt index c7aa7a27c..71f767cc9 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/TileLoadingMeasurementUtils.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/TileLoadingMeasurementUtils.kt @@ -7,8 +7,7 @@ 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.RequiresApi import androidx.annotation.StringDef import com.google.gson.Gson import com.google.gson.JsonObject @@ -26,11 +25,11 @@ import timber.log.Timber import java.io.IOException import java.util.* +@RequiresApi(Build.VERSION_CODES.M) class TileLoadingMeasurementUtils { companion object { - private const val ATTRIBUTE_REQUEST_URL = "requestUrl" fun setUpTileLoadingMeasurement() { if (isTileLoadingMeasurementOn) { val okHttpClient: OkHttpClient = Builder() @@ -41,7 +40,7 @@ class TileLoadingMeasurementUtils { } private val isTileLoadingMeasurementOn: Boolean - private get() = isBooleanMetaDataValueOn( + get() = isBooleanMetaDataValueOn( MapLibreConstants.KEY_META_DATA_MEASURE_TILE_DOWNLOAD_ON, MapLibreConstants.DEFAULT_MEASURE_TILE_DOWNLOAD_ON ) @@ -76,7 +75,7 @@ class TileLoadingMeasurementUtils { */ internal class TileLoadingInterceptor : Interceptor { @StringDef(*[CONNECTION_NONE, CONNECTION_CELLULAR, CONNECTION_WIFI]) - @kotlin.annotation.Retention(AnnotationRetention.SOURCE) + @Retention(AnnotationRetention.SOURCE) internal annotation class ConnectionState @Throws(IOException::class) @@ -108,7 +107,7 @@ class TileLoadingMeasurementUtils { companion object { private var metadata: String? = null - private get() { + get() { if (field == null) { val metaData = JsonObject() metaData.addProperty("os", "android") @@ -116,7 +115,7 @@ class TileLoadingMeasurementUtils { metaData.addProperty("brand", Build.BRAND) metaData.addProperty("device", Build.MODEL) metaData.addProperty("version", Build.VERSION.RELEASE) - metaData.addProperty("abi", Build.CPU_ABI) + metaData.addProperty("abi", Build.SUPPORTED_ABIS[0]) metaData.addProperty("country", Locale.getDefault().isO3Country) metaData.addProperty("ram", ram) metaData.addProperty("screenSize", windowSize) @@ -133,7 +132,7 @@ class TileLoadingMeasurementUtils { } private val ram: String - private get() { + get() { val actManager = MapLibre.getApplicationContext() .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val memInfo = ActivityManager.MemoryInfo() @@ -141,44 +140,33 @@ class TileLoadingMeasurementUtils { return memInfo.totalMem.toString() } private val windowSize: String - private get() { - val windowManager = MapLibre.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() { + val metrics = MapLibre.getApplicationContext().resources.displayMetrics + return "{${metrics.widthPixels},${metrics.heightPixels}}" } @get:ConnectionState private val connectionState: String - private get() { + get() { val appContext = MapLibre.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 - } + 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 - } + connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)?.let { + if (it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + return CONNECTION_WIFI + } else if (it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return CONNECTION_CELLULAR } } } @@ -187,6 +175,6 @@ class TileLoadingMeasurementUtils { } } - private class Attribute internal constructor(private val name: String, private val value: T) + private class Attribute(private val name: String, private val value: T) } } diff --git a/platform/android/gradle/libs.versions.toml b/platform/android/gradle/libs.versions.toml index 9600b00bb..b818f0138 100644 --- a/platform/android/gradle/libs.versions.toml +++ b/platform/android/gradle/libs.versions.toml @@ -31,10 +31,12 @@ multidex = "2.0.1" androidxTestExtJUnit = "1.1.5" androidxTestCoreKtx = "1.5.0" kotlinxSerializationJson = "1.6.0" +kotlinxCoroutinesTest = "1.6.4" androidGradlePlugin = "8.5.1" [libraries] +kotlinxCoroutinesTest = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTest" } maplibreJavaGeoJSON = { group = "org.maplibre.gl", name = "android-sdk-geojson", version.ref = "mapLibreServices" } mapboxAndroidGestures = { group = "com.mapbox.mapboxsdk", name = "mapbox-android-gestures", version.ref = "mapboxGestures" } maplibreJavaTurf = { group = "org.maplibre.gl", name = "android-sdk-turf", version.ref = "mapLibreServices" }