diff --git a/app/build.gradle b/app/build.gradle index aa2aefbcd..05c86b0a7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -158,14 +158,14 @@ 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' + 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..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.mapboxsdk.Mapbox - class MeshUtilApplication : GeeksvilleApplication() { @@ -50,7 +48,5 @@ class MeshUtilApplication : GeeksvilleApplication() { sendCrashReports() // Send the new report } } - - Mapbox.getInstance(this, getString(R.string.mapbox_access_token)) } } \ No newline at end of file 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..c3e588fe9 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,8 @@ 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 import com.geeksville.android.GeeksvilleApplication @@ -17,20 +19,19 @@ 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.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 +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 +import com.mapbox.maps.plugin.animation.MapAnimationOptions +import com.mapbox.maps.plugin.animation.flyTo +import com.mapbox.maps.plugin.gestures.gestures class MapFragment : ScreenFragment("Map"), Logging { @@ -42,22 +43,21 @@ class MapFragment : ScreenFragment("Map"), Logging { private val labelLayerId = "label-layer" private val markerImageId = "my-marker-image" - private val nodePositions = GeoJsonSource(nodeSourceId) + private var 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) + .iconAllowOverlap(true) - 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(12.0) + .textColor(Color.RED) + .textAnchor(TextAnchor.TOP) + //.textVariableAnchor(TextAnchor.TOP) //TODO investigate need for variable anchor vs normal anchor + .textJustify(TextJustify.AUTO) + .textAllowOverlap(true) private fun onNodesChanged(map: MapboxMap, nodes: Collection) { @@ -87,35 +87,39 @@ class MapFragment : ScreenFragment("Map"), Logging { return FeatureCollection.fromFeatures(locations) } - - - - nodePositions.setGeoJson(getCurrentNodes()) // Update node positions + nodePositions.featureCollection(getCurrentNodes()) } - 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() + val unit = if (nodesWithPosition.size >= 2) { - // Add all positions - bounds.includes(nodesWithPosition.map { it.position!! } - .map { LatLng(it.latitude, it.longitude) }) - - CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) + // Multiple nodes, make them all fit on the map view + nodesWithPosition.forEach { + points.add( + Point.fromLngLat( + it.position!!.longitude, + it.position!!.latitude + ) + ) + } + map.cameraForCoordinates(points) } 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) + points.add(Point.fromLngLat(it.longitude, it.latitude)) + map.cameraForCoordinates(points) + cameraOptions { + this.zoom(9.0) + this.center(points[0]) + } } - map.animateCamera(update, 1000) + map.flyTo( + unit, + MapAnimationOptions.mapAnimationOptions { duration(1000) }) } } @@ -141,7 +145,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,84 +155,43 @@ 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) + val map = v.getMapboxMap() + if (view != null) { // it might have gone away by now + val markerIcon = + ContextCompat.getDrawable( + requireActivity(), + R.drawable.ic_twotone_person_pin_24 + )!!.toBitmap() + + map.loadStyleUri(Style.OUTDOORS) { + if (it.isStyleLoaded) { + it.addSource(nodePositions) + it.addImage(markerImageId, markerIcon) + it.addLayer(nodeLayer) + it.addLayer(labelLayer) } } - // 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() - } - - override fun onStop() { - mapView?.onStop() - super.onStop() - } - - override fun onResume() { - super.onResume() - mapView?.onResume() - } + v.gestures.rotateEnabled = false - override fun onDestroyView() { - super.onDestroyView() - mapView?.onDestroy() - } - - override fun onSaveInstanceState(outState: Bundle) { - mapView?.let { - if (!it.isDestroyed) - it.onSaveInstanceState(outState) - } - super.onSaveInstanceState(outState) - } + // Provide initial positions + model.nodeDB.nodes.value?.let { nodes -> + onNodesChanged(map, nodes.values) + } + } - override fun onLowMemory() { - mapView?.let { - if (!it.isDestroyed) - it.onLowMemory() + // Any times nodes change update our map + model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes -> + if (isViewVisible) + onNodesChanged(map, nodes.values) + }) + zoomToNodes(map) + } } - super.onLowMemory() } } diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml index 608b01154..132cb4ee9 100644 --- a/app/src/main/res/layout/map_view.xml +++ b/app/src/main/res/layout/map_view.xml @@ -1,17 +1,8 @@ - - - - - \ No newline at end of file + mapbox:mapbox_cameraZoom="0" /> \ No newline at end of file diff --git a/build.gradle b/build.gradle index c15e31f78..c46b6bd70 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,6 @@ buildscript { repositories { google() - // jcenter() mavenCentral() } dependencies {