From ed98232263484a293f2018fadd32582416b8aba5 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Fri, 4 Feb 2022 21:58:00 -0500 Subject: [PATCH 01/12] Migrating to Mapbox API V10 --- app/build.gradle | 7 +- .../com/geeksville/mesh/ui/MapFragment.kt | 179 ++++++++---------- app/src/main/res/layout/map_view.xml | 13 +- build.gradle | 25 --- settings.gradle | 26 ++- 5 files changed, 119 insertions(+), 131 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a9cccafc4..796d04a2e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,6 +127,9 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.fragment:fragment-ktx:1.4.0' + implementation('com.mapbox.maps:android:10.2.0') { + exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-telemetry' + } implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.3' @@ -158,11 +161,11 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" // For now I'm not using javalite, because I want JSON printing - implementation ('com.google.protobuf:protobuf-java:3.15.8') + implementation('com.google.protobuf:protobuf-java:3.15.8') // For UART access // implementation 'com.google.android.things:androidthings:1.0' - implementation 'com.github.mik3y:usb-serial-for-android:v3.0.0' + implementation 'com.github.mik3y:usb-serial-for-android:3.4.3' // mapbox implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.7.1' diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index f40c78b3d..3d7850dc0 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer import com.geeksville.android.GeeksvilleApplication @@ -17,20 +18,17 @@ import com.geeksville.util.formatAgo import com.mapbox.geojson.Feature import com.mapbox.geojson.FeatureCollection import com.mapbox.geojson.Point -import com.mapbox.mapboxsdk.camera.CameraPosition -import com.mapbox.mapboxsdk.camera.CameraUpdateFactory -import com.mapbox.mapboxsdk.geometry.LatLng -import com.mapbox.mapboxsdk.geometry.LatLngBounds -import com.mapbox.mapboxsdk.maps.MapView -import com.mapbox.mapboxsdk.maps.MapboxMap -import com.mapbox.mapboxsdk.maps.Style -import com.mapbox.mapboxsdk.style.expressions.Expression -import com.mapbox.mapboxsdk.style.layers.Property -import com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_TOP -import com.mapbox.mapboxsdk.style.layers.Property.TEXT_JUSTIFY_AUTO -import com.mapbox.mapboxsdk.style.layers.PropertyFactory.* -import com.mapbox.mapboxsdk.style.layers.SymbolLayer -import com.mapbox.mapboxsdk.style.sources.GeoJsonSource +import com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap +import com.mapbox.maps.MapView +import com.mapbox.maps.CameraOptions +import com.mapbox.maps.MapboxMap +import com.mapbox.maps.Style +import com.mapbox.maps.extension.style.expressions.generated.Expression +import com.mapbox.maps.extension.style.layers.generated.SymbolLayer +import com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor +import com.mapbox.maps.extension.style.layers.properties.generated.TextAnchor +import com.mapbox.maps.extension.style.layers.properties.generated.TextJustify +import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource class MapFragment : ScreenFragment("Map"), Logging { @@ -42,22 +40,19 @@ class MapFragment : ScreenFragment("Map"), Logging { private val labelLayerId = "label-layer" private val markerImageId = "my-marker-image" - private val nodePositions = GeoJsonSource(nodeSourceId) + private val nodePositions = GeoJsonSource(GeoJsonSource.Builder(nodeSourceId)) - private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId).withProperties( - iconImage(markerImageId), - iconAnchor(Property.ICON_ANCHOR_BOTTOM), - iconAllowOverlap(true) - ) + private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId) + .iconImage(markerImageId) + .iconAnchor(IconAnchor.BOTTOM) - private val labelLayer = SymbolLayer(labelLayerId, nodeSourceId).withProperties( - textField(Expression.get("name")), - textSize(12f), - textColor(Color.RED), - textVariableAnchor(arrayOf(TEXT_ANCHOR_TOP)), - textJustify(TEXT_JUSTIFY_AUTO), - textAllowOverlap(true) - ) + private val labelLayer = SymbolLayer(labelLayerId, nodeSourceId) + .textField(Expression.get("name")) + .textSize() + .textColor(Color.RED) + .textVariableAnchor(arrayListOf(TextAnchor.TOP.toString())) + .textJustify(TextJustify.AUTO) + .textAllowOverlap(true) private fun onNodesChanged(map: MapboxMap, nodes: Collection) { @@ -89,33 +84,34 @@ class MapFragment : ScreenFragment("Map"), Logging { } - - nodePositions.setGeoJson(getCurrentNodes()) // Update node positions + // nodePositions.setGeoJson(getCurrentNodes()) // Update node positions } fun zoomToNodes(map: MapboxMap) { val nodesWithPosition = model.nodeDB.nodes.value?.values?.filter { it.validPosition != null } if (nodesWithPosition != null && nodesWithPosition.isNotEmpty()) { - val update = if (nodesWithPosition.size >= 2) { - // Multiple nodes, make them all fit on the map view - val bounds = LatLngBounds.Builder() - - // Add all positions - bounds.includes(nodesWithPosition.map { it.position!! } - .map { LatLng(it.latitude, it.longitude) }) - - CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) - } else { - // Only one node, just zoom in on it - val it = nodesWithPosition[0].position!! - - val cameraPos = CameraPosition.Builder().target( - LatLng(it.latitude, it.longitude) - ).zoom(9.0).build() - CameraUpdateFactory.newCameraPosition(cameraPos) - } - map.animateCamera(update, 1000) +// val update = if (nodesWithPosition.size >= 2) { +// // Multiple nodes, make them all fit on the map view +// val bounds = LatLngBounds.Builder() +// +// // Add all positions +// bounds.includes(nodesWithPosition.map { it.position!! } +// .map { LatLng(it.latitude, it.longitude) }) +// +// CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) +// } else { +// // Only one node, just zoom in on it +// val it = nodesWithPosition[0].position!! +// +// val cameraPos = CameraPosition.Builder().target( +// LatLng(it.latitude, it.longitude) +// ).zoom(9.0).build() +// CameraUpdateFactory.newCameraPosition(cameraPos) +// } +// map.animateCamera(update, 1000) +// } +// } } } @@ -141,7 +137,7 @@ class MapFragment : ScreenFragment("Map"), Logging { * Mapbox native code can crash painfully if you ever call a mapbox view function while the view is not actively being show */ private val isViewVisible: Boolean - get() = !(mapView?.isDestroyed ?: true) + get() = mapView?.isVisible == true override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) { super.onViewCreated(viewIn, savedInstanceState) @@ -151,50 +147,44 @@ class MapFragment : ScreenFragment("Map"), Logging { val vIn = viewIn.findViewById(R.id.mapView) mapView = vIn mapView?.let { v -> - v.onCreate(savedInstanceState) // Each time the pane is shown start fetching new map info (we do this here instead of // onCreate because getMapAsync can die in native code if the view goes away) - v.getMapAsync { map -> - - if (view != null) { // it might have gone away by now - // val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24) - val markerIcon = - ContextCompat.getDrawable( - requireActivity(), - R.drawable.ic_twotone_person_pin_24 - )!! - - map.setStyle(Style.OUTDOORS) { style -> - style.addSource(nodePositions) - style.addImage(markerImageId, markerIcon) - style.addLayer(nodeLayer) - style.addLayer(labelLayer) - } - - map.uiSettings.isRotateGesturesEnabled = false - // Provide initial positions - model.nodeDB.nodes.value?.let { nodes -> - onNodesChanged(map, nodes.values) - } - } - // Any times nodes change update our map - model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes -> - if (isViewVisible) - onNodesChanged(map, nodes.values) - }) - zoomToNodes(map) + val map = v.getMapboxMap() + if (view != null) { // it might have gone away by now + // val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24) + val markerIcon = + ContextCompat.getDrawable( + requireActivity(), + R.drawable.ic_twotone_person_pin_24 + )!! + + map.loadStyleUri(Style.OUTDOORS) +// style.addSource(nodePositions) +// style.addImage(markerImageId, markerIcon) +// style.addLayer(nodeLayer) +// style.addLayer(labelLayer) + + + // map.uiSettings.isRotateGesturesEnabled = false + // Provide initial positions + model.nodeDB.nodes.value?.let { nodes -> + onNodesChanged(map, nodes.values) + } } + + // Any times nodes change update our map + model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes -> + if (isViewVisible) + onNodesChanged(map, nodes.values) + }) + zoomToNodes(map) + } } } - override fun onPause() { - mapView?.onPause() - super.onPause() - } - override fun onStart() { super.onStart() mapView?.onStart() @@ -205,11 +195,6 @@ class MapFragment : ScreenFragment("Map"), Logging { super.onStop() } - override fun onResume() { - super.onResume() - mapView?.onResume() - } - override fun onDestroyView() { super.onDestroyView() mapView?.onDestroy() @@ -217,18 +202,18 @@ class MapFragment : ScreenFragment("Map"), Logging { override fun onSaveInstanceState(outState: Bundle) { mapView?.let { - if (!it.isDestroyed) - it.onSaveInstanceState(outState) + super.onSaveInstanceState(outState) } - super.onSaveInstanceState(outState) } override fun onLowMemory() { - mapView?.let { - if (!it.isDestroyed) - it.onLowMemory() - } super.onLowMemory() + mapView?.onLowMemory() + } + + override fun onDestroy() { + super.onDestroy() + mapView?.onDestroy() } } diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml index 608b01154..5dda7c296 100644 --- a/app/src/main/res/layout/map_view.xml +++ b/app/src/main/res/layout/map_view.xml @@ -2,16 +2,17 @@ + android:layout_height="match_parent"> - + android:clickable="true" + android:focusable="true" + mapbox:mapbox_uiScrollGestures="true" + mapbox:mapbox_uiZoomGestures="true"> \ No newline at end of file diff --git a/build.gradle b/build.gradle index c15e31f78..0fe1b0c83 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,6 @@ buildscript { repositories { google() - // jcenter() mavenCentral() } dependencies { @@ -34,30 +33,6 @@ buildscript { } } -allprojects { - repositories { - maven { - // Per https://docs.mapbox.com/android/maps/guides/install/ we now need to signin to download mapbox lib - url 'https://api.mapbox.com/downloads/v2/releases/maven' - authentication { - basic(BasicAuthentication) - } - credentials { - // Do not change the username below. - // This should always be `mapbox` (not your username). - username = 'mapbox' - // Use the secret token you stored in gradle.properties as the password - password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: "" - } - } - google() - mavenCentral() - // jcenter() - maven { url 'https://jitpack.io' } - //maven { url "https://plugins.gradle.org/m2/" } - } -} - task clean(type: Delete) { delete rootProject.buildDir } diff --git a/settings.gradle b/settings.gradle index 7477052ea..5b7a0b4bd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,29 @@ include ':app' -rootProject.name='Mesh Util' +rootProject.name = 'Mesh Util' include ':geeksville-androidlib' project(':geeksville-androidlib').projectDir = new File('geeksville-androidlib') + + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + repositories { + google() + mavenCentral() + // jcenter() // Warning: this repository is going to shut down soon + maven { + url 'https://api.mapbox.com/downloads/v2/releases/maven' + authentication { + basic(BasicAuthentication) + } + credentials { + // Do not change the username below. + // This should always be `mapbox` (not your username). + username = "mapbox" + // Use the secret token you stored in gradle.properties as the password + password = System.properties["MAPBOX_DOWNLOADS_TOKEN"] + } + } + maven { url 'https://jitpack.io' } + } +} \ No newline at end of file From 7445797d46c17a24ecaf3ee75ef4badb55ce5c21 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 12:32:31 -0500 Subject: [PATCH 02/12] Added TODO in code to point out areas that need work --- .../com/geeksville/mesh/ui/MapFragment.kt | 39 ++++--------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 3d7850dc0..2489500fb 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -45,10 +45,11 @@ class MapFragment : ScreenFragment("Map"), Logging { private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId) .iconImage(markerImageId) .iconAnchor(IconAnchor.BOTTOM) + .iconAllowOverlap(true) private val labelLayer = SymbolLayer(labelLayerId, nodeSourceId) .textField(Expression.get("name")) - .textSize() + .textSize() // TODO Set text size .textColor(Color.RED) .textVariableAnchor(arrayListOf(TextAnchor.TOP.toString())) .textJustify(TextJustify.AUTO) @@ -84,9 +85,11 @@ class MapFragment : ScreenFragment("Map"), Logging { } + //TODO Update node positions // nodePositions.setGeoJson(getCurrentNodes()) // Update node positions } + //TODO Update camera movements fun zoomToNodes(map: MapboxMap) { val nodesWithPosition = model.nodeDB.nodes.value?.values?.filter { it.validPosition != null } @@ -161,13 +164,16 @@ class MapFragment : ScreenFragment("Map"), Logging { )!! map.loadStyleUri(Style.OUTDOORS) + //TODO add layers to current view of map // style.addSource(nodePositions) // style.addImage(markerImageId, markerIcon) // style.addLayer(nodeLayer) // style.addLayer(labelLayer) + //TODO setup gesture controls // map.uiSettings.isRotateGesturesEnabled = false + // Provide initial positions model.nodeDB.nodes.value?.let { nodes -> onNodesChanged(map, nodes.values) @@ -184,37 +190,6 @@ class MapFragment : ScreenFragment("Map"), Logging { } } } - - override fun onStart() { - super.onStart() - mapView?.onStart() - } - - override fun onStop() { - mapView?.onStop() - super.onStop() - } - - override fun onDestroyView() { - super.onDestroyView() - mapView?.onDestroy() - } - - override fun onSaveInstanceState(outState: Bundle) { - mapView?.let { - super.onSaveInstanceState(outState) - } - } - - override fun onLowMemory() { - super.onLowMemory() - mapView?.onLowMemory() - } - - override fun onDestroy() { - super.onDestroy() - mapView?.onDestroy() - } } From ace75f5ec736a96b07a0eb94bd91af0b938dcbd2 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 12:34:07 -0500 Subject: [PATCH 03/12] Updated YML for CI. GSERVICES token is having issues --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index c2ed9158c..09eb3acf5 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -18,7 +18,7 @@ jobs: - name: Load secrets run: | rm ./app/google-services.json - echo $GSERVICES > ./app/google-services.json + cp ./app/google-services-example.json ./app/google-services.json rm ./app/src/main/res/values/mapbox-token.xml echo -e "\n $MAPBOXTOKEN\n" > ./app/src/main/res/values/mapbox-token.xml mkdir -p ~/.gradle From 090c34f4e95bdc44083f4493134b75e35f16578e Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 13:26:08 -0500 Subject: [PATCH 04/12] Added layers to map --- .../com/geeksville/mesh/ui/MapFragment.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 2489500fb..77ccb53fb 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.toBitmap import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer @@ -18,16 +19,16 @@ import com.geeksville.util.formatAgo import com.mapbox.geojson.Feature import com.mapbox.geojson.FeatureCollection import com.mapbox.geojson.Point -import com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap import com.mapbox.maps.MapView -import com.mapbox.maps.CameraOptions import com.mapbox.maps.MapboxMap import com.mapbox.maps.Style import com.mapbox.maps.extension.style.expressions.generated.Expression +import com.mapbox.maps.extension.style.layers.addLayer import com.mapbox.maps.extension.style.layers.generated.SymbolLayer import com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor import com.mapbox.maps.extension.style.layers.properties.generated.TextAnchor import com.mapbox.maps.extension.style.layers.properties.generated.TextJustify +import com.mapbox.maps.extension.style.sources.addSource import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource @@ -49,9 +50,10 @@ class MapFragment : ScreenFragment("Map"), Logging { private val labelLayer = SymbolLayer(labelLayerId, nodeSourceId) .textField(Expression.get("name")) - .textSize() // TODO Set text size + .textSize(12.0) .textColor(Color.RED) - .textVariableAnchor(arrayListOf(TextAnchor.TOP.toString())) + .textAnchor(TextAnchor.TOP) + //.textVariableAnchor(TextAnchor.TOP) //TODO investigate need for variable anchor vs normal anchor .textJustify(TextJustify.AUTO) .textAllowOverlap(true) @@ -156,20 +158,18 @@ class MapFragment : ScreenFragment("Map"), Logging { val map = v.getMapboxMap() if (view != null) { // it might have gone away by now - // val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24) val markerIcon = ContextCompat.getDrawable( requireActivity(), R.drawable.ic_twotone_person_pin_24 - )!! - - map.loadStyleUri(Style.OUTDOORS) - //TODO add layers to current view of map -// style.addSource(nodePositions) -// style.addImage(markerImageId, markerIcon) -// style.addLayer(nodeLayer) -// style.addLayer(labelLayer) + )!!.toBitmap() + map.loadStyleUri(Style.OUTDOORS) { + it.addSource(nodePositions) + it.addImage(markerImageId, markerIcon) + it.addLayer(nodeLayer) + it.addLayer(labelLayer) + } //TODO setup gesture controls // map.uiSettings.isRotateGesturesEnabled = false From 3a06bd04786a75bb668a96943a37ef8d96d43121 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 16:44:39 -0500 Subject: [PATCH 05/12] Added layers to map, got gestures working --- .../com/geeksville/mesh/ui/MapFragment.kt | 15 ++++++++------ app/src/main/res/layout/map_view.xml | 20 ++++++------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 77ccb53fb..8544a8db8 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -30,6 +30,7 @@ import com.mapbox.maps.extension.style.layers.properties.generated.TextAnchor import com.mapbox.maps.extension.style.layers.properties.generated.TextJustify import com.mapbox.maps.extension.style.sources.addSource import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource +import com.mapbox.maps.plugin.gestures.gestures class MapFragment : ScreenFragment("Map"), Logging { @@ -165,14 +166,16 @@ class MapFragment : ScreenFragment("Map"), Logging { )!!.toBitmap() map.loadStyleUri(Style.OUTDOORS) { - it.addSource(nodePositions) - it.addImage(markerImageId, markerIcon) - it.addLayer(nodeLayer) - it.addLayer(labelLayer) + if (it.isStyleLoaded) { + it.addSource(nodePositions) + it.addImage(markerImageId, markerIcon) + it.addLayer(nodeLayer) + it.addLayer(labelLayer) + } + } - //TODO setup gesture controls - // map.uiSettings.isRotateGesturesEnabled = false + v.gestures.rotateEnabled = false // Provide initial positions model.nodeDB.nodes.value?.let { nodes -> diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml index 5dda7c296..f65e5453e 100644 --- a/app/src/main/res/layout/map_view.xml +++ b/app/src/main/res/layout/map_view.xml @@ -1,18 +1,10 @@ - - - - - \ No newline at end of file + android:layout_height="match_parent" + mapbox:mapbox_cameraTargetLat="40.7128" + mapbox:mapbox_cameraTargetLng="-74.0060" + mapbox:mapbox_cameraZoom="9.0" /> \ No newline at end of file From d199b5437d869ba97f291d2e589914c06ab35c6a Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 20:21:42 -0500 Subject: [PATCH 06/12] Got nodes to render on map --- .../com/geeksville/mesh/ui/MapFragment.kt | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 8544a8db8..3354a3346 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -19,9 +19,8 @@ import com.geeksville.util.formatAgo import com.mapbox.geojson.Feature import com.mapbox.geojson.FeatureCollection import com.mapbox.geojson.Point -import com.mapbox.maps.MapView -import com.mapbox.maps.MapboxMap -import com.mapbox.maps.Style +import com.mapbox.mapboxsdk.Mapbox +import com.mapbox.maps.* import com.mapbox.maps.extension.style.expressions.generated.Expression import com.mapbox.maps.extension.style.layers.addLayer import com.mapbox.maps.extension.style.layers.generated.SymbolLayer @@ -30,6 +29,8 @@ import com.mapbox.maps.extension.style.layers.properties.generated.TextAnchor import com.mapbox.maps.extension.style.layers.properties.generated.TextJustify import com.mapbox.maps.extension.style.sources.addSource import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource +import com.mapbox.maps.plugin.animation.MapAnimationOptions +import com.mapbox.maps.plugin.animation.easeTo import com.mapbox.maps.plugin.gestures.gestures @@ -42,7 +43,7 @@ class MapFragment : ScreenFragment("Map"), Logging { private val labelLayerId = "label-layer" private val markerImageId = "my-marker-image" - private val nodePositions = GeoJsonSource(GeoJsonSource.Builder(nodeSourceId)) + private var nodePositions = GeoJsonSource(GeoJsonSource.Builder(nodeSourceId)) private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId) .iconImage(markerImageId) @@ -86,10 +87,7 @@ class MapFragment : ScreenFragment("Map"), Logging { return FeatureCollection.fromFeatures(locations) } - - - //TODO Update node positions - // nodePositions.setGeoJson(getCurrentNodes()) // Update node positions + nodePositions.featureCollection(getCurrentNodes()) } //TODO Update camera movements @@ -97,27 +95,27 @@ class MapFragment : ScreenFragment("Map"), Logging { val nodesWithPosition = model.nodeDB.nodes.value?.values?.filter { it.validPosition != null } if (nodesWithPosition != null && nodesWithPosition.isNotEmpty()) { -// val update = if (nodesWithPosition.size >= 2) { -// // Multiple nodes, make them all fit on the map view -// val bounds = LatLngBounds.Builder() -// -// // Add all positions -// bounds.includes(nodesWithPosition.map { it.position!! } -// .map { LatLng(it.latitude, it.longitude) }) -// -// CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) -// } else { -// // Only one node, just zoom in on it -// val it = nodesWithPosition[0].position!! -// -// val cameraPos = CameraPosition.Builder().target( -// LatLng(it.latitude, it.longitude) -// ).zoom(9.0).build() -// CameraUpdateFactory.newCameraPosition(cameraPos) -// } -// map.animateCamera(update, 1000) -// } -// } + val update = if (nodesWithPosition.size >= 2) { + // Multiple nodes, make them all fit on the map view + // val bounds = LatLngBounds.Builder() + + // Add all positions + // bounds.includes(nodesWithPosition.map { it.position!! } + // .map { LatLng(it.latitude, it.longitude) }) + + // CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) + } else { + // Only one node, just zoom in on it + val it = nodesWithPosition[0].position!! + + val cameraPos = CameraOptions.Builder().center( + Point.fromLngLat(it.latitude, it.longitude) + ).zoom(9.0).build() + // mapView?.getMapboxMap()?.setCamera(cameraPos) + } +// map.easeTo(update, MapAnimationOptions.mapAnimationOptions { +// duration(100) +// }) } } @@ -172,7 +170,6 @@ class MapFragment : ScreenFragment("Map"), Logging { it.addLayer(nodeLayer) it.addLayer(labelLayer) } - } v.gestures.rotateEnabled = false @@ -189,7 +186,6 @@ class MapFragment : ScreenFragment("Map"), Logging { onNodesChanged(map, nodes.values) }) zoomToNodes(map) - } } } From 9d5066bf9d4d855c275f51e2190347c9813a1dd7 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 21:11:53 -0500 Subject: [PATCH 07/12] move mapbox auth back to build gradle --- app/build.gradle | 6 +++--- build.gradle | 24 ++++++++++++++++++++++++ settings.gradle | 26 +------------------------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 316d6f1c4..813d00ff2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,9 +127,6 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.fragment:fragment-ktx:1.4.0' - implementation('com.mapbox.maps:android:10.2.0') { - exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-telemetry' - } implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.3' @@ -169,6 +166,9 @@ dependencies { // mapbox implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.7.1' + implementation('com.mapbox.maps:android:10.2.0') { + exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-telemetry' + } // mapbox specifies a really old version of okhttp3 which causes lots of API warnings. trying a newer version implementation 'com.squareup.okhttp3:okhttp:4.9.0' diff --git a/build.gradle b/build.gradle index 0fe1b0c83..c46b6bd70 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,30 @@ buildscript { } } +allprojects { + repositories { + maven { + // Per https://docs.mapbox.com/android/maps/guides/install/ we now need to signin to download mapbox lib + url 'https://api.mapbox.com/downloads/v2/releases/maven' + authentication { + basic(BasicAuthentication) + } + credentials { + // Do not change the username below. + // This should always be `mapbox` (not your username). + username = 'mapbox' + // Use the secret token you stored in gradle.properties as the password + password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: "" + } + } + google() + mavenCentral() + // jcenter() + maven { url 'https://jitpack.io' } + //maven { url "https://plugins.gradle.org/m2/" } + } +} + task clean(type: Delete) { delete rootProject.buildDir } diff --git a/settings.gradle b/settings.gradle index 5b7a0b4bd..7477052ea 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,29 +1,5 @@ include ':app' -rootProject.name = 'Mesh Util' +rootProject.name='Mesh Util' include ':geeksville-androidlib' project(':geeksville-androidlib').projectDir = new File('geeksville-androidlib') - - -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) - repositories { - google() - mavenCentral() - // jcenter() // Warning: this repository is going to shut down soon - maven { - url 'https://api.mapbox.com/downloads/v2/releases/maven' - authentication { - basic(BasicAuthentication) - } - credentials { - // Do not change the username below. - // This should always be `mapbox` (not your username). - username = "mapbox" - // Use the secret token you stored in gradle.properties as the password - password = System.properties["MAPBOX_DOWNLOADS_TOKEN"] - } - } - maven { url 'https://jitpack.io' } - } -} \ No newline at end of file From 79ef308eacc684e6eb75b5795144043d65251ca3 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 21:30:12 -0500 Subject: [PATCH 08/12] removed default lat/long for map --- app/src/main/res/layout/map_view.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml index f65e5453e..977f1471c 100644 --- a/app/src/main/res/layout/map_view.xml +++ b/app/src/main/res/layout/map_view.xml @@ -5,6 +5,4 @@ android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" - mapbox:mapbox_cameraTargetLat="40.7128" - mapbox:mapbox_cameraTargetLng="-74.0060" mapbox:mapbox_cameraZoom="9.0" /> \ No newline at end of file From 062cad189ed05aad80646c504e4b47fe89a74439 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 22:01:46 -0500 Subject: [PATCH 09/12] Updated camera movement for nodes, Zoomed out map for initial load --- .../com/geeksville/mesh/ui/MapFragment.kt | 38 ++++++++++--------- app/src/main/res/layout/map_view.xml | 2 +- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 3354a3346..9b60ed5c9 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -19,8 +19,8 @@ import com.geeksville.util.formatAgo import com.mapbox.geojson.Feature import com.mapbox.geojson.FeatureCollection import com.mapbox.geojson.Point -import com.mapbox.mapboxsdk.Mapbox import com.mapbox.maps.* +import com.mapbox.maps.dsl.cameraOptions import com.mapbox.maps.extension.style.expressions.generated.Expression import com.mapbox.maps.extension.style.layers.addLayer import com.mapbox.maps.extension.style.layers.generated.SymbolLayer @@ -31,6 +31,7 @@ import com.mapbox.maps.extension.style.sources.addSource import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource import com.mapbox.maps.plugin.animation.MapAnimationOptions import com.mapbox.maps.plugin.animation.easeTo +import com.mapbox.maps.plugin.animation.flyTo import com.mapbox.maps.plugin.gestures.gestures @@ -91,31 +92,34 @@ class MapFragment : ScreenFragment("Map"), Logging { } //TODO Update camera movements - fun zoomToNodes(map: MapboxMap) { + private fun zoomToNodes(map: MapboxMap) { + val points: MutableList = mutableListOf() val nodesWithPosition = model.nodeDB.nodes.value?.values?.filter { it.validPosition != null } if (nodesWithPosition != null && nodesWithPosition.isNotEmpty()) { - val update = if (nodesWithPosition.size >= 2) { - // Multiple nodes, make them all fit on the map view - // val bounds = LatLngBounds.Builder() - - // Add all positions - // bounds.includes(nodesWithPosition.map { it.position!! } - // .map { LatLng(it.latitude, it.longitude) }) + val unit = if (nodesWithPosition.size >= 2) { - // CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) + // Multiple nodes, make them all fit on the map view + for (node in nodesWithPosition) { + val point = + Point.fromLngLat(node.position!!.longitude, node.position!!.latitude) + points.add(point) + } + map.cameraForCoordinates(points) } else { // Only one node, just zoom in on it val it = nodesWithPosition[0].position!! + points.add(Point.fromLngLat(it.longitude, it.latitude)) + map.cameraForCoordinates(points) + cameraOptions { + this.zoom(9.0) + this.center(points[0]) + } - val cameraPos = CameraOptions.Builder().center( - Point.fromLngLat(it.latitude, it.longitude) - ).zoom(9.0).build() - // mapView?.getMapboxMap()?.setCamera(cameraPos) } -// map.easeTo(update, MapAnimationOptions.mapAnimationOptions { -// duration(100) -// }) + map.flyTo( + unit, + MapAnimationOptions.mapAnimationOptions { duration(1000) }) } } diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml index 977f1471c..132cb4ee9 100644 --- a/app/src/main/res/layout/map_view.xml +++ b/app/src/main/res/layout/map_view.xml @@ -5,4 +5,4 @@ android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" - mapbox:mapbox_cameraZoom="9.0" /> \ No newline at end of file + mapbox:mapbox_cameraZoom="0" /> \ No newline at end of file From b5a09d502a7620a35cf491c87125603084ab9386 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 22:03:51 -0500 Subject: [PATCH 10/12] cleaned up code --- .../main/java/com/geeksville/mesh/ui/MapFragment.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 9b60ed5c9..54f63dda8 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -91,7 +91,6 @@ class MapFragment : ScreenFragment("Map"), Logging { nodePositions.featureCollection(getCurrentNodes()) } - //TODO Update camera movements private fun zoomToNodes(map: MapboxMap) { val points: MutableList = mutableListOf() val nodesWithPosition = @@ -100,10 +99,13 @@ class MapFragment : ScreenFragment("Map"), Logging { val unit = if (nodesWithPosition.size >= 2) { // Multiple nodes, make them all fit on the map view - for (node in nodesWithPosition) { - val point = - Point.fromLngLat(node.position!!.longitude, node.position!!.latitude) - points.add(point) + nodesWithPosition.forEach { + points.add( + Point.fromLngLat( + it.position!!.longitude, + it.position!!.latitude + ) + ) } map.cameraForCoordinates(points) } else { @@ -115,7 +117,6 @@ class MapFragment : ScreenFragment("Map"), Logging { this.zoom(9.0) this.center(points[0]) } - } map.flyTo( unit, From f4bfcb85f7badca1ef4c6c7fbe254ba7f6e929e3 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 22:28:14 -0500 Subject: [PATCH 11/12] Removed old dependency of MapBox V9.x.x --- app/build.gradle | 5 +---- .../main/java/com/geeksville/mesh/MeshUtilApplication.kt | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 813d00ff2..05c86b0a7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -165,10 +165,7 @@ dependencies { implementation 'com.github.mik3y:usb-serial-for-android:3.4.3' // mapbox - implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.7.1' - implementation('com.mapbox.maps:android:10.2.0') { - exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-telemetry' - } + implementation('com.mapbox.maps:android:10.2.0') // mapbox specifies a really old version of okhttp3 which causes lots of API warnings. trying a newer version implementation 'com.squareup.okhttp3:okhttp:4.9.0' diff --git a/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt b/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt index e0a9bd87b..bdbb89057 100644 --- a/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt +++ b/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt @@ -7,8 +7,8 @@ import com.geeksville.android.GeeksvilleApplication import com.geeksville.android.Logging import com.geeksville.util.Exceptions import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.mapbox.mapboxsdk.Mapbox - +import com.mapbox.maps.loader.MapboxMaps +import com.mapbox.maps.plugin.Plugin class MeshUtilApplication : GeeksvilleApplication() { @@ -50,7 +50,5 @@ class MeshUtilApplication : GeeksvilleApplication() { sendCrashReports() // Send the new report } } - - Mapbox.getInstance(this, getString(R.string.mapbox_access_token)) } } \ No newline at end of file From 332ef3eb6a74c54497fd42eda892d22a4cd12820 Mon Sep 17 00:00:00 2001 From: Jackson Rosenthal Date: Sat, 5 Feb 2022 22:31:01 -0500 Subject: [PATCH 12/12] removed unused dependencies --- app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt | 2 -- app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt | 1 - 2 files changed, 3 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt b/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt index bdbb89057..af8a643ea 100644 --- a/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt +++ b/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt @@ -7,8 +7,6 @@ import com.geeksville.android.GeeksvilleApplication import com.geeksville.android.Logging import com.geeksville.util.Exceptions import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.mapbox.maps.loader.MapboxMaps -import com.mapbox.maps.plugin.Plugin class MeshUtilApplication : GeeksvilleApplication() { diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 54f63dda8..c3e588fe9 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -30,7 +30,6 @@ import com.mapbox.maps.extension.style.layers.properties.generated.TextJustify import com.mapbox.maps.extension.style.sources.addSource import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource import com.mapbox.maps.plugin.animation.MapAnimationOptions -import com.mapbox.maps.plugin.animation.easeTo import com.mapbox.maps.plugin.animation.flyTo import com.mapbox.maps.plugin.gestures.gestures